diff --git a/lib/src/webcrypto/webcrypto.ecdh.dart b/lib/src/webcrypto/webcrypto.ecdh.dart index 6a7770c2..bf55f3d5 100644 --- a/lib/src/webcrypto/webcrypto.ecdh.dart +++ b/lib/src/webcrypto/webcrypto.ecdh.dart @@ -206,6 +206,10 @@ final class EcdhPrivateKey { /// two parties. /// /// [length] specifies the length of the derived secret in bits. + /// The maximum length that can be derived depends on the elliptic curve: + /// * [EllipticCurve.p256] can derive up to 256 bits. + /// * [EllipticCurve.p384] can derive up to 384 bits. + /// * [EllipticCurve.p521] can derive up to 528 bits. /// [publicKey] is [EcdhPublicKey] from the other party's ECDH key pair. /// /// Returns a [Uint8List] containing the derived shared secret. diff --git a/test/crypto_subtle_test.dart b/test/crypto_subtle_test.dart index 3c114a08..f02dcee5 100644 --- a/test/crypto_subtle_test.dart +++ b/test/crypto_subtle_test.dart @@ -310,6 +310,73 @@ void main() { ); }); }); + group('ECDH deriveBits', () { + test('P-256 allows maximum deriveBits length', () async { + final aliceKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p256); + final bobKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p256); + + final secret = await aliceKeyPair.privateKey.deriveBits( + 256, + bobKeyPair.publicKey, + ); + + expect(secret.length, equals(32)); + }); + + test('P-256 rejects deriveBits larger than maximum', () async { + final aliceKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p256); + final bobKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p256); + + expect( + aliceKeyPair.privateKey.deriveBits(257, bobKeyPair.publicKey), + throwsA(anyOf(isA(), isA())), + ); + }); + + test('P-384 allows maximum deriveBits length', () async { + final aliceKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p384); + final bobKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p384); + + final secret = await aliceKeyPair.privateKey.deriveBits( + 384, + bobKeyPair.publicKey, + ); + + expect(secret.length, equals(48)); + }); + + test('P-384 rejects deriveBits larger than maximum', () async { + final aliceKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p384); + final bobKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p384); + + expect( + aliceKeyPair.privateKey.deriveBits(385, bobKeyPair.publicKey), + throwsA(anyOf(isA(), isA())), + ); + }); + + test('P-521 allows maximum deriveBits length', () async { + final aliceKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p521); + final bobKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p521); + + final secret = await aliceKeyPair.privateKey.deriveBits( + 528, + bobKeyPair.publicKey, + ); + + expect(secret.length, equals(66)); + }); + + test('P-521 rejects deriveBits larger than maximum', () async { + final aliceKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p521); + final bobKeyPair = await EcdhPrivateKey.generateKey(EllipticCurve.p521); + + expect( + aliceKeyPair.privateKey.deriveBits(529, bobKeyPair.publicKey), + throwsA(anyOf(isA(), isA())), + ); + }); + }); } extension on JSArray {