Skip to content

Commit c178c0b

Browse files
Refactor Hash Class (#171)
* refactor: update hash and remove circular imports * style: format dart code * Update lib/src/impl_ffi/impl_ffi.digest.dart Co-authored-by: Jonas Finnemann Jensen <[email protected]> * Update lib/src/impl_ffi/impl_ffi.digest.dart Co-authored-by: Jonas Finnemann Jensen <[email protected]> * fix: add getters for hash and perform cleanup * Update lib/src/impl_ffi/impl_ffi.digest.dart Co-authored-by: Jonas Finnemann Jensen <[email protected]> * Update lib/src/webcrypto/webcrypto.digest.dart Co-authored-by: Jonas Finnemann Jensen <[email protected]> * Update lib/src/impl_js/impl_js.digest.dart Co-authored-by: Jonas Finnemann Jensen <[email protected]> * fix: add constant implementation for public api * docs: add documentation for getters in hashimpl --------- Co-authored-by: Jonas Finnemann Jensen <[email protected]>
1 parent 25db3a0 commit c178c0b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+457
-355
lines changed

lib/src/impl_ffi/impl_ffi.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,16 @@ final class _WebCryptoImpl implements WebCryptoImpl {
110110

111111
@override
112112
final rsaSsaPkcs1v15PublicKey = const _StaticRsaSsaPkcs1V15PublicKeyImpl();
113+
114+
@override
115+
final sha1 = const _Sha1();
116+
117+
@override
118+
final sha256 = const _Sha256();
119+
120+
@override
121+
final sha384 = const _Sha384();
122+
123+
@override
124+
final sha512 = const _Sha512();
113125
}

lib/src/impl_ffi/impl_ffi.digest.dart

Lines changed: 103 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,15 @@
1414

1515
part of 'impl_ffi.dart';
1616

17-
abstract class _Hash implements Hash {
18-
const _Hash();
17+
abstract class _HashImpl implements HashImpl {
18+
const _HashImpl();
1919

20-
factory _Hash.fromHash(Hash hash) {
21-
if (hash is _Hash) {
20+
factory _HashImpl.fromHash(HashImpl hash) {
21+
if (hash is _HashImpl) {
2222
return hash;
2323
}
24-
throw ArgumentError.value(
25-
hash,
26-
'hash',
27-
'Custom implementations of Hash is not supported',
28-
);
24+
throw AssertionError(
25+
'Custom implementations of HashImpl are not supported.');
2926
}
3027

3128
@protected
@@ -62,39 +59,127 @@ abstract class _Hash implements Hash {
6259
return out.copy(size);
6360
});
6461
}
62+
63+
/// Algorithm (`alg` for JWK) when this hash algorithm is used in an HMAC.
64+
///
65+
/// For SHA-1, it returns 'HS1'.
66+
/// For SHA-256, it returns 'HS256'.
67+
/// For SHA-384, it returns 'HS384'.
68+
/// For SHA-512, it returns 'HS512'.
69+
///
70+
/// See canonical registry in:
71+
/// https://www.iana.org/assignments/jose/jose.xhtml
72+
String get hmacJwkAlg;
73+
74+
/// Algorithm (`alg` for JWK) when this hash algorithm is used in RSA-OAEP.
75+
///
76+
/// For SHA-1, it returns 'RSA-OAEP-1'.
77+
/// For SHA-256, it returns 'RSA-OAEP-256'.
78+
/// For SHA-384, it returns 'RSA-OAEP-384'.
79+
/// For SHA-512, it returns 'RSA-OAEP-512'.
80+
///
81+
/// See canonical registry in:
82+
/// https://www.iana.org/assignments/jose/jose.xhtml
83+
String get rsaOaepJwkAlg;
84+
85+
/// Algorithm (`alg` for JWK) when this hash algorithm is used in RSA-PSS.
86+
///
87+
/// For SHA-1, it returns 'PS1'.
88+
/// For SHA-256, it returns 'PS256'.
89+
/// For SHA-384, it returns 'PS384'.
90+
/// For SHA-512, it returns 'PS512'.
91+
///
92+
/// See canonical registry in:
93+
/// https://www.iana.org/assignments/jose/jose.xhtml
94+
String get rsaPssJwkAlg;
95+
96+
/// Algorithm (`alg` for JWK) when this hash algorithm is used in RSASSA-PKCS1-v1_5.
97+
///
98+
/// For SHA-1, it returns 'RS1'.
99+
/// For SHA-256, it returns 'RS256'.
100+
/// For SHA-384, it returns 'RS384'.
101+
/// For SHA-512, it returns 'RS512'.
102+
///
103+
/// See canonical registry in:
104+
/// https://www.iana.org/assignments/jose/jose.xhtml
105+
String get rsassaPkcs1V15JwkAlg;
65106
}
66107

67-
class _Sha1 extends _Hash {
108+
final class _Sha1 extends _HashImpl {
68109
const _Sha1();
69110

111+
@override
112+
String get hmacJwkAlg => 'HS1';
113+
114+
@override
115+
String get rsaOaepJwkAlg => 'RSA-OAEP-1';
116+
117+
@override
118+
String get rsaPssJwkAlg => 'PS1';
119+
120+
@override
121+
String get rsassaPkcs1V15JwkAlg => 'RS1';
122+
70123
@override
71124
ffi.Pointer<EVP_MD> Function() get _algorithm => ssl.EVP_sha1;
72125
}
73126

74-
class _Sha256 extends _Hash {
127+
final class _Sha256 extends _HashImpl {
75128
const _Sha256();
76129

130+
@override
131+
String get hmacJwkAlg => 'HS256';
132+
133+
@override
134+
String get rsaOaepJwkAlg => 'RSA-OAEP-256';
135+
136+
@override
137+
String get rsaPssJwkAlg => 'PS256';
138+
139+
@override
140+
String get rsassaPkcs1V15JwkAlg => 'RS256';
141+
77142
@override
78143
ffi.Pointer<EVP_MD> Function() get _algorithm => ssl.EVP_sha256;
79144
}
80145

81-
class _Sha384 extends _Hash {
146+
final class _Sha384 extends _HashImpl {
82147
const _Sha384();
83148

149+
@override
150+
String get hmacJwkAlg => 'HS384';
151+
152+
@override
153+
String get rsaOaepJwkAlg => 'RSA-OAEP-384';
154+
155+
@override
156+
String get rsaPssJwkAlg => 'PS384';
157+
158+
@override
159+
String get rsassaPkcs1V15JwkAlg => 'RS384';
160+
84161
@override
85162
ffi.Pointer<EVP_MD> Function() get _algorithm => ssl.EVP_sha384;
86163
}
87164

88-
class _Sha512 extends _Hash {
165+
final class _Sha512 extends _HashImpl {
89166
const _Sha512();
90167

168+
@override
169+
String get hmacJwkAlg => 'HS512';
170+
171+
@override
172+
String get rsaOaepJwkAlg => 'RSA-OAEP-512';
173+
174+
@override
175+
String get rsaPssJwkAlg => 'PS512';
176+
177+
@override
178+
String get rsassaPkcs1V15JwkAlg => 'RS512';
179+
91180
@override
92181
ffi.Pointer<EVP_MD> Function() get _algorithm => ssl.EVP_sha512;
93182
}
94183

95-
const Hash sha1 = _Sha1();
96-
const Hash sha256 = _Sha256();
97-
const Hash sha384 = _Sha384();
98-
const Hash sha512 = _Sha512();
99184
// Note: Before adding new hash implementations, make sure to update all the
100-
// places that does if (hash == Hash.shaXXX) ...
185+
// places that does if (hash == HashImpl.shaXXX) ...

lib/src/impl_ffi/impl_ffi.ecdsa.dart

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,12 @@ final class _EcdsaPrivateKeyImpl implements EcdsaPrivateKeyImpl {
218218
}
219219

220220
@override
221-
Future<Uint8List> signBytes(List<int> data, Hash hash) =>
221+
Future<Uint8List> signBytes(List<int> data, HashImpl hash) =>
222222
signStream(Stream.value(data), hash);
223223

224224
@override
225-
Future<Uint8List> signStream(Stream<List<int>> data, Hash hash) async {
226-
final md = _Hash.fromHash(hash)._md;
225+
Future<Uint8List> signStream(Stream<List<int>> data, HashImpl hash) async {
226+
final md = _HashImpl.fromHash(hash)._md;
227227
final sig = await _signStream(_key, md, data);
228228
return _convertEcdsaDerSignatureToWebCryptoSignature(_key, sig);
229229
}
@@ -268,16 +268,17 @@ final class _EcdsaPublicKeyImpl implements EcdsaPublicKeyImpl {
268268
}
269269

270270
@override
271-
Future<bool> verifyBytes(List<int> signature, List<int> data, Hash hash) =>
271+
Future<bool> verifyBytes(
272+
List<int> signature, List<int> data, HashImpl hash) =>
272273
verifyStream(signature, Stream.value(data), hash);
273274

274275
@override
275276
Future<bool> verifyStream(
276277
List<int> signature,
277278
Stream<List<int>> data,
278-
Hash hash,
279+
HashImpl hash,
279280
) async {
280-
final md = _Hash.fromHash(hash)._md;
281+
final md = _HashImpl.fromHash(hash)._md;
281282

282283
// Convert to DER signature
283284
final sig = _convertEcdsaWebCryptoSignatureToDerSignature(_key, signature);

lib/src/impl_ffi/impl_ffi.hkdf.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ final class _HkdfSecretKeyImpl implements HkdfSecretKeyImpl {
4141
@override
4242
Future<Uint8List> deriveBits(
4343
int length,
44-
Hash hash,
44+
HashImpl hash,
4545
List<int> salt,
4646
List<int> info,
4747
) async {
4848
if (length < 0) {
4949
throw ArgumentError.value(length, 'length', 'must be positive integer');
5050
}
51-
final md = _Hash.fromHash(hash)._md;
51+
final md = _HashImpl.fromHash(hash)._md;
5252

5353
// Mirroring limitations in chromium:
5454
// https://chromium.googlesource.com/chromium/src/+/43d62c50b705f88c67b14539e91fd8fd017f70c4/components/webcrypto/algorithms/hkdf.cc#74

lib/src/impl_ffi/impl_ffi.hmac.dart

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,40 +32,23 @@ Uint8List _asUint8ListZeroedToBitLength(List<int> data, [int? lengthInBits]) {
3232
return buf;
3333
}
3434

35-
String _hmacJwkAlgFromHash(_Hash hash) {
36-
if (hash == Hash.sha1) {
37-
return 'HS1';
38-
}
39-
if (hash == Hash.sha256) {
40-
return 'HS256';
41-
}
42-
if (hash == Hash.sha384) {
43-
return 'HS384';
44-
}
45-
if (hash == Hash.sha512) {
46-
return 'HS512';
47-
}
48-
assert(false); // This should never happen!
49-
throw UnsupportedError('hash is not supported');
50-
}
51-
5235
Future<HmacSecretKeyImpl> hmacSecretKey_importRawKey(
5336
List<int> keyData,
54-
Hash hash, {
37+
HashImpl hash, {
5538
int? length,
5639
}) async {
5740
return _HmacSecretKeyImpl(
5841
_asUint8ListZeroedToBitLength(keyData, length),
59-
_Hash.fromHash(hash),
42+
_HashImpl.fromHash(hash),
6043
);
6144
}
6245

6346
Future<HmacSecretKeyImpl> hmacSecretKey_importJsonWebKey(
6447
Map<String, dynamic> jwk,
65-
Hash hash, {
48+
HashImpl hash, {
6649
int? length,
6750
}) async {
68-
final h = _Hash.fromHash(hash);
51+
final h = _HashImpl.fromHash(hash);
6952
final k = JsonWebKey.fromJson(jwk);
7053

7154
void checkJwk(bool condition, String prop, String message) =>
@@ -74,7 +57,7 @@ Future<HmacSecretKeyImpl> hmacSecretKey_importJsonWebKey(
7457
checkJwk(k.kty == 'oct', 'kty', 'must be "oct"');
7558
checkJwk(k.k != null, 'k', 'must be present');
7659
checkJwk(k.use == null || k.use == 'sig', 'use', 'must be "sig", if present');
77-
final expectedAlg = _hmacJwkAlgFromHash(h);
60+
final expectedAlg = h.hmacJwkAlg;
7861
checkJwk(
7962
k.alg == null || k.alg == expectedAlg,
8063
'alg',
@@ -87,10 +70,10 @@ Future<HmacSecretKeyImpl> hmacSecretKey_importJsonWebKey(
8770
}
8871

8972
Future<HmacSecretKeyImpl> hmacSecretKey_generateKey(
90-
Hash hash, {
73+
HashImpl hash, {
9174
int? length,
9275
}) async {
93-
final h = _Hash.fromHash(hash);
76+
final h = _HashImpl.fromHash(hash);
9477
length ??= ssl.EVP_MD_size(h._md) * 8;
9578
final keyData = Uint8List((length / 8).ceil());
9679
fillRandomBytes(keyData);
@@ -105,26 +88,26 @@ final class _StaticHmacSecretKeyImpl implements StaticHmacSecretKeyImpl {
10588
const _StaticHmacSecretKeyImpl();
10689

10790
@override
108-
Future<HmacSecretKeyImpl> importRawKey(List<int> keyData, Hash hash,
91+
Future<HmacSecretKeyImpl> importRawKey(List<int> keyData, HashImpl hash,
10992
{int? length}) {
11093
return hmacSecretKey_importRawKey(keyData, hash, length: length);
11194
}
11295

11396
@override
11497
Future<HmacSecretKeyImpl> importJsonWebKey(
115-
Map<String, dynamic> jwk, Hash hash,
98+
Map<String, dynamic> jwk, HashImpl hash,
11699
{int? length}) {
117100
return hmacSecretKey_importJsonWebKey(jwk, hash, length: length);
118101
}
119102

120103
@override
121-
Future<HmacSecretKeyImpl> generateKey(Hash hash, {int? length = 32}) {
104+
Future<HmacSecretKeyImpl> generateKey(HashImpl hash, {int? length = 32}) {
122105
return hmacSecretKey_generateKey(hash, length: length);
123106
}
124107
}
125108

126109
final class _HmacSecretKeyImpl implements HmacSecretKeyImpl {
127-
final _Hash _hash;
110+
final _HashImpl _hash;
128111
final Uint8List _keyData;
129112

130113
_HmacSecretKeyImpl(this._keyData, this._hash);
@@ -186,7 +169,7 @@ final class _HmacSecretKeyImpl implements HmacSecretKeyImpl {
186169
return JsonWebKey(
187170
kty: 'oct',
188171
use: 'sig',
189-
alg: _hmacJwkAlgFromHash(_hash),
172+
alg: _hash.hmacJwkAlg,
190173
k: _jwkEncodeBase64UrlNoPadding(_keyData),
191174
).toJson();
192175
}

lib/src/impl_ffi/impl_ffi.pbkdf2.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ final class _Pbkdf2SecretKeyImpl implements Pbkdf2SecretKeyImpl {
4343
@override
4444
Future<Uint8List> deriveBits(
4545
int length,
46-
Hash hash,
46+
HashImpl hash,
4747
List<int> salt,
4848
int iterations,
4949
) async {
5050
if (length < 0) {
5151
throw ArgumentError.value(length, 'length', 'must be positive integer');
5252
}
53-
final md = _Hash.fromHash(hash)._md;
53+
final md = _HashImpl.fromHash(hash)._md;
5454

5555
// Mirroring limitations in chromium:
5656
// https://chromium.googlesource.com/chromium/src/+/43d62c50b705f88c67b14539e91fd8fd017f70c4/components/webcrypto/algorithms/pbkdf2.cc#75

0 commit comments

Comments
 (0)