Description
HmacSecretKey.generateKey(hash) produces different default key lengths on native and browser backends.
When length is omitted, Web Crypto requires the recommended HMAC key length to be the block size of the selected hash function. The browser backend delegates this choice to SubtleCrypto.generateKey and follows that rule, but the FFI backend uses EVP_MD_size, which is the digest size rather than the block size.
This gives the following results:
| Hash |
FFI backend |
Web Crypto / browser |
| SHA-1 |
160 bits |
512 bits |
| SHA-256 |
256 bits |
512 bits |
| SHA-384 |
384 bits |
1024 bits |
| SHA-512 |
512 bits |
1024 bits |
The public documentation currently describes the FFI behavior, so it also differs from Web Crypto's definition.
Reproduction
import 'package:webcrypto/webcrypto.dart';
Future<void> main() async {
for (final entry in <String, Hash>{
'SHA-1': Hash.sha1,
'SHA-256': Hash.sha256,
'SHA-384': Hash.sha384,
'SHA-512': Hash.sha512,
}.entries) {
final key = await HmacSecretKey.generateKey(entry.value);
final raw = await key.exportRawKey();
print('${entry.key}: ${raw.length * 8} bits');
}
}
On the FFI backend this prints:
SHA-1: 160 bits
SHA-256: 256 bits
SHA-384: 384 bits
SHA-512: 512 bits
Expected behavior
Omitting length should generate a key whose length equals the hash function's block size:
- 512 bits for SHA-1 and SHA-256
- 1024 bits for SHA-384 and SHA-512
An explicitly supplied length should continue to take precedence unchanged.
This matches the HMAC key generation algorithm in the Web Cryptography specification:
https://www.w3.org/TR/WebCryptoAPI/#hmac-operations
Actual behavior
The FFI implementation defaults to:
length ??= ssl.EVP_MD_size(h._md) * 8;
EVP_MD_size returns the digest size, causing native-generated keys to be shorter than browser-generated keys for every supported hash.
Suggested fix
- Represent the HMAC default block size for each supported hash in the native implementation.
- Use it only when
length is omitted.
- Correct the
HmacSecretKey.generateKey documentation.
- Add regression coverage for all supported hashes and for an explicit length.
Description
HmacSecretKey.generateKey(hash)produces different default key lengths on native and browser backends.When
lengthis omitted, Web Crypto requires the recommended HMAC key length to be the block size of the selected hash function. The browser backend delegates this choice toSubtleCrypto.generateKeyand follows that rule, but the FFI backend usesEVP_MD_size, which is the digest size rather than the block size.This gives the following results:
The public documentation currently describes the FFI behavior, so it also differs from Web Crypto's definition.
Reproduction
On the FFI backend this prints:
Expected behavior
Omitting
lengthshould generate a key whose length equals the hash function's block size:An explicitly supplied
lengthshould continue to take precedence unchanged.This matches the HMAC key generation algorithm in the Web Cryptography specification:
https://www.w3.org/TR/WebCryptoAPI/#hmac-operations
Actual behavior
The FFI implementation defaults to:
EVP_MD_sizereturns the digest size, causing native-generated keys to be shorter than browser-generated keys for every supported hash.Suggested fix
lengthis omitted.HmacSecretKey.generateKeydocumentation.