/** * Validates RSA public and private key. * * @param keyPair the keypair * @return true if keys matches */ public static boolean validateKeyPair(KeyPair keyPair) { RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); if (publicKey.getModulus().bitLength() != privateKey.getModulus().bitLength()) { LOG.error("Keypair length matching error"); return false; } byte[] rawPayload = new byte[64]; new Random().nextBytes(rawPayload); MessageEncoderDecoder encDec = new MessageEncoderDecoder(privateKey, publicKey); byte[] encodedPayload; byte[] decodedPayload; try { encodedPayload = encDec.encodeData(rawPayload); decodedPayload = encDec.decodeData(encodedPayload); } catch (GeneralSecurityException ex) { LOG.error("Validation keypair error ", ex); return false; } return Arrays.equals(rawPayload, decodedPayload); }
throws GeneralSecurityException { if (body != null && messageEncDec != null) { byte[] requestKeyEncoded = messageEncDec.getEncodedSessionKey(); byte[] requestBodyEncoded = messageEncDec.encodeData(body); byte[] signature = null; if (sign) { signature = messageEncDec.sign(requestKeyEncoded); if (sign) { LOG.trace("Signature size: {}", signature.length); LOG.trace(MessageEncoderDecoder.bytesToHex(signature)); LOG.trace(MessageEncoderDecoder.bytesToHex(requestKeyEncoded)); LOG.trace("RequestBodyEncoded size: {}", requestBodyEncoded.length); LOG.trace(MessageEncoderDecoder.bytesToHex(requestBodyEncoded));
protected byte[] verifyResponse(byte[] body, byte[] signature) throws GeneralSecurityException { if (!verificationEnabled || messageEncDec.verify(body, signature)) { return body; } else { throw new SecurityException("message can't be verified"); } }
/** * Decode data using session key then is decoded using private key. * * @param message the message * @param encodedKey the encoded key * @return the byte[] * @throws GeneralSecurityException the general security exception */ public byte[] decodeData(byte[] message, byte[] encodedKey) throws GeneralSecurityException { sessionCipherPair = null; decodeSessionKey(encodedKey); return decodeData(message); }
@Test public void basicTest() throws Exception { String message = "secret" + new Random().nextInt(); MessageEncoderDecoder client = new MessageEncoderDecoder(clientPrivate, clientPublic, serverPublic); MessageEncoderDecoder server = new MessageEncoderDecoder(serverPrivate, serverPublic, clientPublic); MessageEncoderDecoder thief = new MessageEncoderDecoder(theifPrivate, theifPublic, clientPublic); byte[] secretData = client.encodeData(message.getBytes()); byte[] signature = client.sign(secretData); byte[] encodedSessionKey = client.getEncodedSessionKey(); Assert.assertTrue(server.verify(secretData, signature)); String decodedSecret = new String(server.decodeData(secretData, encodedSessionKey)); Assert.assertEquals(message, decodedSecret); byte[] theifData = thief.encodeData(message.getBytes()); byte[] theifSignature = thief.sign(theifData); Assert.assertFalse(server.verify(theifData, theifSignature)); }
KeyPair clientPair = KeyUtil.generateKeyPair(); KeyPair serverPair = KeyUtil.generateKeyPair(); MessageEncoderDecoder crypt = new MessageEncoderDecoder(clientPair.getPrivate(), clientPair.getPublic(), serverPair.getPublic()); AvroByteArrayConverter<org.kaaproject.kaa.common.endpoint.gen.SyncRequest> requestConverter = new AvroByteArrayConverter<>(org.kaaproject.kaa.common.endpoint.gen.SyncRequest.class); org.kaaproject.kaa.common.endpoint.gen.SyncRequest request = new org.kaaproject.kaa.common.endpoint.gen.SyncRequest(); final byte[] payload = crypt.encodeData(rawData); final byte[] sessionKey = crypt.getEncodedSessionKey(); final byte[] signature = crypt.sign(sessionKey);
@Test public void testSignature() throws NoSuchAlgorithmException, GeneralSecurityException { KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(512); KeyPair clientKeyPair = gen.generateKeyPair(); KeyPair remoteKeyPair = gen.generateKeyPair(); TestHttpClient client = new TestHttpClient("test_url", clientKeyPair.getPrivate() , clientKeyPair.getPublic(), remoteKeyPair.getPublic()); MessageEncoderDecoder serverEncoder = new MessageEncoderDecoder( remoteKeyPair.getPrivate(), remoteKeyPair.getPublic()); byte[] message = {1, 2, 3}; byte[] signature = serverEncoder.sign(message); Assert.assertArrayEquals(message, client.verifyResponse(message, signature)); Assert.assertTrue(client.getEncoderDecoder().verify(message, signature)); }
private ClientSync decodeEncryptedRequest(SessionInitMessage message) throws GeneralSecurityException, PlatformEncDecException { byte[] requestRaw = crypt.decodeData( message.getEncodedMessageData(), message.getEncodedSessionKey()); LOG.trace("Request data decrypted"); ClientSync request = decodePlatformLevelData(message.getPlatformId(), requestRaw); LOG.trace("Request data deserialized"); PublicKey endpointKey = getPublicKey(request); if (endpointKey == null) { LOG.warn("Endpoint Key is null"); throw new GeneralSecurityException("Endpoint Key is null"); } else { LOG.trace("Public key extracted"); } crypt.setRemotePublicKey(endpointKey); if (crypt.verify(message.getEncodedSessionKey(), message.getSessionKeySignature())) { LOG.trace("Request data verified"); } else { LOG.warn("Request data verification failed"); throw new GeneralSecurityException("Request data verification failed"); } return request; }
@Override public void onResponse(byte[] response) { LOG.debug("Response for channel [{}] received", getId()); byte[] decodedResponse; try { processingResponse = true; synchronized (httpClientLock) { decodedResponse = httpClient.getEncoderDecoder().decodeData(response); } demultiplexer.processResponse(decodedResponse); processingResponse = false; failoverManager.onServerConnected(currentServer); } catch (Exception ex) { LOG.error("Failed to process response {}", Arrays.toString(response)); LOG.error("Exception stack trace: ", ex); } }
private void sendConnect() throws Exception { LOG.debug("Sending Connect to channel [{}]", getId()); byte[] body = multiplexer.compileRequest(getSupportedTransportTypes()); byte[] requestBodyEncoded = encDec.encodeData(body); byte[] sessionKey = encDec.getEncodedSessionKey(); byte[] signature = encDec.sign(sessionKey); sendFrame(new Connect(CHANNEL_TIMEOUT, Constants.KAA_PLATFORM_PROTOCOL_AVRO_ID_V2, sessionKey, requestBodyEncoded, signature)); }
@Test public void basicUpdateTest() throws Exception { MessageEncoderDecoder client = new MessageEncoderDecoder(clientPrivate, clientPublic, serverPublic); Assert.assertNotNull(client.getPublicKey()); Assert.assertNotNull(client.getPrivateKey()); Assert.assertNotNull(client.getRemotePublicKey()); byte[] remoteKey = client.getRemotePublicKey().getEncoded(); client.setRemotePublicKey(serverPublic); Assert.assertTrue(Arrays.equals(remoteKey, client.getRemotePublicKey().getEncoded())); client.setRemotePublicKey(serverPublic.getEncoded()); Assert.assertTrue(Arrays.equals(remoteKey, client.getRemotePublicKey().getEncoded())); client.setRemotePublicKey(theifPublic.getEncoded()); Assert.assertFalse(Arrays.equals(remoteKey, client.getRemotePublicKey().getEncoded())); }
/** * Sets the remote public key. * * @param remotePublicKey the new remote public key * @throws GeneralSecurityException the general security exception */ public void setRemotePublicKey(PublicKey remotePublicKey) throws GeneralSecurityException { this.remotePublicKey = remotePublicKey; if (LOG.isTraceEnabled()) { LOG.trace("RemotePublicKey {}", this.remotePublicKey != null ? bytesToHex(this.remotePublicKey.getEncoded()) : "empty"); } }
public AbstractHttpClient(String url, PrivateKey privateKey, PublicKey publicKey, PublicKey remotePublicKey) { this.url = url; this.messageEncDec = new MessageEncoderDecoder(privateKey, publicKey, remotePublicKey); }
private void encodeAndForward(final SessionInitMessage message, MessageEncoderDecoder crypt, Map<Integer, PlatformEncDec> platformEncDecMap, ServerSync response) throws PlatformEncDecException, GeneralSecurityException { MessageBuilder converter = message.getMessageBuilder(); byte[] responseData = encodePlatformLevelData( platformEncDecMap, message.getPlatformId(), response); Object[] objects; if (message.isEncrypted()) { byte[] responseSignature = crypt.sign(responseData); responseData = crypt.encodeData(responseData); LOG.trace("Response signature {}", responseSignature); LOG.trace("Response data {}", responseData); objects = converter.build(responseData, responseSignature, message.isEncrypted()); } else { LOG.trace("Response data {}", responseData); objects = converter.build(responseData, message.isEncrypted()); } ChannelContext context = message.getChannelContext(); if (objects != null && objects.length > 0) { for (Object object : objects) { context.write(object); } context.flush(); } }
private ClientSync decodeEncryptedRequest(SessionAwareMessage message) throws GeneralSecurityException, PlatformEncDecException { SessionInfo session = message.getSessionInfo(); crypt.setSessionCipherPair(session.getCipherPair()); byte[] requestRaw = crypt.decodeData(message.getEncodedMessageData()); LOG.trace("Request data decrypted"); ClientSync request = decodePlatformLevelData(message.getPlatformId(), requestRaw); LOG.trace("Request data deserialized"); return request; }
private void processSessionResponse(SessionResponse message) throws GeneralSecurityException, PlatformEncDecException { SessionInfo session = message.getSessionInfo(); byte[] responseData = encodePlatformLevelData(message.getPlatformId(), message); LOG.trace("Response data serialized"); if (session.isEncrypted()) { crypt.setSessionCipherPair(session.getCipherPair()); responseData = crypt.encodeData(responseData); LOG.trace("Response data crypted"); } ChannelContext context = message.getSessionInfo().getCtx(); MessageBuilder converter = message.getMessageBuilder(); Object[] objects = converter.build(responseData, session.isEncrypted()); if (objects != null && objects.length > 0) { for (Object object : objects) { context.write(object); } context.flush(); } }
private void sendKaaSyncRequest(Map<TransportType, ChannelDirection> types) throws Exception { LOG.debug("Sending KaaSync from channel [{}]", getId()); byte[] body = multiplexer.compileRequest(types); byte[] requestBodyEncoded = encDec.encodeData(body); sendFrame(new SyncRequest(requestBodyEncoded, false, true)); }
@Override protected Cipher initialValue() { return cipherForAlgorithm(RSA); } };
@Override protected KeyGenerator initialValue() { return keyGeneratorForAlgorithm(SESSION_KEY_ALGORITHM, SESSION_KEY_SIZE); } };
@Test public void basicSubsequentTest() throws Exception { String message = "secret" + new Random().nextInt(); PrivateKey client2Private = theifPrivate; PublicKey client2Public = theifPublic; MessageEncoderDecoder client = new MessageEncoderDecoder(clientPrivate, clientPublic, serverPublic); MessageEncoderDecoder client2 = new MessageEncoderDecoder(client2Private, client2Public, serverPublic); MessageEncoderDecoder server = new MessageEncoderDecoder(serverPrivate, serverPublic); byte[] secretData = client.encodeData(message.getBytes()); byte[] signature = client.sign(secretData); byte[] encodedSessionKey = client.getEncodedSessionKey(); server.setRemotePublicKey(clientPublic); Assert.assertTrue(server.verify(secretData, signature)); String decodedSecret = new String(server.decodeData(secretData, encodedSessionKey)); Assert.assertEquals(message, decodedSecret); byte[] secretData2 = client2.encodeData(message.getBytes()); byte[] signature2 = client2.sign(secretData2); byte[] encodedSessionKey2 = client2.getEncodedSessionKey(); server.setRemotePublicKey(client2Public); Assert.assertTrue(server.verify(secretData2, signature2)); String decodedSecret2 = new String(server.decodeData(secretData2, encodedSessionKey2)); Assert.assertEquals(message, decodedSecret2); }