public static String receive( String finalMessageText, ContactModel sender, BinaryTextEncoding encoding) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidAlgorithmParameterException, InvalidParameterSpecException, FailedVerificationException, InvalidSessionKeyException { UserModel user = new Select().from(UserModel.class).executeSingle(); Log.d(TAG, "receive - finalMessageText: " + finalMessageText); byte[] finalMessageBytes = encoding.decode(finalMessageText); byte[] integrityPart = Arrays.copyOfRange(finalMessageBytes, 0, INTEGRITY_LENGTH); byte[] intermediateMessage = Arrays.copyOfRange(finalMessageBytes, INTEGRITY_LENGTH, finalMessageBytes.length); Log.d(TAG, "integrityPart: " + encoding.encode(integrityPart)); Log.d(TAG, "intermediateMessage: " + encoding.encode(intermediateMessage)); if (!AsymCrypto.verify(intermediateMessage, integrityPart, sender.getPublicKey())) throw new FailedVerificationException(); byte[] cipheredBody; if (intermediateMessage[0] == 'k') { byte[] cipheredKeyBytes = Arrays.copyOfRange(intermediateMessage, 1, CIPHERED_KEY_LENGTH + 1); cipheredBody = Arrays.copyOfRange( intermediateMessage, CIPHERED_KEY_LENGTH + 1, intermediateMessage.length); Log.d(TAG, "cipheredKeyBytes: " + encoding.encode(cipheredKeyBytes)); byte[] sessionKeyBytes = AsymCrypto.decrypt(cipheredKeyBytes, user.getPrivateKey()); sender.setSessionKey(KeyHelper.bytesToSecretKey(sessionKeyBytes)); sender.save(); } else { cipheredBody = Arrays.copyOfRange(intermediateMessage, 1, intermediateMessage.length); } Log.d(TAG, "cipheredBody: " + encoding.encode(cipheredBody)); if (!sender.hasValidSessionKey()) { throw new InvalidSessionKeyException(); } SecretKey sessionKey = sender.getSessionKey(); byte[] plainBodyBytes = SymCrypto.decrypt(cipheredBody, sessionKey); return new String(plainBodyBytes); }
public static String send(String plainBody, ContactModel destination, BinaryTextEncoding encoding) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException, InvalidAlgorithmParameterException, InvalidParameterSpecException { UserModel user = new Select().from(UserModel.class).executeSingle(); boolean includeSymmetricKey = false; byte[] plainBodyBytes = plainBody.getBytes(); if (!destination.hasValidSessionKey()) { destination.setSessionKey(KeyHelper.generateSymmetricKey()); destination.save(); includeSymmetricKey = true; } SecretKey sessionKey = destination.getSessionKey(); ByteArrayOutputStream messageComposition = new ByteArrayOutputStream(); if (includeSymmetricKey) { messageComposition.write('k'); byte[] cipheredKey = AsymCrypto.encrypt(sessionKey.getEncoded(), destination.getPublicKey()); Log.d(TAG, "cipheredKey: " + encoding.encode(cipheredKey)); messageComposition.write(cipheredKey); } else { messageComposition.write('0'); } byte[] cipheredBody = SymCrypto.encrypt(plainBodyBytes, sessionKey); Log.d(TAG, "cipheredBody: " + encoding.encode(cipheredBody)); messageComposition.write(cipheredBody); byte[] intermediateMessage = messageComposition.toByteArray(); byte[] integrityPart = AsymCrypto.sign(intermediateMessage, user.getPrivateKey()); Log.d(TAG, "intermediateMessage: " + encoding.encode(intermediateMessage)); Log.d(TAG, "integrityPart: " + encoding.encode(integrityPart)); ByteArrayOutputStream finalMessageComposition = new ByteArrayOutputStream(); finalMessageComposition.write(integrityPart); finalMessageComposition.write(intermediateMessage); String finalMessage = encoding.encode(finalMessageComposition.toByteArray()); Log.d(TAG, "send - finalMessage: " + finalMessage); return finalMessage; }