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/protobuf/schema.pb.dart'; | ||||||
|  | import 'package:omemo_dart/src/crypto.dart'; | ||||||
| import 'package:omemo_dart/src/errors.dart'; | import 'package:omemo_dart/src/errors.dart'; | ||||||
| import 'package:omemo_dart/src/helpers.dart'; | import 'package:omemo_dart/src/helpers.dart'; | ||||||
| 
 | 
 | ||||||
| /// Info string for ENCRYPT | /// Info string for ENCRYPT | ||||||
| const encryptHkdfInfoString = 'OMEMO Message Key Material'; | 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. | /// Signals ENCRYPT function as specified by OMEMO 0.8.3. | ||||||
| /// Encrypt [plaintext] using the message key [mk], given associated_data [associatedData] | /// Encrypt [plaintext] using the message key [mk], given associated_data [associatedData] | ||||||
| /// and the AD output from the X3DH [sessionAd]. | /// 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 { | Future<List<int>> encrypt(List<int> mk, List<int> plaintext, List<int> associatedData, List<int> sessionAd) async { | ||||||
|   final hkdf = Hkdf( |   // Generate encryption, authentication key and IV | ||||||
|     hmac: Hmac(Sha256()), |   final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString); | ||||||
|     outputLength: 80, |   final ciphertext = await aes256CbcEncrypt(plaintext, keys.encryptionKey, keys.iv); | ||||||
|   ); |  | ||||||
|   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, |  | ||||||
|   ); |  | ||||||
|    |    | ||||||
|   final header = OMEMOMessage.fromBuffer(associatedData.sublist(sessionAd.length)) |   final header = OMEMOMessage.fromBuffer(associatedData.sublist(sessionAd.length)) | ||||||
|     ..ciphertext = aesResult.cipherText; |     ..ciphertext = ciphertext; | ||||||
|   final headerBytes = header.writeToBuffer(); |   final headerBytes = header.writeToBuffer(); | ||||||
|   final hmacInput = concat([sessionAd, headerBytes]); |   final hmacInput = concat([sessionAd, headerBytes]); | ||||||
|   final hmacResult = (await Hmac.sha256().calculateMac( |   final hmacResult = await truncatedHmac(hmacInput, keys.authenticationKey); | ||||||
|     hmacInput, |  | ||||||
|     secretKey: SecretKey(authenticationKey), |  | ||||||
|   )).bytes.sublist(0, 16); |  | ||||||
|    |  | ||||||
|   final message = OMEMOAuthenticatedMessage() |   final message = OMEMOAuthenticatedMessage() | ||||||
|     ..mac = hmacResult |     ..mac = hmacResult | ||||||
|     ..message = headerBytes; |     ..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] | /// Decrypt [ciphertext] with the message key [mk], given the associated_data [associatedData] | ||||||
| /// and the AD output from the X3DH. | /// and the AD output from the X3DH. | ||||||
| Future<List<int>> decrypt(List<int> mk, List<int> ciphertext, List<int> associatedData, List<int> sessionAd) async { | Future<List<int>> decrypt(List<int> mk, List<int> ciphertext, List<int> associatedData, List<int> sessionAd) async { | ||||||
|   // Generate the keys and iv from mk |   // Generate encryption, authentication key and IV | ||||||
|   final hkdf = Hkdf( |   final keys = await deriveEncryptionKeys(mk, encryptHkdfInfoString); | ||||||
|     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); |  | ||||||
|    |    | ||||||
|   // Assumption ciphertext is a OMEMOAuthenticatedMessage |   // Assumption ciphertext is a OMEMOAuthenticatedMessage | ||||||
|   final message = OMEMOAuthenticatedMessage.fromBuffer(ciphertext); |   final message = OMEMOAuthenticatedMessage.fromBuffer(ciphertext); | ||||||
|   final header = OMEMOMessage.fromBuffer(message.message); |   final header = OMEMOMessage.fromBuffer(message.message); | ||||||
| 
 | 
 | ||||||
|   final hmacInput = concat([sessionAd, header.writeToBuffer()]); |   final hmacInput = concat([sessionAd, header.writeToBuffer()]); | ||||||
|   final hmacResult = (await Hmac.sha256().calculateMac( |   final hmacResult = await truncatedHmac(hmacInput, keys.authenticationKey); | ||||||
|     hmacInput, |  | ||||||
|     secretKey: SecretKey(authenticationKey), |  | ||||||
|   )).bytes.sublist(0, 16); |  | ||||||
| 
 | 
 | ||||||
|   if (!listsEqual(hmacResult, message.mac)) { |   if (!listsEqual(hmacResult, message.mac)) { | ||||||
|     throw InvalidMessageHMACException(); |     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