use of im.actor.runtime.crypto.IntegrityException in project actor-platform by actorapp.
the class EncryptedSessionChain method decrypt.
public byte[] decrypt(byte[] data) throws IntegrityException {
if (data.length < 88) {
throw new IntegrityException("Data length is too small");
}
//
// Parsing message header
//
final int senderKeyGroupId = ByteStrings.bytesToInt(data, 0);
final long senderEphermalKey0Id = ByteStrings.bytesToLong(data, 4);
final long receiverEphermalKey0Id = ByteStrings.bytesToLong(data, 12);
final byte[] senderEphemeralKey = ByteStrings.substring(data, 20, 32);
final byte[] receiverEphemeralKey = ByteStrings.substring(data, 52, 32);
final int messageIndex = ByteStrings.bytesToInt(data, 84);
//
// Validating header
//
// if (senderKeyGroupId != session.getPeerKeyGroupId()) {
// throw new IntegrityException("Incorrect sender key group id");
// }
// if (senderEphermalKey0Id != session.getTheirPreKey().getKeyId()) {
// throw new IntegrityException("Incorrect sender pre key id");
// }
// if (receiverEphermalKey0Id != session.getOwnPreKey().getKeyId()) {
// throw new IntegrityException("Incorrect receiver pre key id");
// }
// if (ByteStrings.isEquals(senderEphemeralKey, theirPublicKey)) {
// throw new IntegrityException("Incorrect sender ephemeral key");
// }
// if (ByteStrings.isEquals(receiverEphemeralKey, ownPrivateKey)) {
// throw new IntegrityException("Incorrect receiver ephemeral key");
// }
//
// Decryption
//
ActorBoxKey ratchetMessageKey = RatchetMessageKey.buildKey(rootChainKey, messageIndex);
byte[] header = ByteStrings.substring(data, 0, 88);
byte[] message = ByteStrings.substring(data, 88, data.length - 88);
return ActorBox.openBox(header, message, ratchetMessageKey);
}
use of im.actor.runtime.crypto.IntegrityException in project actor-platform by actorapp.
the class ActorBox method openBox.
/**
* Opening Encrypted box
*
* @param header plain-text header of a box
* @param cipherText encrypted content
* @param key Box key
* @return plain-text content
* @throws IntegrityException
*/
public static byte[] openBox(byte[] header, byte[] cipherText, ActorBoxKey key) throws IntegrityException {
CBCHmacBox aesCipher = new CBCHmacBox(Crypto.createAES128(key.getKeyAES()), Crypto.createSHA256(), key.getMacAES());
CBCHmacBox kuzCipher = new CBCHmacBox(new KuznechikFastEngine(key.getKeyKuz()), new Streebog256(), key.getMacKuz());
byte[] kuzPackage = aesCipher.decryptPackage(header, ByteStrings.substring(cipherText, 0, 16), ByteStrings.substring(cipherText, 16, cipherText.length - 16));
byte[] plainText = kuzCipher.decryptPackage(header, ByteStrings.substring(kuzPackage, 0, 16), ByteStrings.substring(kuzPackage, 16, kuzPackage.length - 16));
// Validating padding
int paddingSize = plainText[plainText.length - 1] & 0xFF;
if (paddingSize < 0 || paddingSize >= 16) {
throw new IntegrityException("Incorrect padding!");
}
PKCS7Padding padding = new PKCS7Padding();
if (!padding.validate(plainText, plainText.length - 1 - paddingSize, paddingSize)) {
throw new IntegrityException("Padding does not isMatch!");
}
return ByteStrings.substring(plainText, 0, plainText.length - 1 - paddingSize);
}
use of im.actor.runtime.crypto.IntegrityException in project actor-platform by actorapp.
the class EncryptedPeerActor method doEncrypt.
private Promise<EncryptBoxResponse> doEncrypt(final byte[] data) {
if (!isReady) {
stash();
return null;
}
//
// Stage 1: Loading User Key Groups
// Stage 2: Pick sessions for encryption
// Stage 3: Encrypt box_key int session
// Stage 4: Encrypt box
//
final byte[] encKey = Crypto.randomBytes(32);
final byte[] encKeyExtended = keyPrf.calculate(encKey, "ActorPackage", 128);
Log.d(TAG, "doEncrypt");
final long start = Runtime.getActorTime();
return PromisesArray.of(theirKeys.getUserKeysGroups()).filter(new Predicate<UserKeysGroup>() {
@Override
public boolean apply(UserKeysGroup keysGroup) {
return !ignoredKeyGroups.contains(keysGroup.getKeyGroupId());
}
}).mapOptional(new Function<UserKeysGroup, Promise<SessionActor>>() {
@Override
public Promise<SessionActor> apply(final UserKeysGroup keysGroup) {
if (activeSessions.containsKey(keysGroup.getKeyGroupId())) {
return success(activeSessions.get(keysGroup.getKeyGroupId()).getSessions().get(0));
}
return context().getEncryption().getSessionManagerInt().pickSession(uid, keysGroup.getKeyGroupId()).failure(new Consumer<Exception>() {
@Override
public void apply(Exception e) {
ignoredKeyGroups.add(keysGroup.getKeyGroupId());
}
}).map(new Function<PeerSession, SessionActor>() {
@Override
public SessionActor apply(PeerSession src) {
return spawnSession(src);
}
});
}
}).mapOptional(encrypt(encKeyExtended)).zip().map(new Function<List<EncryptedSessionActor.EncryptedPackageRes>, EncryptBoxResponse>() {
@Override
public EncryptBoxResponse apply(List<EncryptedSessionActor.EncryptedPackageRes> src) {
if (src.size() == 0) {
throw new RuntimeException("No sessions available");
}
Log.d(TAG, "Keys Encrypted in " + (Runtime.getActorTime() - start) + " ms");
ArrayList<EncryptedBoxKey> encryptedKeys = new ArrayList<>();
for (EncryptedSessionActor.EncryptedPackageRes r : src) {
Log.d(TAG, "Keys: " + r.getKeyGroupId());
encryptedKeys.add(new EncryptedBoxKey(uid, r.getKeyGroupId(), "curve25519", r.getData()));
}
byte[] encData;
try {
encData = ActorBox.closeBox(ByteStrings.intToBytes(ownKeyGroupId), data, Crypto.randomBytes(32), new ActorBoxKey(encKeyExtended));
} catch (IntegrityException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
Log.d(TAG, "All Encrypted in " + (Runtime.getActorTime() - start) + " ms");
return new EncryptBoxResponse(new EncryptedBox(encryptedKeys.toArray(new EncryptedBoxKey[encryptedKeys.size()]), ByteStrings.merge(ByteStrings.intToBytes(ownKeyGroupId), encData)));
}
});
}
Aggregations