From 1ff9595825957c7f89ae2ab07a2da59d365e115e Mon Sep 17 00:00:00 2001 From: terrier989 Date: Fri, 21 Nov 2025 20:29:00 +0000 Subject: [PATCH] Add BrowserEd25519 and BrowserX25519 --- .../lib/src/browser/_javascript_bindings.dart | 3 + cryptography/lib/src/browser/aes_cbc.dart | 2 +- cryptography/lib/src/browser/aes_ctr.dart | 2 +- cryptography/lib/src/browser/aes_gcm.dart | 3 +- .../lib/src/browser/browser_cryptography.dart | 32 ++++- ...browser_cryptography_when_not_browser.dart | 6 +- cryptography/lib/src/browser/ed25519.dart | 125 +++++++++++++++++ cryptography/lib/src/browser/pbkdf2.dart | 2 +- cryptography/lib/src/browser/rsa_pss.dart | 2 +- .../lib/src/browser/rsa_ssa_pkcs1v15.dart | 2 +- cryptography/lib/src/browser/x25519.dart | 128 ++++++++++++++++++ .../lib/src/cryptography/algorithms.dart | 21 +-- .../lib/src/cryptography/key_pair_type.dart | 24 ++++ .../lib/src/cryptography/secure_random.dart | 2 +- cryptography/lib/src/dart/ed25519.dart | 18 +-- cryptography/lib/src/dart/x25519.dart | 6 +- .../cryptography_with_seeded_random_test.dart | 18 ++- cryptography_test/lib/algorithms/ed25519.dart | 6 +- 18 files changed, 349 insertions(+), 53 deletions(-) create mode 100644 cryptography/lib/src/browser/ed25519.dart create mode 100644 cryptography/lib/src/browser/x25519.dart diff --git a/cryptography/lib/src/browser/_javascript_bindings.dart b/cryptography/lib/src/browser/_javascript_bindings.dart index 9b8de93a..95caede7 100644 --- a/cryptography/lib/src/browser/_javascript_bindings.dart +++ b/cryptography/lib/src/browser/_javascript_bindings.dart @@ -340,8 +340,11 @@ extension type AlgorithmNameParams._(JSObject jsObject) { @internal extension type CryptoKey._(JSObject _) implements JSObject { external JSObject get algorithm; + external bool get extractable; + external JSAny get type; + external JSObject get usages; } diff --git a/cryptography/lib/src/browser/aes_cbc.dart b/cryptography/lib/src/browser/aes_cbc.dart index c3ed4cc9..7999b087 100644 --- a/cryptography/lib/src/browser/aes_cbc.dart +++ b/cryptography/lib/src/browser/aes_cbc.dart @@ -18,8 +18,8 @@ import 'dart:typed_data'; import 'package:cryptography/cryptography.dart'; -import '_javascript_bindings.dart' show jsUint8ListFrom; import '_javascript_bindings.dart' as web_crypto; +import '_javascript_bindings.dart' show jsUint8ListFrom; import 'browser_secret_key.dart'; /// AES-CBC implementation that uses _Web Cryptography API_ in browsers. diff --git a/cryptography/lib/src/browser/aes_ctr.dart b/cryptography/lib/src/browser/aes_ctr.dart index 8538d223..332c68a5 100644 --- a/cryptography/lib/src/browser/aes_ctr.dart +++ b/cryptography/lib/src/browser/aes_ctr.dart @@ -18,8 +18,8 @@ import 'dart:typed_data'; import 'package:cryptography/cryptography.dart'; -import '_javascript_bindings.dart' show jsUint8ListFrom; import '_javascript_bindings.dart' as web_crypto; +import '_javascript_bindings.dart' show jsUint8ListFrom; import 'browser_secret_key.dart'; /// AES-CTR implementation that uses _Web Cryptography API_ in browsers. diff --git a/cryptography/lib/src/browser/aes_gcm.dart b/cryptography/lib/src/browser/aes_gcm.dart index 869592ba..2e0905e4 100644 --- a/cryptography/lib/src/browser/aes_gcm.dart +++ b/cryptography/lib/src/browser/aes_gcm.dart @@ -14,15 +14,14 @@ import 'dart:js_interop'; import 'dart:js_interop_unsafe'; - import 'dart:math'; import 'dart:typed_data'; import 'package:cryptography/cryptography.dart'; import 'package:cryptography/src/browser/browser_secret_key.dart'; -import '_javascript_bindings.dart' show jsUint8ListFrom; import '_javascript_bindings.dart' as web_crypto; +import '_javascript_bindings.dart' show jsUint8ListFrom; /// AES-GCM implementation that uses _Web Cryptography API_ in browsers. class BrowserAesGcm extends AesGcm implements StreamingCipher { diff --git a/cryptography/lib/src/browser/browser_cryptography.dart b/cryptography/lib/src/browser/browser_cryptography.dart index 91ac7334..59519f35 100644 --- a/cryptography/lib/src/browser/browser_cryptography.dart +++ b/cryptography/lib/src/browser/browser_cryptography.dart @@ -16,8 +16,6 @@ import 'dart:math'; import 'package:cryptography/cryptography.dart'; import 'package:cryptography/dart.dart'; -import 'package:cryptography/src/browser/rsa_pss.dart'; -import 'package:cryptography/src/browser/rsa_ssa_pkcs1v15.dart'; import 'package:meta/meta.dart'; import '_javascript_bindings.dart' show isWebCryptoAvailable; @@ -26,10 +24,14 @@ import 'aes_ctr.dart'; import 'aes_gcm.dart'; import 'ecdh.dart'; import 'ecdsa.dart'; +import 'ed25519.dart'; import 'hash.dart'; import 'hkdf.dart'; import 'hmac.dart'; import 'pbkdf2.dart'; +import 'rsa_pss.dart'; +import 'rsa_ssa_pkcs1v15.dart'; +import 'x25519.dart'; class BrowserCryptography extends DartCryptography { // Documented in browser_cryptography_when_not_browser.dart @@ -42,10 +44,10 @@ class BrowserCryptography extends DartCryptography { static bool isDisabledForTesting = false; // Documented in browser_cryptography_when_not_browser.dart - static bool get isSupported => isWebCryptoAvailable && !isDisabledForTesting; + static bool get isRunningInWasm => (0 as num) is! double; // Documented in browser_cryptography_when_not_browser.dart - static bool get isRunningInWasm => (0 as num) is! double; + static bool get isSupported => isWebCryptoAvailable && !isDisabledForTesting; final Random? _random; @@ -54,6 +56,11 @@ class BrowserCryptography extends DartCryptography { super.random, }) : _random = random; + bool get _isDeterministicTest { + final random = _random; + return random is SecureRandom && !random.isSecure; + } + @override AesCbc aesCbc({ required MacAlgorithm macAlgorithm, @@ -183,6 +190,15 @@ class BrowserCryptography extends DartCryptography { return super.ecdsaP521(hashAlgorithm); } + @override + Ed25519 ed25519() { + final fallback = super.ed25519(); + if (isSupported && !_isDeterministicTest) { + return BrowserEd25519(fallback: fallback); + } + return fallback; + } + @override Hkdf hkdf({required Hmac hmac, required int outputLength}) { if (isSupported) { @@ -324,4 +340,12 @@ class BrowserCryptography extends DartCryptography { BrowserCryptography withRandom(Random? random) { return BrowserCryptography(random: random); } + + @override + X25519 x25519() { + if (isSupported && !_isDeterministicTest) { + return const BrowserX25519(fallback: DartX25519()); + } + return super.x25519(); + } } diff --git a/cryptography/lib/src/browser/browser_cryptography_when_not_browser.dart b/cryptography/lib/src/browser/browser_cryptography_when_not_browser.dart index e0092e48..ac291dda 100644 --- a/cryptography/lib/src/browser/browser_cryptography_when_not_browser.dart +++ b/cryptography/lib/src/browser/browser_cryptography_when_not_browser.dart @@ -66,6 +66,9 @@ class BrowserCryptography extends DartCryptography { @visibleForTesting static bool isDisabledForTesting = false; + /// Whether WASM is used. + static bool get isRunningInWasm => false; + /// Whether Web Cryptography is supported in this platform. /// /// Browsers support Web Cryptography only in @@ -77,9 +80,6 @@ class BrowserCryptography extends DartCryptography { /// always available. static bool get isSupported => false; - /// Whether WASM is used. - static bool get isRunningInWasm => false; - /// Constructs an instance of [BrowserCryptography]. /// /// If [random] is not given, algorithms will use some cryptographically diff --git a/cryptography/lib/src/browser/ed25519.dart b/cryptography/lib/src/browser/ed25519.dart new file mode 100644 index 00000000..ae3a31f2 --- /dev/null +++ b/cryptography/lib/src/browser/ed25519.dart @@ -0,0 +1,125 @@ +// Copyright 2019-2020 Gohilla. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:js_interop'; + +import 'package:cryptography/cryptography.dart'; +import 'package:cryptography/dart.dart'; +import 'package:meta/meta.dart'; + +import '_javascript_bindings.dart' as web_crypto; + +class BrowserEd25519 extends Ed25519 { + static final _jsAlgorithm = web_crypto.AlgorithmNameParams( + name: 'Ed25519'.toJS, + ).jsObject; + + final Ed25519? _fallback; + + @literal + const BrowserEd25519({required Ed25519? fallback}) + : _fallback = fallback, + super.constructor(); + + @override + Future newKeyPair() async { + late web_crypto.Jwk jwk; + try { + final jsCryptoKey = await web_crypto.generateKeyWhenKeyPair( + _jsAlgorithm, true.toJS, ['sign'.toJS, 'verify'.toJS].toJS); + jwk = await web_crypto.exportKeyWhenJwk(jsCryptoKey.privateKey); + } catch (e) { + final fallback = _fallback; + if (fallback != null) { + return fallback.newKeyPair(); + } + throw StateError('$runtimeType.newKeyPair(...) failed: $e'); + } + return SimpleKeyPairData( + web_crypto.base64UrlDecode(jwk.d!.toDart), + publicKey: SimplePublicKey( + web_crypto.base64UrlDecode(jwk.x!.toDart), + type: KeyPairType.ed25519, + ), + type: KeyPairType.ed25519, + ); + } + + @override + Future newKeyPairFromSeed(List seed) { + KeyPairType.ed25519.checkPrivateKeyBytesFormat(seed); + return DartEd25519().newKeyPairFromSeed(seed); + } + + @override + Future sign(List message, {required KeyPair keyPair}) async { + try { + final publicKeyFuture = keyPair.extractPublicKey(); + final keyPairData = await (keyPair as SimpleKeyPair).extract(); + final jsCryptoKey = await web_crypto.importKeyWhenJwk( + web_crypto.Jwk( + kty: 'OKP'.toJS, + crv: 'Ed25519'.toJS, + d: web_crypto.base64UrlEncode(keyPairData.bytes).toJS, + x: web_crypto.base64UrlEncode(keyPairData.publicKey.bytes).toJS, + ), + _jsAlgorithm, + false.toJS, + ['sign'.toJS].toJS, + ); + final signature = await web_crypto.sign( + _jsAlgorithm, + jsCryptoKey, + web_crypto.jsUint8ListFrom(message), + ); + return Signature( + signature, + publicKey: await publicKeyFuture, + ); + } catch (e) { + final fallback = _fallback; + if (fallback != null) { + return fallback.sign(message, keyPair: keyPair); + } + throw StateError('$runtimeType.sign(...) failed: $e'); + } + } + + @override + Future verify(List message, {required Signature signature}) async { + Ed25519.checkSignatureLength(signature.bytes.length); + final simplePublicKey = signature.publicKey as SimplePublicKey; + KeyPairType.ed25519.checkPublicKeyBytesFormat(simplePublicKey.bytes); + try { + final jsPublicKey = await web_crypto.importKeyWhenRaw( + web_crypto.jsUint8ListFrom(simplePublicKey.bytes), + _jsAlgorithm, + true.toJS, + ['verify'.toJS].toJS, + ); + return web_crypto.verify( + _jsAlgorithm, + jsPublicKey, + web_crypto.jsUint8ListFrom(signature.bytes), + web_crypto.jsUint8ListFrom(message), + ); + } catch (e) { + final fallback = _fallback; + if (fallback != null) { + return fallback.verify(message, signature: signature); + } + throw StateError('$runtimeType.verify(...) failed: $e'); + } + } +} diff --git a/cryptography/lib/src/browser/pbkdf2.dart b/cryptography/lib/src/browser/pbkdf2.dart index e8786e29..c205f421 100644 --- a/cryptography/lib/src/browser/pbkdf2.dart +++ b/cryptography/lib/src/browser/pbkdf2.dart @@ -16,8 +16,8 @@ import 'dart:js_interop'; import 'package:cryptography/cryptography.dart'; -import '_javascript_bindings.dart' show jsUint8ListFrom; import '_javascript_bindings.dart' as web_crypto; +import '_javascript_bindings.dart' show jsUint8ListFrom; import 'hmac.dart'; /// PBKDF2 implementation that uses _Web Cryptography API_ in browsers. diff --git a/cryptography/lib/src/browser/rsa_pss.dart b/cryptography/lib/src/browser/rsa_pss.dart index eb5c2e3e..7954125c 100644 --- a/cryptography/lib/src/browser/rsa_pss.dart +++ b/cryptography/lib/src/browser/rsa_pss.dart @@ -18,7 +18,6 @@ import 'dart:typed_data'; import 'package:cryptography/cryptography.dart'; -import '_javascript_bindings.dart' as web_crypto; import '_javascript_bindings.dart' show base64UrlEncode, @@ -26,6 +25,7 @@ import '_javascript_bindings.dart' jsUint8ListFrom, base64UrlDecode, base64UrlDecodeMaybe; +import '_javascript_bindings.dart' as web_crypto; import 'hash.dart'; /// RSA-PSS implementation that uses _Web Cryptography API_ in browsers. diff --git a/cryptography/lib/src/browser/rsa_ssa_pkcs1v15.dart b/cryptography/lib/src/browser/rsa_ssa_pkcs1v15.dart index b54e7b62..daea9c22 100644 --- a/cryptography/lib/src/browser/rsa_ssa_pkcs1v15.dart +++ b/cryptography/lib/src/browser/rsa_ssa_pkcs1v15.dart @@ -17,9 +17,9 @@ import 'dart:math'; import 'package:cryptography/cryptography.dart'; -import '_javascript_bindings.dart' as web_crypto; import '_javascript_bindings.dart' show base64UrlEncode, base64UrlEncodeMaybe, base64UrlDecode; +import '_javascript_bindings.dart' as web_crypto; import 'hash.dart'; /// RSA-SSA-PKCS1v15 implementation that uses _Web Cryptography API_ in browsers. diff --git a/cryptography/lib/src/browser/x25519.dart b/cryptography/lib/src/browser/x25519.dart new file mode 100644 index 00000000..74d9ccf0 --- /dev/null +++ b/cryptography/lib/src/browser/x25519.dart @@ -0,0 +1,128 @@ +// Copyright 2019-2020 Gohilla. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'dart:js_interop'; +import 'dart:typed_data'; + +import 'package:cryptography/cryptography.dart'; +import 'package:cryptography/dart.dart'; +import 'package:meta/meta.dart'; + +import '_javascript_bindings.dart' as web_crypto; + +class BrowserX25519 extends X25519 { + static final _jsAlgorithm = web_crypto.AlgorithmNameParams( + name: 'X25519'.toJS, + ).jsObject; + + final X25519? _fallback; + + @literal + const BrowserX25519({required X25519? fallback}) + : _fallback = fallback, + super.constructor(); + + @override + Future newKeyPair() async { + late web_crypto.Jwk jwk; + try { + final jsCryptoKey = await web_crypto.generateKeyWhenKeyPair( + _jsAlgorithm, true.toJS, ['deriveBits'.toJS].toJS); + jwk = await web_crypto.exportKeyWhenJwk(jsCryptoKey.privateKey); + } catch (e) { + final fallback = _fallback; + if (fallback != null) { + return fallback.newKeyPair(); + } + throw StateError('$runtimeType.newKeyPair(...) failed: $e'); + } + return SimpleKeyPairData( + Uint8List.fromList(web_crypto.base64UrlDecode(jwk.d!.toDart)), + publicKey: SimplePublicKey( + Uint8List.fromList(web_crypto.base64UrlDecode(jwk.x!.toDart)), + type: KeyPairType.x25519, + ), + type: KeyPairType.ed25519, + ); + } + + @override + Future newKeyPairFromSeed(List seed) { + KeyPairType.x25519.checkPrivateKeyBytesFormat(seed); + return DartX25519().newKeyPairFromSeed(seed); + } + + @override + Future sharedSecretKey( + {required KeyPair keyPair, required PublicKey remotePublicKey}) async { + final simplePublicKey = remotePublicKey as SimplePublicKey; + KeyPairType.x25519.checkPublicKeyBytesFormat(simplePublicKey.bytes); + + late web_crypto.CryptoKey jsPrivateKey; + try { + final keyPairData = await (keyPair as SimpleKeyPair).extract(); + KeyPairType.ed25519.checkPrivateKeyBytesFormat(keyPairData.bytes); + jsPrivateKey = await web_crypto.importKeyWhenJwk( + web_crypto.Jwk( + kty: 'OKP'.toJS, + crv: 'X25519'.toJS, + d: web_crypto.base64UrlEncode(keyPairData.bytes).toJS, + x: web_crypto.base64UrlEncode(keyPairData.publicKey.bytes).toJS, + ), + _jsAlgorithm, + false.toJS, + ['deriveBits'.toJS].toJS, + ); + } catch (e) { + final fallback = _fallback; + if (fallback != null) { + return fallback.sharedSecretKey( + keyPair: keyPair, + remotePublicKey: remotePublicKey, + ); + } + throw StateError( + '$runtimeType.sharedSecretKey(...) failed to construct JS private key: $e'); + } + late web_crypto.CryptoKey jsPublicKey; + try { + jsPublicKey = await web_crypto.importKeyWhenJwk( + web_crypto.Jwk( + kty: 'OKP'.toJS, + crv: 'X25519'.toJS, + x: web_crypto.base64UrlEncode(simplePublicKey.bytes).toJS, + ), + _jsAlgorithm, + false.toJS, + [].toJS, + ); + } catch (e) { + throw StateError( + '$runtimeType.sharedSecretKey(...) failed to construct JS public key: $e'); + } + try { + final bytes = await web_crypto.deriveBits( + web_crypto.DeriveParamsWhenPublicKey( + name: 'X25519'.toJS, + public: jsPublicKey, + ).jsObject, + jsPrivateKey, + 256.toJS, + ); + return SecretKey(bytes); + } catch (e) { + throw StateError('$runtimeType.sharedSecretKey(...) failed: $e'); + } + } +} diff --git a/cryptography/lib/src/cryptography/algorithms.dart b/cryptography/lib/src/cryptography/algorithms.dart index 734b817e..0681741c 100644 --- a/cryptography/lib/src/cryptography/algorithms.dart +++ b/cryptography/lib/src/cryptography/algorithms.dart @@ -1208,26 +1208,11 @@ abstract class Ed25519 extends SignatureAlgorithm { @override String toString() => '$runtimeType()'; - static void checkPrivateKeyLength(int length) { - if (length != 32) { - throw ArgumentError( - 'Private key must be 32 bytes (got $length bytes)', - ); - } - } - - static void checkPublicKeyLength(int length) { - if (length != 32) { - throw ArgumentError( - 'Public key must be 32 bytes (got $length bytes)', - ); - } - } - + /// Checks that the signature length is correct. static void checkSignatureLength(int length) { if (length != 64) { - throw ArgumentError( - 'Signature must be 64 bytes (got $length bytes)', + throw StateError( + 'Ed25519 signature must be 64 bytes (got $length bytes)', ); } } diff --git a/cryptography/lib/src/cryptography/key_pair_type.dart b/cryptography/lib/src/cryptography/key_pair_type.dart index d925b592..7e373381 100644 --- a/cryptography/lib/src/cryptography/key_pair_type.dart +++ b/cryptography/lib/src/cryptography/key_pair_type.dart @@ -107,6 +107,30 @@ class KeyPairType { this.webCryptoCurve, }); + void checkPrivateKeyBytesFormat(List bytes) { + final length = bytes.length; + final expectedLength = privateKeyLength; + if (expectedLength != -1 && length != expectedLength) { + throw ArgumentError.value( + length, + 'length', + 'Algorithm $name expects a private key with $expectedLength bytes, but got: $length bytes', + ); + } + } + + void checkPublicKeyBytesFormat(List bytes) { + final length = bytes.length; + final expectedLength = publicKeyLength; + if (expectedLength != -1 && length != expectedLength) { + throw ArgumentError.value( + length, + 'length', + 'Algorithm $name expects a public key with $expectedLength bytes, but got: $length bytes', + ); + } + } + bool isValidKeyPairData(KeyPairData keyPair) => keyPair is S && keyPair.type == this; diff --git a/cryptography/lib/src/cryptography/secure_random.dart b/cryptography/lib/src/cryptography/secure_random.dart index c5cab776..2c7689b9 100644 --- a/cryptography/lib/src/cryptography/secure_random.dart +++ b/cryptography/lib/src/cryptography/secure_random.dart @@ -36,7 +36,7 @@ abstract class SecureRandom implements Random { /// /// Currently this is always [SecureRandom.system]. static final Random defaultRandom = system; - + @Deprecated('Use SecureRandom.defaultRandom instead') static Random get safe => defaultRandom; diff --git a/cryptography/lib/src/dart/ed25519.dart b/cryptography/lib/src/dart/ed25519.dart index 5c89d709..dea79207 100644 --- a/cryptography/lib/src/dart/ed25519.dart +++ b/cryptography/lib/src/dart/ed25519.dart @@ -53,6 +53,7 @@ class DartEd25519 extends Ed25519 { }) async { final keyPairData = (await keyPair.extract()) as SimpleKeyPairData; final privateKeyBytes = keyPairData.bytes; + KeyPairType.ed25519.checkPrivateKeyBytesFormat(privateKeyBytes); // Take SHA512 hash of the private key. final privateKeyHash = await _sha512.hash(privateKeyBytes); @@ -64,6 +65,7 @@ class DartEd25519 extends Ed25519 { Register25519()..setBytes(Uint8List.fromList(privateKeyHashFixed)), Ed25519Point.base, )); + KeyPairType.ed25519.checkPublicKeyBytesFormat(publicKeyBytes); final publicKey = SimplePublicKey( publicKeyBytes, type: KeyPairType.ed25519, @@ -109,20 +111,8 @@ class DartEd25519 extends Ed25519 { // Check that parameters appear valid final publicKeyBytes = (signature.publicKey as SimplePublicKey).bytes; final signatureBytes = signature.bytes; - if (publicKeyBytes.length != 32) { - throw ArgumentError.value( - signature, - 'signature', - 'Invalid public key length', - ); - } - if (signatureBytes.length != 64) { - throw ArgumentError.value( - signature, - 'signature', - 'Invalid signature length', - ); - } + KeyPairType.ed25519.checkPublicKeyBytesFormat(publicKeyBytes); + Ed25519.checkSignatureLength(signatureBytes.length); // Decompress `a` final a = _pointDecompress(publicKeyBytes); diff --git a/cryptography/lib/src/dart/x25519.dart b/cryptography/lib/src/dart/x25519.dart index 6870e43f..823b1bb3 100644 --- a/cryptography/lib/src/dart/x25519.dart +++ b/cryptography/lib/src/dart/x25519.dart @@ -44,6 +44,7 @@ class DartX25519 extends X25519 with DartKeyExchangeAlgorithmMixin { @override Future newKeyPairFromSeed(List seed) async { + KeyPairType.x25519.checkPrivateKeyBytesFormat(seed); final modifiedBytes = DartX25519.modifiedPrivateKeyBytes(seed); return SimpleKeyPairData( modifiedBytes, @@ -72,11 +73,14 @@ class DartX25519 extends X25519 with DartKeyExchangeAlgorithmMixin { ); } final privateKeyBytes = modifiedPrivateKeyBytes(keyPairData.bytes); + final publicKeyBytes = remotePublicKey.bytes; + KeyPairType.x25519.checkPrivateKeyBytesFormat(privateKeyBytes); + KeyPairType.x25519.checkPublicKeyBytesFormat(publicKeyBytes); final result = Uint8List(32); _calculate( result, privateKeyBytes, - Uint8List.fromList(remotePublicKey.bytes), + Uint8List.fromList(publicKeyBytes), ); return SecretKey(result); } diff --git a/cryptography/test/cryptography_with_seeded_random_test.dart b/cryptography/test/cryptography_with_seeded_random_test.dart index 43cf3df2..8117c7f4 100644 --- a/cryptography/test/cryptography_with_seeded_random_test.dart +++ b/cryptography/test/cryptography_with_seeded_random_test.dart @@ -191,9 +191,12 @@ void _testCryptography(Cryptography Function(Random? random) f) { // XorShift // -class _TestRandom implements Random { +class _TestRandom implements SecureRandom { int _state = 2463534242; + @override + bool get isSecure => false; + @override bool nextBool() => nextInt(2) != 0; @@ -214,4 +217,17 @@ class _TestRandom implements Random { _state = x; return x % max; } + + @override + int nextUint32() { + throw UnimplementedError(); + } + + @override + int nextUint52([int? max]) { + throw UnimplementedError(); + } + + @override + void reset() {} } diff --git a/cryptography_test/lib/algorithms/ed25519.dart b/cryptography_test/lib/algorithms/ed25519.dart index a7771ee6..1ef7a419 100644 --- a/cryptography_test/lib/algorithms/ed25519.dart +++ b/cryptography_test/lib/algorithms/ed25519.dart @@ -22,13 +22,11 @@ import '../signature.dart'; void testEd25519() { testSignatureAlgorithm( builder: () => Ed25519(), - otherTests: () { - _test(); - }, + otherTests: _otherTests, ); } -void _test() { +void _otherTests() { group('ed25519:', () { late Ed25519 algorithm;