Skip to content

Commit 923ac08

Browse files
Refactor EcdhPublicKey and EcdhPrivateKey Class (#145)
* refactor: update ecdh-private-key ecdh-public-key * fix!: remove cyclic imports and migrate keypair class
1 parent cdf81ad commit 923ac08

22 files changed

+339
-187
lines changed

lib/src/impl_ffi/impl_ffi.dart

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,6 @@ class _OperationError extends Error implements OperationError {
5858
String toString() => _message;
5959
}
6060

61-
/// Implementation of [KeyPair].
62-
class _KeyPair<S, T> implements KeyPair<S, T> {
63-
@override
64-
final S privateKey;
65-
66-
@override
67-
final T publicKey;
68-
69-
_KeyPair({required this.privateKey, required this.publicKey});
70-
}
71-
72-
7361
const WebCryptoImpl webCryptImpl = _WebCryptoImpl();
7462

7563
final class _WebCryptoImpl implements WebCryptoImpl {
@@ -89,4 +77,10 @@ final class _WebCryptoImpl implements WebCryptoImpl {
8977

9078
@override
9179
final pbkdf2SecretKey = const _StaticPbkdf2SecretKeyImpl();
80+
81+
@override
82+
final ecdhPrivateKey = const _StaticEcdhPrivateKeyImpl();
83+
84+
@override
85+
final ecdhPublicKey = const _StaticEcdhPublicKeyImpl();
9286
}

lib/src/impl_ffi/impl_ffi.ec_common.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,9 +351,9 @@ KeyPair<_EvpPKey, _EvpPKey> _generateEcKeyPair(
351351
final pubKey = _EvpPKey();
352352
_checkOpIsOne(ssl.EVP_PKEY_set1_EC_KEY.invoke(pubKey, ecPub));
353353

354-
return _KeyPair(
355-
privateKey: privKey,
356-
publicKey: pubKey,
354+
return createKeyPair(
355+
privKey,
356+
pubKey,
357357
);
358358
});
359359
}

lib/src/impl_ffi/impl_ffi.ecdh.dart

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,71 +16,90 @@
1616

1717
part of 'impl_ffi.dart';
1818

19-
Future<EcdhPrivateKey> ecdhPrivateKey_importPkcs8Key(
19+
Future<EcdhPrivateKeyImpl> ecdhPrivateKey_importPkcs8Key(
2020
List<int> keyData,
2121
EllipticCurve curve,
2222
) async =>
23-
_EcdhPrivateKey(_importPkcs8EcPrivateKey(keyData, curve));
23+
_EcdhPrivateKeyImpl(_importPkcs8EcPrivateKey(keyData, curve));
2424

25-
Future<EcdhPrivateKey> ecdhPrivateKey_importJsonWebKey(
25+
Future<EcdhPrivateKeyImpl> ecdhPrivateKey_importJsonWebKey(
2626
Map<String, dynamic> jwk,
2727
EllipticCurve curve,
2828
) async =>
29-
_EcdhPrivateKey(_importJwkEcPrivateOrPublicKey(
29+
_EcdhPrivateKeyImpl(_importJwkEcPrivateOrPublicKey(
3030
JsonWebKey.fromJson(jwk),
3131
curve,
3232
isPrivateKey: true,
3333
expectedUse: 'enc',
3434
expectedAlg: null, // ECDH has no validation of 'jwk.alg'
3535
));
3636

37-
Future<KeyPair<EcdhPrivateKey, EcdhPublicKey>> ecdhPrivateKey_generateKey(
37+
Future<KeyPair<EcdhPrivateKeyImpl, EcdhPublicKeyImpl>> ecdhPrivateKey_generateKey(
3838
EllipticCurve curve,
3939
) async {
4040
final p = _generateEcKeyPair(curve);
41-
return _KeyPair(
42-
privateKey: _EcdhPrivateKey(p.privateKey),
43-
publicKey: _EcdhPublicKey(p.publicKey),
41+
return createKeyPair(
42+
_EcdhPrivateKeyImpl(p.privateKey),
43+
_EcdhPublicKeyImpl(p.publicKey),
4444
);
4545
}
4646

47-
Future<EcdhPublicKey> ecdhPublicKey_importRawKey(
47+
Future<EcdhPublicKeyImpl> ecdhPublicKey_importRawKey(
4848
List<int> keyData,
4949
EllipticCurve curve,
5050
) async =>
51-
_EcdhPublicKey(_importRawEcPublicKey(keyData, curve));
51+
_EcdhPublicKeyImpl(_importRawEcPublicKey(keyData, curve));
5252

53-
Future<EcdhPublicKey> ecdhPublicKey_importSpkiKey(
53+
Future<EcdhPublicKeyImpl> ecdhPublicKey_importSpkiKey(
5454
List<int> keyData,
5555
EllipticCurve curve,
5656
) async =>
57-
_EcdhPublicKey(_importSpkiEcPublicKey(keyData, curve));
57+
_EcdhPublicKeyImpl(_importSpkiEcPublicKey(keyData, curve));
5858

59-
Future<EcdhPublicKey> ecdhPublicKey_importJsonWebKey(
59+
Future<EcdhPublicKeyImpl> ecdhPublicKey_importJsonWebKey(
6060
Map<String, dynamic> jwk,
6161
EllipticCurve curve,
6262
) async =>
63-
_EcdhPublicKey(_importJwkEcPrivateOrPublicKey(
63+
_EcdhPublicKeyImpl(_importJwkEcPrivateOrPublicKey(
6464
JsonWebKey.fromJson(jwk),
6565
curve,
6666
isPrivateKey: false,
6767
expectedUse: 'enc',
6868
expectedAlg: null, // ECDH has no validation of 'jwk.alg'
6969
));
7070

71-
class _EcdhPrivateKey implements EcdhPrivateKey {
71+
final class _StaticEcdhPrivateKeyImpl implements StaticEcdhPrivateKeyImpl {
72+
const _StaticEcdhPrivateKeyImpl();
73+
74+
@override
75+
Future<EcdhPrivateKeyImpl> importPkcs8Key(List<int> keyData, EllipticCurve curve) =>
76+
ecdhPrivateKey_importPkcs8Key(keyData, curve);
77+
78+
@override
79+
Future<EcdhPrivateKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve) =>
80+
ecdhPrivateKey_importJsonWebKey(jwk, curve);
81+
82+
@override
83+
Future<(EcdhPrivateKeyImpl, EcdhPublicKeyImpl)> generateKey(EllipticCurve curve) async {
84+
final KeyPair<EcdhPrivateKeyImpl, EcdhPublicKeyImpl> keyPair = await ecdhPrivateKey_generateKey(curve);
85+
86+
return (keyPair.privateKey, keyPair.publicKey);
87+
}
88+
}
89+
90+
final class _EcdhPrivateKeyImpl implements EcdhPrivateKeyImpl {
7291
final _EvpPKey _key;
7392

74-
_EcdhPrivateKey(this._key);
93+
_EcdhPrivateKeyImpl(this._key);
7594

7695
@override
7796
String toString() {
7897
return 'Instance of \'EcdhPrivateKey\'';
7998
}
8099

81100
@override
82-
Future<Uint8List> deriveBits(int length, EcdhPublicKey publicKey) async {
83-
if (publicKey is! _EcdhPublicKey) {
101+
Future<Uint8List> deriveBits(int length, EcdhPublicKeyImpl publicKey) async {
102+
if (publicKey is! _EcdhPublicKeyImpl) {
84103
throw ArgumentError.value(
85104
publicKey,
86105
'publicKey',
@@ -167,10 +186,26 @@ class _EcdhPrivateKey implements EcdhPrivateKey {
167186
Future<Uint8List> exportPkcs8Key() async => _exportPkcs8Key(_key);
168187
}
169188

170-
class _EcdhPublicKey implements EcdhPublicKey {
189+
final class _StaticEcdhPublicKeyImpl implements StaticEcdhPublicKeyImpl {
190+
const _StaticEcdhPublicKeyImpl();
191+
192+
@override
193+
Future<EcdhPublicKeyImpl> importRawKey(List<int> keyData, EllipticCurve curve) =>
194+
ecdhPublicKey_importRawKey(keyData, curve);
195+
196+
@override
197+
Future<EcdhPublicKeyImpl> importSpkiKey(List<int> keyData, EllipticCurve curve) =>
198+
ecdhPublicKey_importSpkiKey(keyData, curve);
199+
200+
@override
201+
Future<EcdhPublicKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve) =>
202+
ecdhPublicKey_importJsonWebKey(jwk, curve);
203+
}
204+
205+
final class _EcdhPublicKeyImpl implements EcdhPublicKeyImpl {
171206
final _EvpPKey _key;
172207

173-
_EcdhPublicKey(this._key);
208+
_EcdhPublicKeyImpl(this._key);
174209

175210
@override
176211
String toString() {

lib/src/impl_ffi/impl_ffi.ecdsa.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,9 @@ Future<KeyPair<EcdsaPrivateKey, EcdsaPublicKey>> ecdsaPrivateKey_generateKey(
5454
EllipticCurve curve,
5555
) async {
5656
final p = _generateEcKeyPair(curve);
57-
return _KeyPair(
58-
privateKey: _EcdsaPrivateKey(p.privateKey),
59-
publicKey: _EcdsaPublicKey(p.publicKey),
57+
return createKeyPair(
58+
_EcdsaPrivateKey(p.privateKey),
59+
_EcdsaPublicKey(p.publicKey),
6060
);
6161
}
6262

lib/src/impl_ffi/impl_ffi.rsa_common.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ Map<String, dynamic> _exportJwkRsaPrivateOrPublicKey(
229229
});
230230
}
231231

232-
_KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair(
232+
KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair(
233233
int modulusLength,
234234
BigInt publicExponent,
235235
) {
@@ -278,9 +278,9 @@ _KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair(
278278
final pubKey = _EvpPKey();
279279
_checkOp(ssl.EVP_PKEY_set1_RSA.invoke(pubKey, pubRSA) == 1);
280280

281-
return _KeyPair(
282-
privateKey: privKey,
283-
publicKey: pubKey,
281+
return createKeyPair(
282+
privKey,
283+
pubKey,
284284
);
285285
});
286286
}

lib/src/impl_ffi/impl_ffi.rsaoaep.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ Future<KeyPair<RsaOaepPrivateKey, RsaOaepPublicKey>>
6868
// Get hash first, to avoid a leak of EVP_PKEY if _Hash.fromHash throws
6969
final h = _Hash.fromHash(hash);
7070
final keys = _generateRsaKeyPair(modulusLength, publicExponent);
71-
return _KeyPair(
72-
privateKey: _RsaOaepPrivateKey(keys.privateKey, h),
73-
publicKey: _RsaOaepPublicKey(keys.publicKey, h),
71+
return createKeyPair(
72+
_RsaOaepPrivateKey(keys.privateKey, h),
73+
_RsaOaepPublicKey(keys.publicKey, h),
7474
);
7575
}
7676

lib/src/impl_ffi/impl_ffi.rsapss.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ Future<KeyPair<RsaPssPrivateKey, RsaPssPublicKey>> rsaPssPrivateKey_generateKey(
6767
// Validate and get hash function
6868
final h = _Hash.fromHash(hash);
6969
final keys = _generateRsaKeyPair(modulusLength, publicExponent);
70-
return _KeyPair(
71-
privateKey: _RsaPssPrivateKey(keys.privateKey, h),
72-
publicKey: _RsaPssPublicKey(keys.publicKey, h),
70+
return createKeyPair(
71+
_RsaPssPrivateKey(keys.privateKey, h),
72+
_RsaPssPublicKey(keys.publicKey, h),
7373
);
7474
}
7575

lib/src/impl_ffi/impl_ffi.rsassapkcs1v15.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ Future<KeyPair<RsassaPkcs1V15PrivateKey, RsassaPkcs1V15PublicKey>>
6868
// Get hash first, to avoid a leak of EVP_PKEY if _Hash.fromHash throws
6969
final h = _Hash.fromHash(hash);
7070
final keys = _generateRsaKeyPair(modulusLength, publicExponent);
71-
return _KeyPair(
72-
privateKey: _RsassaPkcs1V15PrivateKey(keys.privateKey, h),
73-
publicKey: _RsassaPkcs1V15PublicKey(keys.publicKey, h),
71+
return createKeyPair(
72+
_RsassaPkcs1V15PrivateKey(keys.privateKey, h),
73+
_RsassaPkcs1V15PublicKey(keys.publicKey, h),
7474
);
7575
}
7676

lib/src/impl_interface/impl_interface.dart

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,46 @@ library impl_stub;
1717
import 'dart:typed_data';
1818
import 'dart:async';
1919

20-
import 'package:webcrypto/webcrypto.dart';
21-
20+
import 'package:webcrypto/webcrypto.dart' show Hash;
2221

2322
part 'impl_interface.aescbc.dart';
2423
part 'impl_interface.aesctr.dart';
2524
part 'impl_interface.hmac.dart';
2625
part 'impl_interface.pbkdf2.dart';
2726
part 'impl_interface.aesgcm.dart';
27+
part 'impl_interface.ecdh.dart';
28+
29+
/// A key-pair as returned from key generation.
30+
class KeyPair<S, T> {
31+
KeyPair._(this.privateKey, this.publicKey); // keep the constructor private.
32+
33+
/// Private key for [publicKey].
34+
final S privateKey;
35+
36+
/// Public key matching [privateKey].
37+
final T publicKey;
38+
}
39+
40+
/// Factory method to create KeyPair instance
41+
KeyPair<S, T> createKeyPair<S, T>(S privateKey, T publicKey) {
42+
return KeyPair._(privateKey, publicKey);
43+
}
44+
45+
/// Elliptic curves supported by ECDSA and ECDH.
46+
///
47+
/// > [!NOTE]
48+
/// > Additional values may be added to this enum in the future.
49+
enum EllipticCurve {
50+
p256,
51+
p384,
52+
53+
///
54+
///
55+
/// P-521 is **not supported on Safari**, see [bug 216755 (bugs.webkit.org)][1].
56+
///
57+
/// [1]: https://bugs.webkit.org/show_bug.cgi?id=216755
58+
p521,
59+
}
2860

2961
/// Interface to be provided by platform implementations.
3062
///
@@ -48,4 +80,6 @@ abstract interface class WebCryptoImpl {
4880
StaticAesGcmSecretKeyImpl get aesGcmSecretKey;
4981
StaticHmacSecretKeyImpl get hmacSecretKey;
5082
StaticPbkdf2SecretKeyImpl get pbkdf2SecretKey;
83+
StaticEcdhPrivateKeyImpl get ecdhPrivateKey;
84+
StaticEcdhPublicKeyImpl get ecdhPublicKey;
5185
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
part of 'impl_interface.dart';
16+
17+
abstract interface class StaticEcdhPrivateKeyImpl {
18+
Future<EcdhPrivateKeyImpl> importPkcs8Key(List<int> keyData, EllipticCurve curve);
19+
Future<EcdhPrivateKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve);
20+
Future<(EcdhPrivateKeyImpl, EcdhPublicKeyImpl)> generateKey(EllipticCurve curve);
21+
}
22+
23+
abstract interface class EcdhPrivateKeyImpl {
24+
Future<Uint8List> deriveBits(int length, EcdhPublicKeyImpl publicKey);
25+
Future<Uint8List> exportPkcs8Key();
26+
Future<Map<String, dynamic>> exportJsonWebKey();
27+
}
28+
29+
abstract interface class StaticEcdhPublicKeyImpl {
30+
Future<EcdhPublicKeyImpl> importRawKey(List<int> keyData, EllipticCurve curve);
31+
Future<EcdhPublicKeyImpl> importSpkiKey(List<int> keyData, EllipticCurve curve);
32+
Future<EcdhPublicKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve);
33+
}
34+
35+
abstract interface class EcdhPublicKeyImpl {
36+
Future<Uint8List> exportRawKey();
37+
Future<Uint8List> exportSpkiKey();
38+
Future<Map<String, dynamic>> exportJsonWebKey();
39+
}

lib/src/impl_js/impl_js.dart

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,6 @@ class _OperationError extends Error implements OperationError {
4545
String toString() => _message;
4646
}
4747

48-
/// Implementation of [KeyPair].
49-
class _KeyPair<S, T> implements KeyPair<S, T> {
50-
@override
51-
final S privateKey;
52-
53-
@override
54-
final T publicKey;
55-
56-
_KeyPair({required this.privateKey, required this.publicKey});
57-
}
58-
5948
const WebCryptoImpl webCryptImpl = _WebCryptoImpl();
6049

6150
final class _WebCryptoImpl implements WebCryptoImpl {
@@ -75,4 +64,10 @@ final class _WebCryptoImpl implements WebCryptoImpl {
7564

7665
@override
7766
final pbkdf2SecretKey = const _StaticPbkdf2SecretKeyImpl();
67+
68+
@override
69+
final ecdhPrivateKey = const _StaticEcdhPrivateKeyImpl();
70+
71+
@override
72+
final ecdhPublicKey = const _StaticEcdhPublicKeyImpl();
7873
}

0 commit comments

Comments
 (0)