Skip to content
3 changes: 3 additions & 0 deletions lib/src/impl_ffi/impl_ffi.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,7 @@ final class _WebCryptoImpl implements WebCryptoImpl {

@override
final sha512 = const _Sha512();

@override
final random = const _RandomImpl();
}
25 changes: 15 additions & 10 deletions lib/src/impl_ffi/impl_ffi.random.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,20 @@

part of 'impl_ffi.dart';

void fillRandomBytes(TypedData destination) {
return _Scope.sync((scope) {
final dest = destination.buffer.asUint8List(
destination.offsetInBytes,
destination.lengthInBytes,
);
final class _RandomImpl implements RandomImpl {
const _RandomImpl();

final out = scope<ffi.Uint8>(dest.length);
_checkOp(ssl.RAND_bytes(out, dest.length) == 1);
dest.setAll(0, out.asTypedList(dest.length));
});
@override
void fillRandomBytes(TypedData destination) {
return _Scope.sync((scope) {
final dest = destination.buffer.asUint8List(
destination.offsetInBytes,
destination.lengthInBytes,
);

final out = scope<ffi.Uint8>(dest.length);
_checkOp(ssl.RAND_bytes(out, dest.length) == 1);
dest.setAll(0, out.asTypedList(dest.length));
});
}
}
2 changes: 2 additions & 0 deletions lib/src/impl_interface/impl_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ part 'impl_interface.hkdf.dart';
part 'impl_interface.rsapss.dart';
part 'impl_interface.rsassapkcs1v15.dart';
part 'impl_interface.digest.dart';
part 'impl_interface.random.dart';

/// A key-pair as returned from key generation.
class KeyPair<S, T> {
Expand Down Expand Up @@ -99,4 +100,5 @@ abstract interface class WebCryptoImpl {
HashImpl get sha256;
HashImpl get sha384;
HashImpl get sha512;
RandomImpl get random;
}
19 changes: 19 additions & 0 deletions lib/src/impl_interface/impl_interface.random.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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 RandomImpl {
void fillRandomBytes(TypedData destination);
}
3 changes: 3 additions & 0 deletions lib/src/impl_js/impl_js.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,7 @@ final class _WebCryptoImpl implements WebCryptoImpl {

@override
final sha512 = const _HashImpl('SHA-512');

@override
final random = const _RandomImpl();
}
15 changes: 10 additions & 5 deletions lib/src/impl_js/impl_js.random.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@

part of 'impl_js.dart';

void fillRandomBytes(TypedData destination) {
try {
subtle.getRandomValues(destination);
} on subtle.JSDomException catch (e) {
throw _translateDomException(e);
final class _RandomImpl implements RandomImpl {
const _RandomImpl();

@override
void fillRandomBytes(TypedData destination) {
try {
subtle.getRandomValues(destination);
} on subtle.JSDomException catch (e) {
throw _translateDomException(e);
}
}
}
47 changes: 0 additions & 47 deletions lib/src/impl_stub.dart

This file was deleted.

4 changes: 4 additions & 0 deletions lib/src/impl_stub/impl_stub.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ part 'impl_stub.hkdf.dart';
part 'impl_stub.rsapss.dart';
part 'impl_stub.rsassapkcs1v15.dart';
part 'impl_stub.digest.dart';
part 'impl_stub.random.dart';

const WebCryptoImpl webCryptImpl = _WebCryptoImpl();

Expand Down Expand Up @@ -95,4 +96,7 @@ final class _WebCryptoImpl implements WebCryptoImpl {

@override
final sha512 = const _HashImpl();

@override
final random = const _RandomImpl();
}
4 changes: 2 additions & 2 deletions lib/src/impl_stub/impl_stub.ecdsa.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

part of 'impl_stub.dart';

class _StaticEcdsaPrivateKeyImpl implements StaticEcdsaPrivateKeyImpl {
final class _StaticEcdsaPrivateKeyImpl implements StaticEcdsaPrivateKeyImpl {
const _StaticEcdsaPrivateKeyImpl();

@override
Expand All @@ -38,7 +38,7 @@ class _StaticEcdsaPrivateKeyImpl implements StaticEcdsaPrivateKeyImpl {
throw UnimplementedError('Not implemented');
}

class _StaticEcdsaPublicKeyImpl implements StaticEcdsaPublicKeyImpl {
final class _StaticEcdsaPublicKeyImpl implements StaticEcdsaPublicKeyImpl {
const _StaticEcdsaPublicKeyImpl();

@override
Expand Down
24 changes: 24 additions & 0 deletions lib/src/impl_stub/impl_stub.random.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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 _RandomImpl implements RandomImpl {
const _RandomImpl();

@override
void fillRandomBytes(TypedData destination) {
throw UnimplementedError('Not implemented');
}
}
3 changes: 0 additions & 3 deletions lib/src/webcrypto/webcrypto.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ import 'dart:convert';
import 'dart:async';
import 'dart:typed_data';
import '../impl_interface/impl_interface.dart';
import '../impl_stub.dart'
if (dart.library.ffi) '../impl_ffi/impl_ffi.dart'
if (dart.library.js) '../impl_js/impl_js.dart' as impl;
import '../impl_stub/impl_stub.dart'
if (dart.library.ffi) '../impl_ffi/impl_ffi.dart'
if (dart.library.js) '../impl_js/impl_js.dart' show webCryptImpl;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/webcrypto/webcrypto.random.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,5 @@ void fillRandomBytes(
'array of more than 65536 bytes is not allowed');
}

impl.fillRandomBytes(destination);
webCryptImpl.random.fillRandomBytes(destination);
}
14 changes: 9 additions & 5 deletions test/crypto_subtle_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import 'dart:typed_data';

import 'package:test/test.dart';
import 'package:webcrypto/src/crypto_subtle.dart' as subtle;
import 'package:webcrypto/src/impl_js/impl_js.dart';

void main() {
group('fillRandomBytes', () {
Expand All @@ -30,7 +29,7 @@ void main() {
data.every((e) => e == 0),
isTrue,
);
fillRandomBytes(data);
subtle.window.crypto.getRandomValues(data.toJS);
expect(
data.any((e) => e != 0),
isTrue,
Expand All @@ -39,16 +38,21 @@ void main() {

test('Uint8List: too long', () {
expect(
() => fillRandomBytes(Uint8List(1000000)),
() => subtle.window.crypto.getRandomValues(Uint8List(1000000).toJS),
throwsA(
isA<ArgumentError>(),
isA<subtle.JSDomException>().having(
(e) => e.name,
'name',
'QuotaExceededError',
),
),
);
});

test('Uint64List: not supported type', () {
expect(
() => fillRandomBytes(Uint64List(32)),
() => subtle.window.crypto
.getRandomValues(Uint8List.view(Uint64List(32).buffer).toJS),
throwsA(
isA<UnsupportedError>(),
),
Expand Down
Loading