-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate AES-GCM divergence, tag #39
Comments
I'll investigate this. I think that using PaddedBlockCipher for AES-GCM is messing up the encryption. I'm not as sure about the tag length, but my guess is that that can be fixed as well. PaddingAES.none is something I wanted to avoid (runtime-errors are more frequent; lib harder to use) but, as you said, not having it appears to be causing more trouble. |
Okay, I mostly figured this out: Internally, in our fork of PointyCastle, tagSize is represented as macSize:
To conform with the unified BlockCipher interface, we do some things internally: steel_crypt/lib/PointyCastleN/src/impl/base_aead_block_cipher.dart Lines 131 to 181 in fdf3b2c
And then, the actual issue resides here: steel_crypt/lib/src/encoded/aes.dart Line 92 in fdf3b2c
I'm thinking that some serious rearchitecture of AesCrypt is necessary. It just doesn't make sense to abstract GCM and CBC and CTR and ECB in the same method. It creates classes of bugs like this one (which are mostly avoidable). A better way to do this would be: var aes = AesCrypt(key); //Usable for literally anything at this point.
print(aes.gcm.encrypt(inp: 'words', iv: iv, tagLength: tl, aad: aad)); //GCM encrypt.
print(aes.ecb.encrypt(inp: 'words')); //ECB encrypt This bug will be fixed and the new architecture will be implemented in the next commit. |
This sounds excellent - thank you for the quick reply as well! Will this result in a 2.0.4 (beta) release? |
It will, yeah. I can probably have it done by mid-week. |
Sorry to bug you, but any update on this or a timeframe for an initial attempt? |
@Archprogrammer Woah sorry it's been a while. I was wrapped up in this test suite I've been creating. I'll try to have it out by the end of this week. |
Just me nagging again. :) Any progress on this issue? Is there anything I can do to help out? |
Ugh. I'm really sorry about this. I've been wrapped up in some other things professionally which are kind of a time sink. Regardless, I'll try to get this update out today. |
Alright, this feature is actually complete and ready to publish. I'm working on a CMac bug right now; once that's done I'll publish this. |
@Archprogrammer done with the latest commit and published to pub. See example/example.dart to see the new syntax. You can put in |
I'm afraid this doesn't work quite as intended. Testing the new version runs into this problem: macSize is required to be 16 in pointycastle. However - the resulting output looks correct, so it's possible to set the tagSize to 128 bits and just chop off the last 4 bytes to get a 96-bit tag even if this is a bit cumbersome. Without examining the code further, I'd hazard a guess that the easiest way to support a tagLength argument would be to implement it in steel_crypt as a post-encryption step? |
Does the output come out to the correct thing if you truncate the last 32 bits? This is pretty minimal overhead for me to implement, so I think I could probably do this. |
Yes, that is a property of the tag - a shorter tag is a prefix of a longer tag. You can always truncate the tag to the wanted length if you have a longer one and the resulting, shorter tag, will be correct. At least that is how I understand it. |
Cool. I'll publish a hotfix for this in a few hours. |
@Archprogrammer I tried to implement this, but decryption doesn't work: Uint8List encrypt({@required Uint8List inp, @required Uint8List iv, Uint8List aad, int tagLength = 128}) {
dynamic params = (padding == PaddingAES.none)
? AEADParameters(KeyParameter(key), 128, iv, aad)
: PaddedBlockCipherParameters(
AEADParameters(KeyParameter(key), 128, iv, aad), null);
var cipher = (padding == PaddingAES.none)
? GCMBlockCipher(AESFastEngine())
: PaddedBlockCipher('AES/GCM/' + parsePadding(padding));
cipher.init(true, params);
return cipher.process(inp).sublist(0, tagLength ~/ 8);
}
Uint8List decrypt({@required Uint8List enc, @required Uint8List iv, Uint8List aad, int tagLength = 128}) {
dynamic params = (padding == PaddingAES.none)
? AEADParameters(KeyParameter(key), 128, iv, aad)
: PaddedBlockCipherParameters(
AEADParameters(KeyParameter(key), 128, iv, aad), null);
var cipher = (padding == PaddingAES.none)
? GCMBlockCipher(AESFastEngine())
: BlockCipher('AES/GCM/' + parsePadding(padding));
cipher.init(false, params);
return cipher.process(enc);
} This is some code that I'm testing (from GcmSatelliteRaw). It fails during decryption because PointyCastle expects an input length that is a multiple of the block size; I may have to "re-pad" the input, but I'm not sure how to go about that. |
I think it's easier to file this as an issue upstream than to try and deal with it here. It's clear that this is a pointycastle issue, not really one with this library. I'll leave this open as a marker for the upstream issue (which I will file when I get around to it). |
Sounds like a good plan - I can adjust the tag outside of steel_crypt for now since I only need to encrypt at the moment, so this works for me right now. Hopefully this can be solved in PointyCastle soon. Thanks for the help! |
Following up on issue #11
The following code:
Results in the output :
Encrypting the same string (in utf-8) with the same key and the same IV in Firefox using subtle.crypto (but setting tag-length to 96 bits) results in the following byte sequence:
The sequences match for the first 18 bytes after which they diverge - if I understand it correctly, they should be identical (to the shortest length).
Furthermore, as referenced in #11 , an input string of 88 bytes resulted in a 64-bit tag (8 bytes) but this sample code results in a 112-bit tag (14 bytes).
To sum it up - there appears to be two major and one minor problem:
If I can provide any more information or help in any other way, just ask.
The text was updated successfully, but these errors were encountered: