In my Flutter App I need to decrypt a secure token from the Modulr API. First I need to generate a RSA key and Modulr will use it to generate a secure token.
When the token is generated I receive a encryptedSymmetricKey, a initialisationVector (iv) and a token I need to decrypt.
The encryptedSymmetricKey is encoded using RSA ECB cipher with OAEP and with a hash SHA-256.
Then with the decrypted encryptedSymmetricKey I can decrypt the token encoded with a AES GCM cipher with no padding.
I'm using the pointycastle package.
This is my code:
/// DECRYPT SYMMETRIC KEY
final p = OAEPEncoding.withSHA256(RSAEngine());
p.init(false, PrivateKeyParameter<RSAPrivateKey>(modulrKey.keypair.privateKey.asPointyCastle));
final decryptedSymetricKeyBytes = p.process(base64Decode(result.encryptedSymmetricKey));
/// AES-GCM ALGO
final algo = AesGcm.with128bits();
/// DECODE INIT VECTOR
final decodedIv = base64Decode(result.initialisationVector);
/// AES KEY
final aesKey = await algo.newSecretKeyFromBytes(decryptedSymetricKeyBytes);
/// DECRYPT TOKEN
final decodedToken = base64Decode(result.token);
final secretBox = SecretBox(decodedToken, nonce: decodedIv, mac: Mac.empty);
final decryptedTokenBytes = await algo.decrypt(secretBox, secretKey: aesKey);
final decryptedToken = base64Encode(decryptedTokenBytes);
But when I execute it I get this error:
SecretBox has wrong message authentication code (MAC)
Any idea how I can resolve this error??
Additionally, this is the Modlur documentation: https://modulr.readme.io/docs/retrieve-secure-card-details
The linked JavaScript and Java code show that decodedToken is the concatenation of the actual ciphertext and the 16 bytes GCM tag. However, since the cryptography package used in the Dart code processes the ciphertext and the tag independently, both portions must first be separated. Then they can be passed to SecretBox. The decrypted data must be UTF-8 decoded.
A possible fix is:
import 'dart:convert';
import 'package:cryptography/cryptography.dart';
...
// Separate ciphertext and tag
final decodedToken = base64Decode(result.token);
final token = decodedToken.sublist(0, decodedToken.length - 16);
final tag = decodedToken.sublist(decodedToken.length - 16);
...
// Apply ciphertext and tag
final secretBox = SecretBox(token, nonce: decodedIv, mac: Mac(tag));
...
// Utf-8 decode
final decryptedToken = utf8.decode(decryptedTokenBytes);
With this, the posted Dart code is functionally identical to the linked JavaScript and Java code, respectively.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With