Skip to content
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

Refactor EcdhPublicKey and EcdhPrivateKey Class #145

Merged
merged 3 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 6 additions & 12 deletions lib/src/impl_ffi/impl_ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,6 @@ class _OperationError extends Error implements OperationError {
String toString() => _message;
}

/// Implementation of [KeyPair].
class _KeyPair<S, T> implements KeyPair<S, T> {
@override
final S privateKey;

@override
final T publicKey;

_KeyPair({required this.privateKey, required this.publicKey});
}


const WebCryptoImpl webCryptImpl = _WebCryptoImpl();

final class _WebCryptoImpl implements WebCryptoImpl {
Expand All @@ -89,4 +77,10 @@ final class _WebCryptoImpl implements WebCryptoImpl {

@override
final pbkdf2SecretKey = const _StaticPbkdf2SecretKeyImpl();

@override
final ecdhPrivateKey = const _StaticEcdhPrivateKeyImpl();

@override
final ecdhPublicKey = const _StaticEcdhPublicKeyImpl();
}
6 changes: 3 additions & 3 deletions lib/src/impl_ffi/impl_ffi.ec_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,9 @@ KeyPair<_EvpPKey, _EvpPKey> _generateEcKeyPair(
final pubKey = _EvpPKey();
_checkOpIsOne(ssl.EVP_PKEY_set1_EC_KEY.invoke(pubKey, ecPub));

return _KeyPair(
privateKey: privKey,
publicKey: pubKey,
return createKeyPair(
privKey,
pubKey,
);
});
}
75 changes: 55 additions & 20 deletions lib/src/impl_ffi/impl_ffi.ecdh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,71 +16,90 @@

part of 'impl_ffi.dart';

Future<EcdhPrivateKey> ecdhPrivateKey_importPkcs8Key(
Future<EcdhPrivateKeyImpl> ecdhPrivateKey_importPkcs8Key(
List<int> keyData,
EllipticCurve curve,
) async =>
_EcdhPrivateKey(_importPkcs8EcPrivateKey(keyData, curve));
_EcdhPrivateKeyImpl(_importPkcs8EcPrivateKey(keyData, curve));

Future<EcdhPrivateKey> ecdhPrivateKey_importJsonWebKey(
Future<EcdhPrivateKeyImpl> ecdhPrivateKey_importJsonWebKey(
Map<String, dynamic> jwk,
EllipticCurve curve,
) async =>
_EcdhPrivateKey(_importJwkEcPrivateOrPublicKey(
_EcdhPrivateKeyImpl(_importJwkEcPrivateOrPublicKey(
JsonWebKey.fromJson(jwk),
curve,
isPrivateKey: true,
expectedUse: 'enc',
expectedAlg: null, // ECDH has no validation of 'jwk.alg'
));

Future<KeyPair<EcdhPrivateKey, EcdhPublicKey>> ecdhPrivateKey_generateKey(
Future<KeyPair<EcdhPrivateKeyImpl, EcdhPublicKeyImpl>> ecdhPrivateKey_generateKey(
EllipticCurve curve,
) async {
final p = _generateEcKeyPair(curve);
return _KeyPair(
privateKey: _EcdhPrivateKey(p.privateKey),
publicKey: _EcdhPublicKey(p.publicKey),
return createKeyPair(
_EcdhPrivateKeyImpl(p.privateKey),
_EcdhPublicKeyImpl(p.publicKey),
);
}

Future<EcdhPublicKey> ecdhPublicKey_importRawKey(
Future<EcdhPublicKeyImpl> ecdhPublicKey_importRawKey(
List<int> keyData,
EllipticCurve curve,
) async =>
_EcdhPublicKey(_importRawEcPublicKey(keyData, curve));
_EcdhPublicKeyImpl(_importRawEcPublicKey(keyData, curve));

Future<EcdhPublicKey> ecdhPublicKey_importSpkiKey(
Future<EcdhPublicKeyImpl> ecdhPublicKey_importSpkiKey(
List<int> keyData,
EllipticCurve curve,
) async =>
_EcdhPublicKey(_importSpkiEcPublicKey(keyData, curve));
_EcdhPublicKeyImpl(_importSpkiEcPublicKey(keyData, curve));

Future<EcdhPublicKey> ecdhPublicKey_importJsonWebKey(
Future<EcdhPublicKeyImpl> ecdhPublicKey_importJsonWebKey(
Map<String, dynamic> jwk,
EllipticCurve curve,
) async =>
_EcdhPublicKey(_importJwkEcPrivateOrPublicKey(
_EcdhPublicKeyImpl(_importJwkEcPrivateOrPublicKey(
JsonWebKey.fromJson(jwk),
curve,
isPrivateKey: false,
expectedUse: 'enc',
expectedAlg: null, // ECDH has no validation of 'jwk.alg'
));

class _EcdhPrivateKey implements EcdhPrivateKey {
final class _StaticEcdhPrivateKeyImpl implements StaticEcdhPrivateKeyImpl {
const _StaticEcdhPrivateKeyImpl();

@override
Future<EcdhPrivateKeyImpl> importPkcs8Key(List<int> keyData, EllipticCurve curve) =>
ecdhPrivateKey_importPkcs8Key(keyData, curve);

@override
Future<EcdhPrivateKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve) =>
ecdhPrivateKey_importJsonWebKey(jwk, curve);

@override
Future<(EcdhPrivateKeyImpl, EcdhPublicKeyImpl)> generateKey(EllipticCurve curve) async {
final KeyPair<EcdhPrivateKeyImpl, EcdhPublicKeyImpl> keyPair = await ecdhPrivateKey_generateKey(curve);

return (keyPair.privateKey, keyPair.publicKey);
}
}

final class _EcdhPrivateKeyImpl implements EcdhPrivateKeyImpl {
final _EvpPKey _key;

_EcdhPrivateKey(this._key);
_EcdhPrivateKeyImpl(this._key);

@override
String toString() {
return 'Instance of \'EcdhPrivateKey\'';
}

@override
Future<Uint8List> deriveBits(int length, EcdhPublicKey publicKey) async {
if (publicKey is! _EcdhPublicKey) {
Future<Uint8List> deriveBits(int length, EcdhPublicKeyImpl publicKey) async {
if (publicKey is! _EcdhPublicKeyImpl) {
throw ArgumentError.value(
publicKey,
'publicKey',
Expand Down Expand Up @@ -167,10 +186,26 @@ class _EcdhPrivateKey implements EcdhPrivateKey {
Future<Uint8List> exportPkcs8Key() async => _exportPkcs8Key(_key);
}

class _EcdhPublicKey implements EcdhPublicKey {
final class _StaticEcdhPublicKeyImpl implements StaticEcdhPublicKeyImpl {
const _StaticEcdhPublicKeyImpl();

@override
Future<EcdhPublicKeyImpl> importRawKey(List<int> keyData, EllipticCurve curve) =>
ecdhPublicKey_importRawKey(keyData, curve);

@override
Future<EcdhPublicKeyImpl> importSpkiKey(List<int> keyData, EllipticCurve curve) =>
ecdhPublicKey_importSpkiKey(keyData, curve);

@override
Future<EcdhPublicKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve) =>
ecdhPublicKey_importJsonWebKey(jwk, curve);
}

final class _EcdhPublicKeyImpl implements EcdhPublicKeyImpl {
final _EvpPKey _key;

_EcdhPublicKey(this._key);
_EcdhPublicKeyImpl(this._key);

@override
String toString() {
Expand Down
6 changes: 3 additions & 3 deletions lib/src/impl_ffi/impl_ffi.ecdsa.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ Future<KeyPair<EcdsaPrivateKey, EcdsaPublicKey>> ecdsaPrivateKey_generateKey(
EllipticCurve curve,
) async {
final p = _generateEcKeyPair(curve);
return _KeyPair(
privateKey: _EcdsaPrivateKey(p.privateKey),
publicKey: _EcdsaPublicKey(p.publicKey),
return createKeyPair(
_EcdsaPrivateKey(p.privateKey),
_EcdsaPublicKey(p.publicKey),
);
}

Expand Down
8 changes: 4 additions & 4 deletions lib/src/impl_ffi/impl_ffi.rsa_common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Map<String, dynamic> _exportJwkRsaPrivateOrPublicKey(
});
}

_KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair(
KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair(
int modulusLength,
BigInt publicExponent,
) {
Expand Down Expand Up @@ -278,9 +278,9 @@ _KeyPair<_EvpPKey, _EvpPKey> _generateRsaKeyPair(
final pubKey = _EvpPKey();
_checkOp(ssl.EVP_PKEY_set1_RSA.invoke(pubKey, pubRSA) == 1);

return _KeyPair(
privateKey: privKey,
publicKey: pubKey,
return createKeyPair(
privKey,
pubKey,
);
});
}
6 changes: 3 additions & 3 deletions lib/src/impl_ffi/impl_ffi.rsaoaep.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ Future<KeyPair<RsaOaepPrivateKey, RsaOaepPublicKey>>
// Get hash first, to avoid a leak of EVP_PKEY if _Hash.fromHash throws
final h = _Hash.fromHash(hash);
final keys = _generateRsaKeyPair(modulusLength, publicExponent);
return _KeyPair(
privateKey: _RsaOaepPrivateKey(keys.privateKey, h),
publicKey: _RsaOaepPublicKey(keys.publicKey, h),
return createKeyPair(
_RsaOaepPrivateKey(keys.privateKey, h),
_RsaOaepPublicKey(keys.publicKey, h),
);
}

Expand Down
6 changes: 3 additions & 3 deletions lib/src/impl_ffi/impl_ffi.rsapss.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ Future<KeyPair<RsaPssPrivateKey, RsaPssPublicKey>> rsaPssPrivateKey_generateKey(
// Validate and get hash function
final h = _Hash.fromHash(hash);
final keys = _generateRsaKeyPair(modulusLength, publicExponent);
return _KeyPair(
privateKey: _RsaPssPrivateKey(keys.privateKey, h),
publicKey: _RsaPssPublicKey(keys.publicKey, h),
return createKeyPair(
_RsaPssPrivateKey(keys.privateKey, h),
_RsaPssPublicKey(keys.publicKey, h),
);
}

Expand Down
6 changes: 3 additions & 3 deletions lib/src/impl_ffi/impl_ffi.rsassapkcs1v15.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ Future<KeyPair<RsassaPkcs1V15PrivateKey, RsassaPkcs1V15PublicKey>>
// Get hash first, to avoid a leak of EVP_PKEY if _Hash.fromHash throws
final h = _Hash.fromHash(hash);
final keys = _generateRsaKeyPair(modulusLength, publicExponent);
return _KeyPair(
privateKey: _RsassaPkcs1V15PrivateKey(keys.privateKey, h),
publicKey: _RsassaPkcs1V15PublicKey(keys.publicKey, h),
return createKeyPair(
_RsassaPkcs1V15PrivateKey(keys.privateKey, h),
_RsassaPkcs1V15PublicKey(keys.publicKey, h),
);
}

Expand Down
38 changes: 36 additions & 2 deletions lib/src/impl_interface/impl_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,46 @@ library impl_stub;
import 'dart:typed_data';
import 'dart:async';

import 'package:webcrypto/webcrypto.dart';

import 'package:webcrypto/webcrypto.dart' show Hash;

part 'impl_interface.aescbc.dart';
part 'impl_interface.aesctr.dart';
part 'impl_interface.hmac.dart';
part 'impl_interface.pbkdf2.dart';
part 'impl_interface.aesgcm.dart';
part 'impl_interface.ecdh.dart';

/// A key-pair as returned from key generation.
class KeyPair<S, T> {
KeyPair._(this.privateKey, this.publicKey); // keep the constructor private.

/// Private key for [publicKey].
final S privateKey;

/// Public key matching [privateKey].
final T publicKey;
}

/// Factory method to create KeyPair instance
KeyPair<S, T> createKeyPair<S, T>(S privateKey, T publicKey) {
return KeyPair._(privateKey, publicKey);
}

/// Elliptic curves supported by ECDSA and ECDH.
///
/// > [!NOTE]
/// > Additional values may be added to this enum in the future.
enum EllipticCurve {
p256,
p384,

///
///
/// P-521 is **not supported on Safari**, see [bug 216755 (bugs.webkit.org)][1].
///
/// [1]: https://bugs.webkit.org/show_bug.cgi?id=216755
p521,
}

/// Interface to be provided by platform implementations.
///
Expand All @@ -48,4 +80,6 @@ abstract interface class WebCryptoImpl {
StaticAesGcmSecretKeyImpl get aesGcmSecretKey;
StaticHmacSecretKeyImpl get hmacSecretKey;
StaticPbkdf2SecretKeyImpl get pbkdf2SecretKey;
StaticEcdhPrivateKeyImpl get ecdhPrivateKey;
StaticEcdhPublicKeyImpl get ecdhPublicKey;
}
39 changes: 39 additions & 0 deletions lib/src/impl_interface/impl_interface.ecdh.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2020 Google LLC
//
// 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.

part of 'impl_interface.dart';

abstract interface class StaticEcdhPrivateKeyImpl {
Future<EcdhPrivateKeyImpl> importPkcs8Key(List<int> keyData, EllipticCurve curve);
Future<EcdhPrivateKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve);
Future<(EcdhPrivateKeyImpl, EcdhPublicKeyImpl)> generateKey(EllipticCurve curve);
}

abstract interface class EcdhPrivateKeyImpl {
Future<Uint8List> deriveBits(int length, EcdhPublicKeyImpl publicKey);
Future<Uint8List> exportPkcs8Key();
Future<Map<String, dynamic>> exportJsonWebKey();
}

abstract interface class StaticEcdhPublicKeyImpl {
Future<EcdhPublicKeyImpl> importRawKey(List<int> keyData, EllipticCurve curve);
Future<EcdhPublicKeyImpl> importSpkiKey(List<int> keyData, EllipticCurve curve);
Future<EcdhPublicKeyImpl> importJsonWebKey(Map<String, dynamic> jwk, EllipticCurve curve);
}

abstract interface class EcdhPublicKeyImpl {
Future<Uint8List> exportRawKey();
Future<Uint8List> exportSpkiKey();
Future<Map<String, dynamic>> exportJsonWebKey();
}
17 changes: 6 additions & 11 deletions lib/src/impl_js/impl_js.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,6 @@ class _OperationError extends Error implements OperationError {
String toString() => _message;
}

/// Implementation of [KeyPair].
class _KeyPair<S, T> implements KeyPair<S, T> {
@override
final S privateKey;

@override
final T publicKey;

_KeyPair({required this.privateKey, required this.publicKey});
}

const WebCryptoImpl webCryptImpl = _WebCryptoImpl();

final class _WebCryptoImpl implements WebCryptoImpl {
Expand All @@ -75,4 +64,10 @@ final class _WebCryptoImpl implements WebCryptoImpl {

@override
final pbkdf2SecretKey = const _StaticPbkdf2SecretKeyImpl();

@override
final ecdhPrivateKey = const _StaticEcdhPrivateKeyImpl();

@override
final ecdhPublicKey = const _StaticEcdhPublicKeyImpl();
}
Loading
Loading