From c1ca4f4240a8d1eeeb67ab2230576aee3688af3b Mon Sep 17 00:00:00 2001 From: HamdaanAliQuatil <96776914+HamdaanAliQuatil@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:56:59 +0530 Subject: [PATCH] refactor: update hkdf-secret-key (#164) --- lib/src/impl_ffi/impl_ffi.dart | 3 ++ lib/src/impl_ffi/impl_ffi.hkdf.dart | 17 ++++++++--- lib/src/impl_interface/impl_interface.dart | 2 ++ .../impl_interface/impl_interface.hkdf.dart | 28 +++++++++++++++++++ lib/src/impl_js/impl_js.dart | 3 ++ lib/src/impl_js/impl_js.hkdf.dart | 19 +++++++++---- lib/src/impl_stub.dart | 3 -- lib/src/impl_stub/impl_stub.dart | 4 +++ lib/src/impl_stub/impl_stub.hkdf.dart | 23 +++++++++++++++ lib/src/webcrypto/webcrypto.hkdf.dart | 15 ++++++---- 10 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 lib/src/impl_interface/impl_interface.hkdf.dart create mode 100644 lib/src/impl_stub/impl_stub.hkdf.dart diff --git a/lib/src/impl_ffi/impl_ffi.dart b/lib/src/impl_ffi/impl_ffi.dart index d4897aa9..bfa0dcf1 100644 --- a/lib/src/impl_ffi/impl_ffi.dart +++ b/lib/src/impl_ffi/impl_ffi.dart @@ -95,4 +95,7 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final rsaOaepPublicKey = const _StaticRsaOaepPublicKeyImpl(); + + @override + final hkdfSecretKey = const _StaticHkdfSecretKeyImpl(); } diff --git a/lib/src/impl_ffi/impl_ffi.hkdf.dart b/lib/src/impl_ffi/impl_ffi.hkdf.dart index 52dcf908..37e54b0c 100644 --- a/lib/src/impl_ffi/impl_ffi.hkdf.dart +++ b/lib/src/impl_ffi/impl_ffi.hkdf.dart @@ -16,13 +16,22 @@ part of 'impl_ffi.dart'; -Future hkdfSecretKey_importRawKey(List keyData) async => - _HkdfSecretKey(Uint8List.fromList(keyData)); +Future hkdfSecretKey_importRawKey(List keyData) async => + _HkdfSecretKeyImpl(Uint8List.fromList(keyData)); -class _HkdfSecretKey implements HkdfSecretKey { +final class _StaticHkdfSecretKeyImpl implements StaticHkdfSecretKeyImpl { + const _StaticHkdfSecretKeyImpl(); + + @override + Future importRawKey(List keyData) async { + return hkdfSecretKey_importRawKey(keyData); + } +} + +final class _HkdfSecretKeyImpl implements HkdfSecretKeyImpl { final Uint8List _key; - _HkdfSecretKey(this._key); + _HkdfSecretKeyImpl(this._key); @override String toString() { diff --git a/lib/src/impl_interface/impl_interface.dart b/lib/src/impl_interface/impl_interface.dart index 487981e2..f04c5d01 100644 --- a/lib/src/impl_interface/impl_interface.dart +++ b/lib/src/impl_interface/impl_interface.dart @@ -27,6 +27,7 @@ part 'impl_interface.aesgcm.dart'; part 'impl_interface.ecdh.dart'; part 'impl_interface.ecdsa.dart'; part 'impl_interface.rsaoaep.dart'; +part 'impl_interface.hkdf.dart'; /// A key-pair as returned from key generation. class KeyPair { @@ -88,4 +89,5 @@ abstract interface class WebCryptoImpl { StaticEcdsaPublicKeyImpl get ecdsaPublicKey; StaticRsaOaepPrivateKeyImpl get rsaOaepPrivateKey; StaticRsaOaepPublicKeyImpl get rsaOaepPublicKey; + StaticHkdfSecretKeyImpl get hkdfSecretKey; } diff --git a/lib/src/impl_interface/impl_interface.hkdf.dart b/lib/src/impl_interface/impl_interface.hkdf.dart new file mode 100644 index 00000000..73578e56 --- /dev/null +++ b/lib/src/impl_interface/impl_interface.hkdf.dart @@ -0,0 +1,28 @@ +// 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 StaticHkdfSecretKeyImpl { + Future importRawKey(List keyData); +} + +abstract interface class HkdfSecretKeyImpl { + Future deriveBits( + int length, + Hash hash, + List salt, + List info, + ); +} diff --git a/lib/src/impl_js/impl_js.dart b/lib/src/impl_js/impl_js.dart index 2217bfd2..4a45d31f 100644 --- a/lib/src/impl_js/impl_js.dart +++ b/lib/src/impl_js/impl_js.dart @@ -82,4 +82,7 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final rsaOaepPublicKey = const _StaticRsaOaepPublicKeyImpl(); + + @override + final hkdfSecretKey = const _StaticHkdfSecretKeyImpl(); } diff --git a/lib/src/impl_js/impl_js.hkdf.dart b/lib/src/impl_js/impl_js.hkdf.dart index 3ef8e807..ebbed475 100644 --- a/lib/src/impl_js/impl_js.hkdf.dart +++ b/lib/src/impl_js/impl_js.hkdf.dart @@ -18,22 +18,31 @@ part of 'impl_js.dart'; const _hkdfAlgorithmName = 'HKDF'; -Future hkdfSecretKey_importRawKey(List keyData) async { - return _HkdfSecretKey(await _importKey( +Future hkdfSecretKey_importRawKey(List keyData) async { + return _HkdfSecretKeyImpl(await _importKey( 'raw', keyData, const subtle.Algorithm(name: _hkdfAlgorithmName), _usagesDeriveBits, 'secret', - // Unlike all other key types it makes no sense to HkdfSecretKey to be + // Unlike all other key types it makes no sense to HkdfSecretKeyImpl to be // exported, and indeed webcrypto requires `extractable: false`. extractable: false, )); } -class _HkdfSecretKey implements HkdfSecretKey { +final class _StaticHkdfSecretKeyImpl implements StaticHkdfSecretKeyImpl { + const _StaticHkdfSecretKeyImpl(); + + @override + Future importRawKey(List keyData) async { + return await hkdfSecretKey_importRawKey(keyData); + } +} + +final class _HkdfSecretKeyImpl implements HkdfSecretKeyImpl { final subtle.JSCryptoKey _key; - _HkdfSecretKey(this._key); + _HkdfSecretKeyImpl(this._key); @override String toString() { diff --git a/lib/src/impl_stub.dart b/lib/src/impl_stub.dart index c7a0ec8f..cb814484 100644 --- a/lib/src/impl_stub.dart +++ b/lib/src/impl_stub.dart @@ -126,7 +126,4 @@ Future rsaPssPublicKey_importJsonWebKey( //---------------------- HKDF -Future hkdfSecretKey_importRawKey(List keyData) => - throw _notImplemented; - //---------------------- PBKDF2 diff --git a/lib/src/impl_stub/impl_stub.dart b/lib/src/impl_stub/impl_stub.dart index 0eba5aaa..6f7f08d9 100644 --- a/lib/src/impl_stub/impl_stub.dart +++ b/lib/src/impl_stub/impl_stub.dart @@ -26,6 +26,7 @@ part 'impl_stub.pbkdf2.dart'; part 'impl_stub.ecdh.dart'; part 'impl_stub.ecdsa.dart'; part 'impl_stub.rsaoaep.dart'; +part 'impl_stub.hkdf.dart'; const WebCryptoImpl webCryptImpl = _WebCryptoImpl(); @@ -64,4 +65,7 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final rsaOaepPublicKey = const _StaticRsaOaepPublicKeyImpl(); + + @override + final hkdfSecretKey = const _StaticHkdfSecretKeyImpl(); } diff --git a/lib/src/impl_stub/impl_stub.hkdf.dart b/lib/src/impl_stub/impl_stub.hkdf.dart new file mode 100644 index 00000000..1e07cead --- /dev/null +++ b/lib/src/impl_stub/impl_stub.hkdf.dart @@ -0,0 +1,23 @@ +// 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_stub.dart'; + +final class _StaticHkdfSecretKeyImpl implements StaticHkdfSecretKeyImpl { + const _StaticHkdfSecretKeyImpl(); + + @override + Future importRawKey(List keyData) => + throw UnimplementedError('Not implemented'); +} diff --git a/lib/src/webcrypto/webcrypto.hkdf.dart b/lib/src/webcrypto/webcrypto.hkdf.dart index 7df11735..8b98c69f 100644 --- a/lib/src/webcrypto/webcrypto.hkdf.dart +++ b/lib/src/webcrypto/webcrypto.hkdf.dart @@ -50,17 +50,19 @@ part of 'webcrypto.dart'; /// [1]: https://tools.ietf.org/html/rfc5869 // TODO: It might be wise to use a random salt, then suggest that the non-secret // salt is stored or exchanged... -@sealed -abstract class HkdfSecretKey { - HkdfSecretKey._(); // keep the constructor private. +final class HkdfSecretKey { + final HkdfSecretKeyImpl _impl; + + HkdfSecretKey._(this._impl); // keep the constructor private. /// Import [HkdfSecretKey] from raw [keyData]. /// /// Creates a [HkdfSecretKey] for key derivation using [keyData]. /// /// {@macro HkdfSecretKey:example} - static Future importRawKey(List keyData) { - return impl.hkdfSecretKey_importRawKey(keyData); + static Future importRawKey(List keyData) async { + final impl = await webCryptImpl.hkdfSecretKey.importRawKey(keyData); + return HkdfSecretKey._(impl); } /// Derive key from [salt], [info] and password specified as `keyData` in @@ -89,5 +91,6 @@ abstract class HkdfSecretKey { Hash hash, List salt, List info, - ); + ) => + _impl.deriveBits(length, hash, salt, info); }