fix: Migrate Double Ratchet to the helper functions
This commit is contained in:
parent
4d6dbef549
commit
31d3897995
@ -1,62 +1,24 @@
|
||||
import 'dart:convert';
|
||||
import 'package:cryptography/cryptography.dart';
|
||||
import 'package:omemo_dart/protobuf/schema.pb.dart';
|
||||
import 'package:omemo_dart/src/crypto.dart';
|
||||
import 'package:omemo_dart/src/errors.dart';
|
||||
import 'package:omemo_dart/src/helpers.dart';
|
||||
|
||||
/// Info string for ENCRYPT
|
||||
const encryptHkdfInfoString = 'OMEMO Message Key Material';
|
||||
|
||||
/// cryptography _really_ wants to check the MAC output from AES-256-CBC. Since
|
||||
/// we don't have it, we need the MAC check to always "pass".
|
||||
class NoMacSecretBox extends SecretBox {
|
||||
NoMacSecretBox(super.cipherText, { required super.nonce }) : super(mac: Mac.empty);
|
||||
|
||||
@override
|
||||
Future<void> checkMac({
|
||||
required MacAlgorithm macAlgorithm,
|
||||
required SecretKey secretKey,
|
||||
required List<int> aad,
|
||||
}) async {}
|
||||
}
|
||||
|
||||
/// Signals ENCRYPT function as specified by OMEMO 0.8.3.
|
||||
/// Encrypt [plaintext] using the message key [mk], given associated_data [associatedData]
|
||||
/// and the AD output from the X3DH [sessionAd].
|
||||
Future<List<int>> encrypt(List<int> mk, List<int> plaintext, List<int> associatedData, List<int> sessionAd) async {
|
||||
final hkdf = Hkdf(
|
||||
hmac: Hmac(Sha256()),
|
||||
outputLength: 80,
|
||||
);
|
||||
final hkdfResult = await hkdf.deriveKey(
|
||||
secretKey: SecretKey(mk),
|
||||
nonce: List<int>.filled(32, 0x0),
|
||||
info: utf8.encode(encryptHkdfInfoString),
|
||||
);
|
||||
final hkdfBytes = await hkdfResult.extractBytes();
|
||||
|
||||
// Split hkdfBytes into encryption, authentication key and IV
|
||||
final encryptionKey = hkdfBytes.sublist(0, 32);
|
||||
final authenticationKey = hkdfBytes.sublist(32, 64);
|
||||
final iv = hkdfBytes.sublist(64, 80);
|
||||
|
||||
final aesResult = await AesCbc.with256bits(
|
||||
macAlgorithm: MacAlgorithm.empty,
|
||||
).encrypt(
|
||||
plaintext,
|
||||
secretKey: SecretKey(encryptionKey),
|
||||
nonce: iv,
|
||||
);
|
||||
// Generate encryption, authentication key and IV
|
||||
final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString);
|
||||
final ciphertext = await aes256CbcEncrypt(plaintext, keys.encryptionKey, keys.iv);
|
||||
|
||||
final header = OMEMOMessage.fromBuffer(associatedData.sublist(sessionAd.length))
|
||||
..ciphertext = aesResult.cipherText;
|
||||
..ciphertext = ciphertext;
|
||||
final headerBytes = header.writeToBuffer();
|
||||
final hmacInput = concat([sessionAd, headerBytes]);
|
||||
final hmacResult = (await Hmac.sha256().calculateMac(
|
||||
hmacInput,
|
||||
secretKey: SecretKey(authenticationKey),
|
||||
)).bytes.sublist(0, 16);
|
||||
|
||||
final hmacResult = await truncatedHmac(hmacInput, keys.authenticationKey);
|
||||
final message = OMEMOAuthenticatedMessage()
|
||||
..mac = hmacResult
|
||||
..message = headerBytes;
|
||||
@ -67,46 +29,19 @@ Future<List<int>> encrypt(List<int> mk, List<int> plaintext, List<int> associate
|
||||
/// Decrypt [ciphertext] with the message key [mk], given the associated_data [associatedData]
|
||||
/// and the AD output from the X3DH.
|
||||
Future<List<int>> decrypt(List<int> mk, List<int> ciphertext, List<int> associatedData, List<int> sessionAd) async {
|
||||
// Generate the keys and iv from mk
|
||||
final hkdf = Hkdf(
|
||||
hmac: Hmac(Sha256()),
|
||||
outputLength: 80,
|
||||
);
|
||||
final hkdfResult = await hkdf.deriveKey(
|
||||
secretKey: SecretKey(mk),
|
||||
nonce: List<int>.filled(32, 0x0),
|
||||
info: utf8.encode(encryptHkdfInfoString),
|
||||
);
|
||||
final hkdfBytes = await hkdfResult.extractBytes();
|
||||
|
||||
// Split hkdfBytes into encryption, authentication key and IV
|
||||
final encryptionKey = hkdfBytes.sublist(0, 32);
|
||||
final authenticationKey = hkdfBytes.sublist(32, 64);
|
||||
final iv = hkdfBytes.sublist(64, 80);
|
||||
// Generate encryption, authentication key and IV
|
||||
final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString);
|
||||
|
||||
// Assumption ciphertext is a OMEMOAuthenticatedMessage
|
||||
final message = OMEMOAuthenticatedMessage.fromBuffer(ciphertext);
|
||||
final header = OMEMOMessage.fromBuffer(message.message);
|
||||
|
||||
final hmacInput = concat([sessionAd, header.writeToBuffer()]);
|
||||
final hmacResult = (await Hmac.sha256().calculateMac(
|
||||
hmacInput,
|
||||
secretKey: SecretKey(authenticationKey),
|
||||
)).bytes.sublist(0, 16);
|
||||
final hmacResult = await truncatedHmac(hmacInput, keys.authenticationKey);
|
||||
|
||||
if (!listsEqual(hmacResult, message.mac)) {
|
||||
throw InvalidMessageHMACException();
|
||||
}
|
||||
|
||||
final plaintext = await AesCbc.with256bits(
|
||||
macAlgorithm: MacAlgorithm.empty,
|
||||
).decrypt(
|
||||
NoMacSecretBox(
|
||||
header.ciphertext,
|
||||
nonce: iv,
|
||||
),
|
||||
secretKey: SecretKey(encryptionKey),
|
||||
);
|
||||
|
||||
return plaintext;
|
||||
return aes256CbcDecrypt(header.ciphertext, keys.encryptionKey, keys.iv);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user