From 0bcae1208c561f0610fdf4ad771f1f27cf8b0107 Mon Sep 17 00:00:00 2001 From: HamdaanAliQuatil Date: Wed, 14 Aug 2024 16:24:52 +0530 Subject: [PATCH 1/2] refactor: update aesgcm-secret-key --- lib/src/impl_ffi/impl_ffi.aescbc.dart | 2 +- lib/src/impl_ffi/impl_ffi.aesctr.dart | 2 +- lib/src/impl_ffi/impl_ffi.aesgcm.dart | 35 ++++++++++++++----- lib/src/impl_ffi/impl_ffi.dart | 3 ++ .../impl_interface/impl_interface.aescbc.dart | 2 +- .../impl_interface/impl_interface.aesctr.dart | 2 +- .../impl_interface/impl_interface.aesgcm.dart | 28 +++++++++++++++ lib/src/impl_interface/impl_interface.dart | 2 ++ lib/src/impl_js/impl_js.aesctr.dart | 2 +- lib/src/impl_js/impl_js.aesgcm.dart | 35 ++++++++++++++----- lib/src/impl_js/impl_js.dart | 3 ++ lib/src/impl_stub.dart | 8 ----- lib/src/impl_stub/impl_stub.aesgcm.dart | 31 ++++++++++++++++ lib/src/impl_stub/impl_stub.dart | 4 +++ lib/src/webcrypto/webcrypto.aesgcm.dart | 32 ++++++++++------- 15 files changed, 149 insertions(+), 42 deletions(-) create mode 100644 lib/src/impl_interface/impl_interface.aesgcm.dart create mode 100644 lib/src/impl_stub/impl_stub.aesgcm.dart diff --git a/lib/src/impl_ffi/impl_ffi.aescbc.dart b/lib/src/impl_ffi/impl_ffi.aescbc.dart index 34d9ae48..55a5e5a1 100644 --- a/lib/src/impl_ffi/impl_ffi.aescbc.dart +++ b/lib/src/impl_ffi/impl_ffi.aescbc.dart @@ -114,7 +114,7 @@ final class _StaticAesCbcSecretKeyImpl implements StaticAesCbcSecretKeyImpl { } } -final class _AesCbcSecretKeyImpl extends AesCbcSecretKeyImpl { +final class _AesCbcSecretKeyImpl implements AesCbcSecretKeyImpl { final Uint8List _key; _AesCbcSecretKeyImpl(this._key); diff --git a/lib/src/impl_ffi/impl_ffi.aesctr.dart b/lib/src/impl_ffi/impl_ffi.aesctr.dart index cfd8599f..709b5fff 100644 --- a/lib/src/impl_ffi/impl_ffi.aesctr.dart +++ b/lib/src/impl_ffi/impl_ffi.aesctr.dart @@ -221,7 +221,7 @@ final class _StaticAesCtrSecretKeyImpl implements StaticAesCtrSecretKeyImpl { } } -final class _AesCtrSecretKeyImpl extends AesCtrSecretKeyImpl { +final class _AesCtrSecretKeyImpl implements AesCtrSecretKeyImpl { final Uint8List _key; _AesCtrSecretKeyImpl(this._key); diff --git a/lib/src/impl_ffi/impl_ffi.aesgcm.dart b/lib/src/impl_ffi/impl_ffi.aesgcm.dart index 5adc463d..7922dd1a 100644 --- a/lib/src/impl_ffi/impl_ffi.aesgcm.dart +++ b/lib/src/impl_ffi/impl_ffi.aesgcm.dart @@ -16,19 +16,19 @@ part of 'impl_ffi.dart'; -Future aesGcm_importRawKey(List keyData) async => - _AesGcmSecretKey(_aesImportRawKey(keyData)); +Future aesGcm_importRawKey(List keyData) async => + _AesGcmSecretKeyImpl(_aesImportRawKey(keyData)); -Future aesGcm_importJsonWebKey( +Future aesGcm_importJsonWebKey( Map jwk, ) async => - _AesGcmSecretKey(_aesImportJwkKey( + _AesGcmSecretKeyImpl(_aesImportJwkKey( jwk, expectedJwkAlgSuffix: 'GCM', )); -Future aesGcm_generateKey(int length) async => - _AesGcmSecretKey(_aesGenerateKey(length)); +Future aesGcm_generateKey(int length) async => + _AesGcmSecretKeyImpl(_aesGenerateKey(length)); Future _aesGcmEncryptDecrypt( List key, @@ -111,9 +111,28 @@ Future _aesGcmEncryptDecrypt( }); } -class _AesGcmSecretKey implements AesGcmSecretKey { +final class _StaticAesGcmSecretKeyImpl implements StaticAesGcmSecretKeyImpl { + const _StaticAesGcmSecretKeyImpl(); + + @override + Future importRawKey(List keyData) async { + return await aesGcm_importRawKey(keyData); + } + + @override + Future importJsonWebKey(Map jwk) async { + return await aesGcm_importJsonWebKey(jwk); + } + + @override + Future generateKey(int length) async { + return await aesGcm_generateKey(length); + } +} + +final class _AesGcmSecretKeyImpl implements AesGcmSecretKeyImpl { final Uint8List _key; - _AesGcmSecretKey(this._key); + _AesGcmSecretKeyImpl(this._key); @override String toString() { diff --git a/lib/src/impl_ffi/impl_ffi.dart b/lib/src/impl_ffi/impl_ffi.dart index 1064f9d9..b8f74c49 100644 --- a/lib/src/impl_ffi/impl_ffi.dart +++ b/lib/src/impl_ffi/impl_ffi.dart @@ -80,4 +80,7 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final aesCtrSecretKey = const _StaticAesCtrSecretKeyImpl(); + + @override + final aesGcmSecretKey = const _StaticAesGcmSecretKeyImpl(); } diff --git a/lib/src/impl_interface/impl_interface.aescbc.dart b/lib/src/impl_interface/impl_interface.aescbc.dart index 47e5a382..543dc87d 100644 --- a/lib/src/impl_interface/impl_interface.aescbc.dart +++ b/lib/src/impl_interface/impl_interface.aescbc.dart @@ -20,7 +20,7 @@ abstract interface class StaticAesCbcSecretKeyImpl { Future generateKey(int length); } -abstract class AesCbcSecretKeyImpl { +abstract interface class AesCbcSecretKeyImpl { Future encryptBytes(List data, List iv); Future decryptBytes(List data, List iv); Stream encryptStream(Stream> data, List iv); diff --git a/lib/src/impl_interface/impl_interface.aesctr.dart b/lib/src/impl_interface/impl_interface.aesctr.dart index 9714eecc..65db9dce 100644 --- a/lib/src/impl_interface/impl_interface.aesctr.dart +++ b/lib/src/impl_interface/impl_interface.aesctr.dart @@ -20,7 +20,7 @@ abstract interface class StaticAesCtrSecretKeyImpl { Future generateKey(int length); } -abstract class AesCtrSecretKeyImpl { +abstract interface class AesCtrSecretKeyImpl { Future encryptBytes(List data, List counter, int length); Future decryptBytes(List data, List counter, int length); Stream encryptStream(Stream> data, List counter, int length); diff --git a/lib/src/impl_interface/impl_interface.aesgcm.dart b/lib/src/impl_interface/impl_interface.aesgcm.dart new file mode 100644 index 00000000..fa0afb88 --- /dev/null +++ b/lib/src/impl_interface/impl_interface.aesgcm.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 StaticAesGcmSecretKeyImpl { + Future importRawKey(List keyData); + Future importJsonWebKey(Map jwk); + Future generateKey(int length); +} + +abstract interface class AesGcmSecretKeyImpl { + Future encryptBytes(List data, List iv, {List? additionalData, int? tagLength}); + Future decryptBytes(List data, List iv, {List? additionalData, int? tagLength}); + Future exportRawKey(); + Future> exportJsonWebKey(); +} diff --git a/lib/src/impl_interface/impl_interface.dart b/lib/src/impl_interface/impl_interface.dart index f2a5df4e..5d456ff8 100644 --- a/lib/src/impl_interface/impl_interface.dart +++ b/lib/src/impl_interface/impl_interface.dart @@ -20,6 +20,7 @@ import 'dart:async'; part 'impl_interface.aescbc.dart'; part 'impl_interface.aesctr.dart'; +part 'impl_interface.aesgcm.dart'; /// Interface to be provided by platform implementations. /// @@ -40,4 +41,5 @@ part 'impl_interface.aesctr.dart'; abstract interface class WebCryptoImpl { StaticAesCbcSecretKeyImpl get aesCbcSecretKey; StaticAesCtrSecretKeyImpl get aesCtrSecretKey; + StaticAesGcmSecretKeyImpl get aesGcmSecretKey; } diff --git a/lib/src/impl_js/impl_js.aesctr.dart b/lib/src/impl_js/impl_js.aesctr.dart index 895701f5..3a97ff80 100644 --- a/lib/src/impl_js/impl_js.aesctr.dart +++ b/lib/src/impl_js/impl_js.aesctr.dart @@ -66,7 +66,7 @@ final class _StaticAesCtrSecretKeyImpl implements StaticAesCtrSecretKeyImpl { } } -final class _AesCtrSecretKeyImpl extends AesCtrSecretKeyImpl { +final class _AesCtrSecretKeyImpl implements AesCtrSecretKeyImpl { final subtle.JSCryptoKey _key; _AesCtrSecretKeyImpl(this._key); diff --git a/lib/src/impl_js/impl_js.aesgcm.dart b/lib/src/impl_js/impl_js.aesgcm.dart index d1dae77b..d630e15a 100644 --- a/lib/src/impl_js/impl_js.aesgcm.dart +++ b/lib/src/impl_js/impl_js.aesgcm.dart @@ -18,8 +18,8 @@ part of 'impl_js.dart'; const _aesGcmAlgorithm = subtle.Algorithm(name: 'AES-GCM'); -Future aesGcm_importRawKey(List keyData) async { - return _AesGcmSecretKey(await _importKey( +Future aesGcm_importRawKey(List keyData) async { + return _AesGcmSecretKeyImpl(await _importKey( 'raw', keyData, _aesGcmAlgorithm, @@ -28,10 +28,10 @@ Future aesGcm_importRawKey(List keyData) async { )); } -Future aesGcm_importJsonWebKey( +Future aesGcm_importJsonWebKey( Map jwk, ) async { - return _AesGcmSecretKey(await _importJsonWebKey( + return _AesGcmSecretKeyImpl(await _importJsonWebKey( jwk, _aesGcmAlgorithm, _usagesEncryptDecrypt, @@ -39,17 +39,36 @@ Future aesGcm_importJsonWebKey( )); } -Future aesGcm_generateKey(int length) async { - return _AesGcmSecretKey(await _generateKey( +Future aesGcm_generateKey(int length) async { + return _AesGcmSecretKeyImpl(await _generateKey( _aesGcmAlgorithm.update(length: length), _usagesEncryptDecrypt, 'secret', )); } -class _AesGcmSecretKey implements AesGcmSecretKey { +final class _StaticAesGcmSecretKeyImpl implements StaticAesGcmSecretKeyImpl { + const _StaticAesGcmSecretKeyImpl(); + + @override + Future importRawKey(List keyData) async { + return await aesGcm_importRawKey(keyData); + } + + @override + Future importJsonWebKey(Map jwk) async { + return await aesGcm_importJsonWebKey(jwk); + } + + @override + Future generateKey(int length) async { + return await aesGcm_generateKey(length); + } +} + +final class _AesGcmSecretKeyImpl implements AesGcmSecretKeyImpl { final subtle.JSCryptoKey _key; - _AesGcmSecretKey(this._key); + _AesGcmSecretKeyImpl(this._key); @override String toString() { diff --git a/lib/src/impl_js/impl_js.dart b/lib/src/impl_js/impl_js.dart index fc3c14b7..3037aeb9 100644 --- a/lib/src/impl_js/impl_js.dart +++ b/lib/src/impl_js/impl_js.dart @@ -66,4 +66,7 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final aesCtrSecretKey = const _StaticAesCtrSecretKeyImpl(); + + @override + final aesGcmSecretKey = const _StaticAesGcmSecretKeyImpl(); } diff --git a/lib/src/impl_stub.dart b/lib/src/impl_stub.dart index 20a96f31..a8138781 100644 --- a/lib/src/impl_stub.dart +++ b/lib/src/impl_stub.dart @@ -207,14 +207,6 @@ Future rsaOaepPublicKey_importJsonWebKey( //---------------------- AES-GCM -Future aesGcm_importRawKey(List keyData) => - throw _notImplemented; - -Future aesGcm_importJsonWebKey(Map jwk) => - throw _notImplemented; - -Future aesGcm_generateKey(int length) => throw _notImplemented; - //---------------------- ECDH Future ecdhPrivateKey_importPkcs8Key( diff --git a/lib/src/impl_stub/impl_stub.aesgcm.dart b/lib/src/impl_stub/impl_stub.aesgcm.dart new file mode 100644 index 00000000..7f98490e --- /dev/null +++ b/lib/src/impl_stub/impl_stub.aesgcm.dart @@ -0,0 +1,31 @@ +// 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 _StaticAesGcmSecretKeyImpl implements StaticAesGcmSecretKeyImpl { + const _StaticAesGcmSecretKeyImpl(); + + @override + Future importRawKey(List keyData) => + throw UnimplementedError('Not implemented'); + + @override + Future importJsonWebKey(Map jwk) => + throw UnimplementedError('Not implemented'); + + @override + Future generateKey(int length) => + throw UnimplementedError('Not implemented'); +} diff --git a/lib/src/impl_stub/impl_stub.dart b/lib/src/impl_stub/impl_stub.dart index 4d0dd232..6d39b0ff 100644 --- a/lib/src/impl_stub/impl_stub.dart +++ b/lib/src/impl_stub/impl_stub.dart @@ -18,6 +18,7 @@ import 'package:webcrypto/src/impl_interface/impl_interface.dart'; part 'impl_stub.aescbc.dart'; part 'impl_stub.aesctr.dart'; +part 'impl_stub.aesgcm.dart'; const WebCryptoImpl webCryptImpl = _WebCryptoImpl(); @@ -29,4 +30,7 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final aesCtrSecretKey = const _StaticAesCtrSecretKeyImpl(); + + @override + final aesGcmSecretKey = const _StaticAesGcmSecretKeyImpl(); } diff --git a/lib/src/webcrypto/webcrypto.aesgcm.dart b/lib/src/webcrypto/webcrypto.aesgcm.dart index c27f09b1..f5acbf53 100644 --- a/lib/src/webcrypto/webcrypto.aesgcm.dart +++ b/lib/src/webcrypto/webcrypto.aesgcm.dart @@ -32,9 +32,10 @@ part of 'webcrypto.dart'; /// [1]: https://csrc.nist.gov/pubs/sp/800/38/d/final /// [2]: https://tools.ietf.org/html/rfc7517 /// [3]: https://en.wikipedia.org/wiki/Authenticated_encryption -@sealed -abstract class AesGcmSecretKey { - AesGcmSecretKey._(); // keep the constructor private. +final class AesGcmSecretKey { + final AesGcmSecretKeyImpl _impl; + + AesGcmSecretKey._(this._impl); // keep the constructor private. /// Import an [AesGcmSecretKey] from raw [keyData]. /// @@ -66,8 +67,9 @@ abstract class AesGcmSecretKey { /// // Decrypt message (requires the same iv) /// print(utf8.decode(await k.decryptBytes(c, iv))); // hello world /// ``` - static Future importRawKey(List keyData) { - return impl.aesGcm_importRawKey(keyData); + static Future importRawKey(List keyData) async { + final impl = await webCryptImpl.aesGcmSecretKey.importRawKey(keyData); + return AesGcmSecretKey._(impl); } /// Import an [AesGcmSecretKey] from [JSON Web Key][1]. @@ -102,8 +104,9 @@ abstract class AesGcmSecretKey { /// ``` /// /// [1]: https://tools.ietf.org/html/rfc7517 - static Future importJsonWebKey(Map jwk) { - return impl.aesGcm_importJsonWebKey(jwk); + static Future importJsonWebKey(Map jwk) async { + final impl = await webCryptImpl.aesGcmSecretKey.importJsonWebKey(jwk); + return AesGcmSecretKey._(impl); } /// Generate a random [AesGcmSecretKey]. @@ -122,8 +125,9 @@ abstract class AesGcmSecretKey { /// // Generate a new random AES-GCM secret key for AES-256. /// final key = await AesGcmSecretKey.generate(256); /// ``` - static Future generateKey(int length) { - return impl.aesGcm_generateKey(length); + static Future generateKey(int length) async { + final impl = await webCryptImpl.aesGcmSecretKey.generateKey(length); + return AesGcmSecretKey._(impl); } /// Encrypt [data] with this [AesCbcSecretKey] using AES in @@ -218,7 +222,8 @@ abstract class AesGcmSecretKey { List iv, { List? additionalData, int? tagLength = 128, - }); + }) => + _impl.encryptBytes(data, iv, additionalData: additionalData, tagLength: tagLength); // TODO: Document this method, notice that [data] must be concatenation of // ciphertext and authentication tag. @@ -228,7 +233,8 @@ abstract class AesGcmSecretKey { List iv, { List? additionalData, int? tagLength = 128, - }); + }) => + _impl.decryptBytes(data, iv, additionalData: additionalData, tagLength: tagLength); /// Export [AesGcmSecretKey] as raw bytes. /// @@ -250,7 +256,7 @@ abstract class AesGcmSecretKey { /// // If we wanted to we could import the key as follows: /// // key = await AesGcmSecretKey.importRawKey(secretBytes); /// ``` - Future exportRawKey(); + Future exportRawKey() => _impl.exportRawKey(); /// Export [AesGcmSecretKey] as [JSON Web Key][1]. /// @@ -274,5 +280,5 @@ abstract class AesGcmSecretKey { /// ``` /// /// [1]: https://tools.ietf.org/html/rfc7517 - Future> exportJsonWebKey(); + Future> exportJsonWebKey() => _impl.exportJsonWebKey(); } From a0f19afde88c6027563be0056fc01ab671c2dba7 Mon Sep 17 00:00:00 2001 From: HamdaanAliQuatil Date: Wed, 14 Aug 2024 16:24:52 +0530 Subject: [PATCH 2/2] refactor: update aesgcm-secret-key --- lib/src/impl_ffi/impl_ffi.aescbc.dart | 2 +- lib/src/impl_ffi/impl_ffi.aesctr.dart | 2 +- lib/src/impl_ffi/impl_ffi.aesgcm.dart | 35 ++++++++++++++----- lib/src/impl_ffi/impl_ffi.dart | 3 ++ .../impl_interface/impl_interface.aescbc.dart | 2 +- .../impl_interface/impl_interface.aesctr.dart | 2 +- .../impl_interface/impl_interface.aesgcm.dart | 28 +++++++++++++++ lib/src/impl_interface/impl_interface.dart | 2 ++ lib/src/impl_js/impl_js.aesctr.dart | 2 +- lib/src/impl_js/impl_js.aesgcm.dart | 35 ++++++++++++++----- lib/src/impl_js/impl_js.dart | 3 ++ lib/src/impl_stub.dart | 8 ----- lib/src/impl_stub/impl_stub.aesgcm.dart | 31 ++++++++++++++++ lib/src/impl_stub/impl_stub.dart | 4 +++ lib/src/webcrypto/webcrypto.aesgcm.dart | 32 ++++++++++------- 15 files changed, 149 insertions(+), 42 deletions(-) create mode 100644 lib/src/impl_interface/impl_interface.aesgcm.dart create mode 100644 lib/src/impl_stub/impl_stub.aesgcm.dart diff --git a/lib/src/impl_ffi/impl_ffi.aescbc.dart b/lib/src/impl_ffi/impl_ffi.aescbc.dart index 34d9ae48..55a5e5a1 100644 --- a/lib/src/impl_ffi/impl_ffi.aescbc.dart +++ b/lib/src/impl_ffi/impl_ffi.aescbc.dart @@ -114,7 +114,7 @@ final class _StaticAesCbcSecretKeyImpl implements StaticAesCbcSecretKeyImpl { } } -final class _AesCbcSecretKeyImpl extends AesCbcSecretKeyImpl { +final class _AesCbcSecretKeyImpl implements AesCbcSecretKeyImpl { final Uint8List _key; _AesCbcSecretKeyImpl(this._key); diff --git a/lib/src/impl_ffi/impl_ffi.aesctr.dart b/lib/src/impl_ffi/impl_ffi.aesctr.dart index cfd8599f..709b5fff 100644 --- a/lib/src/impl_ffi/impl_ffi.aesctr.dart +++ b/lib/src/impl_ffi/impl_ffi.aesctr.dart @@ -221,7 +221,7 @@ final class _StaticAesCtrSecretKeyImpl implements StaticAesCtrSecretKeyImpl { } } -final class _AesCtrSecretKeyImpl extends AesCtrSecretKeyImpl { +final class _AesCtrSecretKeyImpl implements AesCtrSecretKeyImpl { final Uint8List _key; _AesCtrSecretKeyImpl(this._key); diff --git a/lib/src/impl_ffi/impl_ffi.aesgcm.dart b/lib/src/impl_ffi/impl_ffi.aesgcm.dart index 5adc463d..7922dd1a 100644 --- a/lib/src/impl_ffi/impl_ffi.aesgcm.dart +++ b/lib/src/impl_ffi/impl_ffi.aesgcm.dart @@ -16,19 +16,19 @@ part of 'impl_ffi.dart'; -Future aesGcm_importRawKey(List keyData) async => - _AesGcmSecretKey(_aesImportRawKey(keyData)); +Future aesGcm_importRawKey(List keyData) async => + _AesGcmSecretKeyImpl(_aesImportRawKey(keyData)); -Future aesGcm_importJsonWebKey( +Future aesGcm_importJsonWebKey( Map jwk, ) async => - _AesGcmSecretKey(_aesImportJwkKey( + _AesGcmSecretKeyImpl(_aesImportJwkKey( jwk, expectedJwkAlgSuffix: 'GCM', )); -Future aesGcm_generateKey(int length) async => - _AesGcmSecretKey(_aesGenerateKey(length)); +Future aesGcm_generateKey(int length) async => + _AesGcmSecretKeyImpl(_aesGenerateKey(length)); Future _aesGcmEncryptDecrypt( List key, @@ -111,9 +111,28 @@ Future _aesGcmEncryptDecrypt( }); } -class _AesGcmSecretKey implements AesGcmSecretKey { +final class _StaticAesGcmSecretKeyImpl implements StaticAesGcmSecretKeyImpl { + const _StaticAesGcmSecretKeyImpl(); + + @override + Future importRawKey(List keyData) async { + return await aesGcm_importRawKey(keyData); + } + + @override + Future importJsonWebKey(Map jwk) async { + return await aesGcm_importJsonWebKey(jwk); + } + + @override + Future generateKey(int length) async { + return await aesGcm_generateKey(length); + } +} + +final class _AesGcmSecretKeyImpl implements AesGcmSecretKeyImpl { final Uint8List _key; - _AesGcmSecretKey(this._key); + _AesGcmSecretKeyImpl(this._key); @override String toString() { diff --git a/lib/src/impl_ffi/impl_ffi.dart b/lib/src/impl_ffi/impl_ffi.dart index 95de3f58..e824e8ff 100644 --- a/lib/src/impl_ffi/impl_ffi.dart +++ b/lib/src/impl_ffi/impl_ffi.dart @@ -81,6 +81,9 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final aesCtrSecretKey = const _StaticAesCtrSecretKeyImpl(); + @override + final aesGcmSecretKey = const _StaticAesGcmSecretKeyImpl(); + @override final hmacSecretKey = const _StaticHmacSecretKeyImpl(); } diff --git a/lib/src/impl_interface/impl_interface.aescbc.dart b/lib/src/impl_interface/impl_interface.aescbc.dart index 47e5a382..543dc87d 100644 --- a/lib/src/impl_interface/impl_interface.aescbc.dart +++ b/lib/src/impl_interface/impl_interface.aescbc.dart @@ -20,7 +20,7 @@ abstract interface class StaticAesCbcSecretKeyImpl { Future generateKey(int length); } -abstract class AesCbcSecretKeyImpl { +abstract interface class AesCbcSecretKeyImpl { Future encryptBytes(List data, List iv); Future decryptBytes(List data, List iv); Stream encryptStream(Stream> data, List iv); diff --git a/lib/src/impl_interface/impl_interface.aesctr.dart b/lib/src/impl_interface/impl_interface.aesctr.dart index 9714eecc..65db9dce 100644 --- a/lib/src/impl_interface/impl_interface.aesctr.dart +++ b/lib/src/impl_interface/impl_interface.aesctr.dart @@ -20,7 +20,7 @@ abstract interface class StaticAesCtrSecretKeyImpl { Future generateKey(int length); } -abstract class AesCtrSecretKeyImpl { +abstract interface class AesCtrSecretKeyImpl { Future encryptBytes(List data, List counter, int length); Future decryptBytes(List data, List counter, int length); Stream encryptStream(Stream> data, List counter, int length); diff --git a/lib/src/impl_interface/impl_interface.aesgcm.dart b/lib/src/impl_interface/impl_interface.aesgcm.dart new file mode 100644 index 00000000..fa0afb88 --- /dev/null +++ b/lib/src/impl_interface/impl_interface.aesgcm.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 StaticAesGcmSecretKeyImpl { + Future importRawKey(List keyData); + Future importJsonWebKey(Map jwk); + Future generateKey(int length); +} + +abstract interface class AesGcmSecretKeyImpl { + Future encryptBytes(List data, List iv, {List? additionalData, int? tagLength}); + Future decryptBytes(List data, List iv, {List? additionalData, int? tagLength}); + Future exportRawKey(); + Future> exportJsonWebKey(); +} diff --git a/lib/src/impl_interface/impl_interface.dart b/lib/src/impl_interface/impl_interface.dart index bfc53b9c..27531c7e 100644 --- a/lib/src/impl_interface/impl_interface.dart +++ b/lib/src/impl_interface/impl_interface.dart @@ -23,6 +23,7 @@ import 'package:webcrypto/webcrypto.dart'; part 'impl_interface.aescbc.dart'; part 'impl_interface.aesctr.dart'; part 'impl_interface.hmac.dart'; +part 'impl_interface.aesgcm.dart'; /// Interface to be provided by platform implementations. /// @@ -43,5 +44,6 @@ part 'impl_interface.hmac.dart'; abstract interface class WebCryptoImpl { StaticAesCbcSecretKeyImpl get aesCbcSecretKey; StaticAesCtrSecretKeyImpl get aesCtrSecretKey; + StaticAesGcmSecretKeyImpl get aesGcmSecretKey; StaticHmacSecretKeyImpl get hmacSecretKey; } diff --git a/lib/src/impl_js/impl_js.aesctr.dart b/lib/src/impl_js/impl_js.aesctr.dart index 895701f5..3a97ff80 100644 --- a/lib/src/impl_js/impl_js.aesctr.dart +++ b/lib/src/impl_js/impl_js.aesctr.dart @@ -66,7 +66,7 @@ final class _StaticAesCtrSecretKeyImpl implements StaticAesCtrSecretKeyImpl { } } -final class _AesCtrSecretKeyImpl extends AesCtrSecretKeyImpl { +final class _AesCtrSecretKeyImpl implements AesCtrSecretKeyImpl { final subtle.JSCryptoKey _key; _AesCtrSecretKeyImpl(this._key); diff --git a/lib/src/impl_js/impl_js.aesgcm.dart b/lib/src/impl_js/impl_js.aesgcm.dart index d1dae77b..d630e15a 100644 --- a/lib/src/impl_js/impl_js.aesgcm.dart +++ b/lib/src/impl_js/impl_js.aesgcm.dart @@ -18,8 +18,8 @@ part of 'impl_js.dart'; const _aesGcmAlgorithm = subtle.Algorithm(name: 'AES-GCM'); -Future aesGcm_importRawKey(List keyData) async { - return _AesGcmSecretKey(await _importKey( +Future aesGcm_importRawKey(List keyData) async { + return _AesGcmSecretKeyImpl(await _importKey( 'raw', keyData, _aesGcmAlgorithm, @@ -28,10 +28,10 @@ Future aesGcm_importRawKey(List keyData) async { )); } -Future aesGcm_importJsonWebKey( +Future aesGcm_importJsonWebKey( Map jwk, ) async { - return _AesGcmSecretKey(await _importJsonWebKey( + return _AesGcmSecretKeyImpl(await _importJsonWebKey( jwk, _aesGcmAlgorithm, _usagesEncryptDecrypt, @@ -39,17 +39,36 @@ Future aesGcm_importJsonWebKey( )); } -Future aesGcm_generateKey(int length) async { - return _AesGcmSecretKey(await _generateKey( +Future aesGcm_generateKey(int length) async { + return _AesGcmSecretKeyImpl(await _generateKey( _aesGcmAlgorithm.update(length: length), _usagesEncryptDecrypt, 'secret', )); } -class _AesGcmSecretKey implements AesGcmSecretKey { +final class _StaticAesGcmSecretKeyImpl implements StaticAesGcmSecretKeyImpl { + const _StaticAesGcmSecretKeyImpl(); + + @override + Future importRawKey(List keyData) async { + return await aesGcm_importRawKey(keyData); + } + + @override + Future importJsonWebKey(Map jwk) async { + return await aesGcm_importJsonWebKey(jwk); + } + + @override + Future generateKey(int length) async { + return await aesGcm_generateKey(length); + } +} + +final class _AesGcmSecretKeyImpl implements AesGcmSecretKeyImpl { final subtle.JSCryptoKey _key; - _AesGcmSecretKey(this._key); + _AesGcmSecretKeyImpl(this._key); @override String toString() { diff --git a/lib/src/impl_js/impl_js.dart b/lib/src/impl_js/impl_js.dart index 6984219a..f969fa65 100644 --- a/lib/src/impl_js/impl_js.dart +++ b/lib/src/impl_js/impl_js.dart @@ -67,6 +67,9 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final aesCtrSecretKey = const _StaticAesCtrSecretKeyImpl(); + @override + final aesGcmSecretKey = const _StaticAesGcmSecretKeyImpl(); + @override final hmacSecretKey = const _StaticHmacSecretKeyImpl(); } diff --git a/lib/src/impl_stub.dart b/lib/src/impl_stub.dart index 18326ed8..f0455e9c 100644 --- a/lib/src/impl_stub.dart +++ b/lib/src/impl_stub.dart @@ -190,14 +190,6 @@ Future rsaOaepPublicKey_importJsonWebKey( //---------------------- AES-GCM -Future aesGcm_importRawKey(List keyData) => - throw _notImplemented; - -Future aesGcm_importJsonWebKey(Map jwk) => - throw _notImplemented; - -Future aesGcm_generateKey(int length) => throw _notImplemented; - //---------------------- ECDH Future ecdhPrivateKey_importPkcs8Key( diff --git a/lib/src/impl_stub/impl_stub.aesgcm.dart b/lib/src/impl_stub/impl_stub.aesgcm.dart new file mode 100644 index 00000000..7f98490e --- /dev/null +++ b/lib/src/impl_stub/impl_stub.aesgcm.dart @@ -0,0 +1,31 @@ +// 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 _StaticAesGcmSecretKeyImpl implements StaticAesGcmSecretKeyImpl { + const _StaticAesGcmSecretKeyImpl(); + + @override + Future importRawKey(List keyData) => + throw UnimplementedError('Not implemented'); + + @override + Future importJsonWebKey(Map jwk) => + throw UnimplementedError('Not implemented'); + + @override + Future generateKey(int length) => + throw UnimplementedError('Not implemented'); +} diff --git a/lib/src/impl_stub/impl_stub.dart b/lib/src/impl_stub/impl_stub.dart index 84ea0832..f6faa5e9 100644 --- a/lib/src/impl_stub/impl_stub.dart +++ b/lib/src/impl_stub/impl_stub.dart @@ -19,6 +19,7 @@ import 'package:webcrypto/webcrypto.dart'; part 'impl_stub.aescbc.dart'; part 'impl_stub.aesctr.dart'; +part 'impl_stub.aesgcm.dart'; part 'impl_stub.hmac.dart'; const WebCryptoImpl webCryptImpl = _WebCryptoImpl(); @@ -32,6 +33,9 @@ final class _WebCryptoImpl implements WebCryptoImpl { @override final aesCtrSecretKey = const _StaticAesCtrSecretKeyImpl(); + @override + final aesGcmSecretKey = const _StaticAesGcmSecretKeyImpl(); + @override final hmacSecretKey = const _StaticHmacSecretKeyImpl(); } diff --git a/lib/src/webcrypto/webcrypto.aesgcm.dart b/lib/src/webcrypto/webcrypto.aesgcm.dart index c27f09b1..f5acbf53 100644 --- a/lib/src/webcrypto/webcrypto.aesgcm.dart +++ b/lib/src/webcrypto/webcrypto.aesgcm.dart @@ -32,9 +32,10 @@ part of 'webcrypto.dart'; /// [1]: https://csrc.nist.gov/pubs/sp/800/38/d/final /// [2]: https://tools.ietf.org/html/rfc7517 /// [3]: https://en.wikipedia.org/wiki/Authenticated_encryption -@sealed -abstract class AesGcmSecretKey { - AesGcmSecretKey._(); // keep the constructor private. +final class AesGcmSecretKey { + final AesGcmSecretKeyImpl _impl; + + AesGcmSecretKey._(this._impl); // keep the constructor private. /// Import an [AesGcmSecretKey] from raw [keyData]. /// @@ -66,8 +67,9 @@ abstract class AesGcmSecretKey { /// // Decrypt message (requires the same iv) /// print(utf8.decode(await k.decryptBytes(c, iv))); // hello world /// ``` - static Future importRawKey(List keyData) { - return impl.aesGcm_importRawKey(keyData); + static Future importRawKey(List keyData) async { + final impl = await webCryptImpl.aesGcmSecretKey.importRawKey(keyData); + return AesGcmSecretKey._(impl); } /// Import an [AesGcmSecretKey] from [JSON Web Key][1]. @@ -102,8 +104,9 @@ abstract class AesGcmSecretKey { /// ``` /// /// [1]: https://tools.ietf.org/html/rfc7517 - static Future importJsonWebKey(Map jwk) { - return impl.aesGcm_importJsonWebKey(jwk); + static Future importJsonWebKey(Map jwk) async { + final impl = await webCryptImpl.aesGcmSecretKey.importJsonWebKey(jwk); + return AesGcmSecretKey._(impl); } /// Generate a random [AesGcmSecretKey]. @@ -122,8 +125,9 @@ abstract class AesGcmSecretKey { /// // Generate a new random AES-GCM secret key for AES-256. /// final key = await AesGcmSecretKey.generate(256); /// ``` - static Future generateKey(int length) { - return impl.aesGcm_generateKey(length); + static Future generateKey(int length) async { + final impl = await webCryptImpl.aesGcmSecretKey.generateKey(length); + return AesGcmSecretKey._(impl); } /// Encrypt [data] with this [AesCbcSecretKey] using AES in @@ -218,7 +222,8 @@ abstract class AesGcmSecretKey { List iv, { List? additionalData, int? tagLength = 128, - }); + }) => + _impl.encryptBytes(data, iv, additionalData: additionalData, tagLength: tagLength); // TODO: Document this method, notice that [data] must be concatenation of // ciphertext and authentication tag. @@ -228,7 +233,8 @@ abstract class AesGcmSecretKey { List iv, { List? additionalData, int? tagLength = 128, - }); + }) => + _impl.decryptBytes(data, iv, additionalData: additionalData, tagLength: tagLength); /// Export [AesGcmSecretKey] as raw bytes. /// @@ -250,7 +256,7 @@ abstract class AesGcmSecretKey { /// // If we wanted to we could import the key as follows: /// // key = await AesGcmSecretKey.importRawKey(secretBytes); /// ``` - Future exportRawKey(); + Future exportRawKey() => _impl.exportRawKey(); /// Export [AesGcmSecretKey] as [JSON Web Key][1]. /// @@ -274,5 +280,5 @@ abstract class AesGcmSecretKey { /// ``` /// /// [1]: https://tools.ietf.org/html/rfc7517 - Future> exportJsonWebKey(); + Future> exportJsonWebKey() => _impl.exportJsonWebKey(); }