style: fix format and lint
This commit is contained in:
parent
ac9df588d1
commit
545ce26e39
|
|
@ -101,7 +101,8 @@ class SSSS {
|
||||||
mac: base64.encode(hmac.bytes));
|
mac: base64.encode(hmac.bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<String> decryptAes(_Encrypted data, Uint8List key, String name) async {
|
static Future<String> decryptAes(
|
||||||
|
_Encrypted data, Uint8List key, String name) async {
|
||||||
final keys = deriveKeys(key, name);
|
final keys = deriveKeys(key, name);
|
||||||
final cipher = base64.decode(data.ciphertext);
|
final cipher = base64.decode(data.ciphertext);
|
||||||
final hmac = base64
|
final hmac = base64
|
||||||
|
|
@ -110,7 +111,8 @@ class SSSS {
|
||||||
if (hmac != data.mac.replaceAll(RegExp(r'=+$'), '')) {
|
if (hmac != data.mac.replaceAll(RegExp(r'=+$'), '')) {
|
||||||
throw Exception('Bad MAC');
|
throw Exception('Bad MAC');
|
||||||
}
|
}
|
||||||
final decipher = await uc.aesCtr.encrypt(cipher, keys.aesKey, base64.decode(data.iv));
|
final decipher =
|
||||||
|
await uc.aesCtr.encrypt(cipher, keys.aesKey, base64.decode(data.iv));
|
||||||
return String.fromCharCodes(decipher);
|
return String.fromCharCodes(decipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,11 +149,13 @@ class SSSS {
|
||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<Uint8List> keyFromPassphrase(String passphrase, PassphraseInfo info) async {
|
static Future<Uint8List> keyFromPassphrase(
|
||||||
|
String passphrase, PassphraseInfo info) async {
|
||||||
if (info.algorithm != AlgorithmTypes.pbkdf2) {
|
if (info.algorithm != AlgorithmTypes.pbkdf2) {
|
||||||
throw Exception('Unknown algorithm');
|
throw Exception('Unknown algorithm');
|
||||||
}
|
}
|
||||||
return await uc.pbkdf2(utf8.encode(passphrase), utf8.encode(info.salt), uc.sha512, info.iterations, info.bits ?? 256);
|
return await uc.pbkdf2(utf8.encode(passphrase), utf8.encode(info.salt),
|
||||||
|
uc.sha512, info.iterations, info.bits ?? 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValidator(String type, FutureOr<bool> Function(String) validator) {
|
void setValidator(String type, FutureOr<bool> Function(String) validator) {
|
||||||
|
|
@ -194,7 +198,8 @@ class SSSS {
|
||||||
content.passphrase.algorithm = AlgorithmTypes.pbkdf2;
|
content.passphrase.algorithm = AlgorithmTypes.pbkdf2;
|
||||||
content.passphrase.salt = base64
|
content.passphrase.salt = base64
|
||||||
.encode(uc.secureRandomBytes(pbkdf2SaltLength)); // generate salt
|
.encode(uc.secureRandomBytes(pbkdf2SaltLength)); // generate salt
|
||||||
content.passphrase.iterations = pbkdf2DefaultIterations;;
|
content.passphrase.iterations = pbkdf2DefaultIterations;
|
||||||
|
;
|
||||||
content.passphrase.bits = ssssKeyLength * 8;
|
content.passphrase.bits = ssssKeyLength * 8;
|
||||||
privateKey = await runInBackground(
|
privateKey = await runInBackground(
|
||||||
_keyFromPassphrase,
|
_keyFromPassphrase,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,8 @@ Future<EncryptedFile> encryptFile(Uint8List input) async {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> decryptFile(EncryptedFile input) async {
|
Future<Uint8List> decryptFile(EncryptedFile input) async {
|
||||||
if (base64.encode(await sha256(input.data)) != base64.normalize(input.sha256)) {
|
if (base64.encode(await sha256(input.data)) !=
|
||||||
|
base64.normalize(input.sha256)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,70 +7,100 @@ final libcrypto = Platform.isIOS
|
||||||
? 'libcrypto.so'
|
? 'libcrypto.so'
|
||||||
: Platform.isWindows
|
: Platform.isWindows
|
||||||
? 'libcrypto.dll'
|
? 'libcrypto.dll'
|
||||||
: Platform.isMacOS ? 'libcrypto.1.1.dylib' : 'libcrypto.so.1.1');
|
: Platform.isMacOS
|
||||||
|
? 'libcrypto.1.1.dylib'
|
||||||
|
: 'libcrypto.so.1.1');
|
||||||
|
|
||||||
final PKCS5_PBKDF2_HMAC = libcrypto.lookupFunction<
|
final PKCS5_PBKDF2_HMAC = libcrypto.lookupFunction<
|
||||||
IntPtr Function(Pointer<Uint8> pass, IntPtr passlen, Pointer<Uint8> salt, IntPtr saltlen, IntPtr iter, Pointer<NativeType> digest, IntPtr keylen, Pointer<Uint8> out),
|
IntPtr Function(
|
||||||
int Function(Pointer<Uint8> pass, int passlen, Pointer<Uint8> salt, int saltlen, int iter, Pointer<NativeType> digest, int keylen, Pointer<Uint8> out)
|
Pointer<Uint8> pass,
|
||||||
>('PKCS5_PBKDF2_HMAC');
|
IntPtr passlen,
|
||||||
|
Pointer<Uint8> salt,
|
||||||
|
IntPtr saltlen,
|
||||||
|
IntPtr iter,
|
||||||
|
Pointer<NativeType> digest,
|
||||||
|
IntPtr keylen,
|
||||||
|
Pointer<Uint8> out),
|
||||||
|
int Function(
|
||||||
|
Pointer<Uint8> pass,
|
||||||
|
int passlen,
|
||||||
|
Pointer<Uint8> salt,
|
||||||
|
int saltlen,
|
||||||
|
int iter,
|
||||||
|
Pointer<NativeType> digest,
|
||||||
|
int keylen,
|
||||||
|
Pointer<Uint8> out)>('PKCS5_PBKDF2_HMAC');
|
||||||
|
|
||||||
final EVP_sha1 = libcrypto.lookupFunction<
|
final EVP_sha1 = libcrypto.lookupFunction<Pointer<NativeType> Function(),
|
||||||
Pointer<NativeType> Function(),
|
Pointer<NativeType> Function()>('EVP_sha1');
|
||||||
Pointer<NativeType> Function()
|
|
||||||
>('EVP_sha1');
|
|
||||||
|
|
||||||
final EVP_sha256 = libcrypto.lookupFunction<
|
final EVP_sha256 = libcrypto.lookupFunction<Pointer<NativeType> Function(),
|
||||||
Pointer<NativeType> Function(),
|
Pointer<NativeType> Function()>('EVP_sha256');
|
||||||
Pointer<NativeType> Function()
|
|
||||||
>('EVP_sha256');
|
|
||||||
|
|
||||||
final EVP_sha512 = libcrypto.lookupFunction<
|
final EVP_sha512 = libcrypto.lookupFunction<Pointer<NativeType> Function(),
|
||||||
Pointer<NativeType> Function(),
|
Pointer<NativeType> Function()>('EVP_sha512');
|
||||||
Pointer<NativeType> Function()
|
|
||||||
>('EVP_sha512');
|
|
||||||
|
|
||||||
final EVP_aes_128_ctr = libcrypto.lookupFunction<
|
final EVP_aes_128_ctr = libcrypto.lookupFunction<Pointer<NativeType> Function(),
|
||||||
Pointer<NativeType> Function(),
|
Pointer<NativeType> Function()>('EVP_aes_128_ctr');
|
||||||
Pointer<NativeType> Function()
|
|
||||||
>('EVP_aes_128_ctr');
|
|
||||||
|
|
||||||
final EVP_aes_256_ctr = libcrypto.lookupFunction<
|
final EVP_aes_256_ctr = libcrypto.lookupFunction<Pointer<NativeType> Function(),
|
||||||
Pointer<NativeType> Function(),
|
Pointer<NativeType> Function()>('EVP_aes_256_ctr');
|
||||||
Pointer<NativeType> Function()
|
|
||||||
>('EVP_aes_256_ctr');
|
|
||||||
|
|
||||||
final EVP_CIPHER_CTX_new = libcrypto.lookupFunction<
|
final EVP_CIPHER_CTX_new = libcrypto.lookupFunction<
|
||||||
Pointer<NativeType> Function(),
|
Pointer<NativeType> Function(),
|
||||||
Pointer<NativeType> Function()
|
Pointer<NativeType> Function()>('EVP_CIPHER_CTX_new');
|
||||||
>('EVP_CIPHER_CTX_new');
|
|
||||||
|
|
||||||
final EVP_EncryptInit_ex = libcrypto.lookupFunction<
|
final EVP_EncryptInit_ex = libcrypto.lookupFunction<
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<NativeType> alg, Pointer<NativeType> some, Pointer<Uint8> key, Pointer<Uint8> iv),
|
Pointer<NativeType> Function(
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<NativeType> alg, Pointer<NativeType> some, Pointer<Uint8> key, Pointer<Uint8> iv)
|
Pointer<NativeType> ctx,
|
||||||
>('EVP_EncryptInit_ex');
|
Pointer<NativeType> alg,
|
||||||
|
Pointer<NativeType> some,
|
||||||
|
Pointer<Uint8> key,
|
||||||
|
Pointer<Uint8> iv),
|
||||||
|
Pointer<NativeType> Function(
|
||||||
|
Pointer<NativeType> ctx,
|
||||||
|
Pointer<NativeType> alg,
|
||||||
|
Pointer<NativeType> some,
|
||||||
|
Pointer<Uint8> key,
|
||||||
|
Pointer<Uint8> iv)>('EVP_EncryptInit_ex');
|
||||||
|
|
||||||
final EVP_EncryptUpdate = libcrypto.lookupFunction<
|
final EVP_EncryptUpdate = libcrypto.lookupFunction<
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<Uint8> output, Pointer<IntPtr> outputLen, Pointer<Uint8> input, IntPtr inputLen),
|
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<Uint8> output,
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<Uint8> output, Pointer<IntPtr> outputLen, Pointer<Uint8> input, int inputLen)
|
Pointer<IntPtr> outputLen, Pointer<Uint8> input, IntPtr inputLen),
|
||||||
>('EVP_EncryptUpdate');
|
Pointer<NativeType> Function(
|
||||||
|
Pointer<NativeType> ctx,
|
||||||
|
Pointer<Uint8> output,
|
||||||
|
Pointer<IntPtr> outputLen,
|
||||||
|
Pointer<Uint8> input,
|
||||||
|
int inputLen)>('EVP_EncryptUpdate');
|
||||||
|
|
||||||
final EVP_EncryptFinal_ex = libcrypto.lookupFunction<
|
final EVP_EncryptFinal_ex = libcrypto.lookupFunction<
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<Uint8> data, Pointer<IntPtr> len),
|
Pointer<NativeType> Function(
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<Uint8> data, Pointer<IntPtr> len)
|
Pointer<NativeType> ctx, Pointer<Uint8> data, Pointer<IntPtr> len),
|
||||||
>('EVP_EncryptFinal_ex');
|
Pointer<NativeType> Function(Pointer<NativeType> ctx, Pointer<Uint8> data,
|
||||||
|
Pointer<IntPtr> len)>('EVP_EncryptFinal_ex');
|
||||||
|
|
||||||
final EVP_CIPHER_CTX_free = libcrypto.lookupFunction<
|
final EVP_CIPHER_CTX_free = libcrypto.lookupFunction<
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx),
|
Pointer<NativeType> Function(Pointer<NativeType> ctx),
|
||||||
Pointer<NativeType> Function(Pointer<NativeType> ctx)
|
Pointer<NativeType> Function(
|
||||||
>('EVP_CIPHER_CTX_free');
|
Pointer<NativeType> ctx)>('EVP_CIPHER_CTX_free');
|
||||||
|
|
||||||
final EVP_Digest = libcrypto.lookupFunction<
|
final EVP_Digest = libcrypto.lookupFunction<
|
||||||
IntPtr Function(Pointer<Uint8> data, IntPtr len, Pointer<Uint8> hash, Pointer<IntPtr> hsize, Pointer<NativeType> alg, Pointer<NativeType> engine),
|
IntPtr Function(
|
||||||
int Function(Pointer<Uint8> data, int len, Pointer<Uint8> hash, Pointer<IntPtr> hsize, Pointer<NativeType> alg, Pointer<NativeType> engine)
|
Pointer<Uint8> data,
|
||||||
>('EVP_Digest');
|
IntPtr len,
|
||||||
|
Pointer<Uint8> hash,
|
||||||
|
Pointer<IntPtr> hsize,
|
||||||
|
Pointer<NativeType> alg,
|
||||||
|
Pointer<NativeType> engine),
|
||||||
|
int Function(
|
||||||
|
Pointer<Uint8> data,
|
||||||
|
int len,
|
||||||
|
Pointer<Uint8> hash,
|
||||||
|
Pointer<IntPtr> hsize,
|
||||||
|
Pointer<NativeType> alg,
|
||||||
|
Pointer<NativeType> engine)>('EVP_Digest');
|
||||||
|
|
||||||
final EVP_MD_size = libcrypto.lookupFunction<
|
final EVP_MD_size = libcrypto.lookupFunction<
|
||||||
IntPtr Function(Pointer<NativeType> ctx),
|
IntPtr Function(Pointer<NativeType> ctx),
|
||||||
int Function(Pointer<NativeType> ctx)
|
int Function(Pointer<NativeType> ctx)>('EVP_MD_size');
|
||||||
>('EVP_MD_size');
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ abstract class Hash {
|
||||||
Hash._(this.name);
|
Hash._(this.name);
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
Future<Uint8List> call(Uint8List input) async => Uint8List.view(await digest(name, input));
|
Future<Uint8List> call(Uint8List input) async =>
|
||||||
|
Uint8List.view(await digest(name, input));
|
||||||
}
|
}
|
||||||
|
|
||||||
final Hash sha1 = _Sha1();
|
final Hash sha1 = _Sha1();
|
||||||
|
|
@ -33,10 +34,10 @@ abstract class Cipher {
|
||||||
Cipher._(this.name);
|
Cipher._(this.name);
|
||||||
String name;
|
String name;
|
||||||
Object params(Uint8List iv);
|
Object params(Uint8List iv);
|
||||||
Future<Uint8List> encrypt(Uint8List input, Uint8List key, Uint8List iv) async {
|
Future<Uint8List> encrypt(
|
||||||
|
Uint8List input, Uint8List key, Uint8List iv) async {
|
||||||
final subtleKey = await importKey('raw', key, name, false, ['encrypt']);
|
final subtleKey = await importKey('raw', key, name, false, ['encrypt']);
|
||||||
return (await subtle.encrypt(params(iv), subtleKey, input))
|
return (await subtle.encrypt(params(iv), subtleKey, input)).asUint8List();
|
||||||
.asUint8List();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,11 +47,18 @@ class _AesCtr extends Cipher {
|
||||||
_AesCtr() : super._('AES-CTR');
|
_AesCtr() : super._('AES-CTR');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Object params(Uint8List iv) => AesCtrParams(name: name, counter: iv, length: 64);
|
Object params(Uint8List iv) =>
|
||||||
|
AesCtrParams(name: name, counter: iv, length: 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Uint8List> pbkdf2(Uint8List passphrase, Uint8List salt, Hash hash, int iterations, int bits) async {
|
Future<Uint8List> pbkdf2(Uint8List passphrase, Uint8List salt, Hash hash,
|
||||||
final raw = await importKey('raw', passphrase, 'PBKDF2', false, ['deriveBits']);
|
int iterations, int bits) async {
|
||||||
final res = await deriveBits(Pbkdf2Params(name: 'PBKDF2', hash: hash.name, salt: salt, iterations: iterations), raw, bits);
|
final raw =
|
||||||
|
await importKey('raw', passphrase, 'PBKDF2', false, ['deriveBits']);
|
||||||
|
final res = await deriveBits(
|
||||||
|
Pbkdf2Params(
|
||||||
|
name: 'PBKDF2', hash: hash.name, salt: salt, iterations: iterations),
|
||||||
|
raw,
|
||||||
|
bits);
|
||||||
return Uint8List.view(res);
|
return Uint8List.view(res);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:ffi';
|
import 'dart:ffi';
|
||||||
import 'package:ffi/ffi.dart';
|
import 'package:ffi/ffi.dart';
|
||||||
|
|
@ -8,7 +9,7 @@ abstract class Hash {
|
||||||
Hash._(this.ptr);
|
Hash._(this.ptr);
|
||||||
Pointer<NativeType> ptr;
|
Pointer<NativeType> ptr;
|
||||||
|
|
||||||
Uint8List call(Uint8List data) {
|
FutureOr<Uint8List> call(Uint8List data) {
|
||||||
final outSize = EVP_MD_size(ptr);
|
final outSize = EVP_MD_size(ptr);
|
||||||
final mem = malloc.call<Uint8>(outSize + data.length);
|
final mem = malloc.call<Uint8>(outSize + data.length);
|
||||||
final dataMem = mem.elementAt(outSize);
|
final dataMem = mem.elementAt(outSize);
|
||||||
|
|
@ -41,9 +42,10 @@ class _Sha512 extends Hash {
|
||||||
abstract class Cipher {
|
abstract class Cipher {
|
||||||
Cipher._();
|
Cipher._();
|
||||||
Pointer<NativeType> getAlg(int keysize);
|
Pointer<NativeType> getAlg(int keysize);
|
||||||
Uint8List encrypt(Uint8List input, Uint8List key, Uint8List iv) {
|
FutureOr<Uint8List> encrypt(Uint8List input, Uint8List key, Uint8List iv) {
|
||||||
final alg = getAlg(key.length * 8);
|
final alg = getAlg(key.length * 8);
|
||||||
final mem = malloc.call<Uint8>(sizeOf<IntPtr>() + key.length + iv.length + input.length);
|
final mem = malloc
|
||||||
|
.call<Uint8>(sizeOf<IntPtr>() + key.length + iv.length + input.length);
|
||||||
final lenMem = mem.cast<IntPtr>();
|
final lenMem = mem.cast<IntPtr>();
|
||||||
final keyMem = mem.elementAt(sizeOf<IntPtr>());
|
final keyMem = mem.elementAt(sizeOf<IntPtr>());
|
||||||
final ivMem = keyMem.elementAt(key.length);
|
final ivMem = keyMem.elementAt(key.length);
|
||||||
|
|
@ -72,14 +74,18 @@ class _AesCtr extends Cipher {
|
||||||
@override
|
@override
|
||||||
Pointer<NativeType> getAlg(int keysize) {
|
Pointer<NativeType> getAlg(int keysize) {
|
||||||
switch (keysize) {
|
switch (keysize) {
|
||||||
case 128: return EVP_aes_128_ctr();
|
case 128:
|
||||||
case 256: return EVP_aes_256_ctr();
|
return EVP_aes_128_ctr();
|
||||||
default: throw ArgumentError('invalid key size');
|
case 256:
|
||||||
|
return EVP_aes_256_ctr();
|
||||||
|
default:
|
||||||
|
throw ArgumentError('invalid key size');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint8List pbkdf2(Uint8List passphrase, Uint8List salt, Hash hash, int iterations, int bits) {
|
FutureOr<Uint8List> pbkdf2(
|
||||||
|
Uint8List passphrase, Uint8List salt, Hash hash, int iterations, int bits) {
|
||||||
final outLen = bits ~/ 8;
|
final outLen = bits ~/ 8;
|
||||||
final mem = malloc.call<Uint8>(passphrase.length + salt.length + outLen);
|
final mem = malloc.call<Uint8>(passphrase.length + salt.length + outLen);
|
||||||
final saltMem = mem.elementAt(passphrase.length);
|
final saltMem = mem.elementAt(passphrase.length);
|
||||||
|
|
@ -87,7 +93,8 @@ Uint8List pbkdf2(Uint8List passphrase, Uint8List salt, Hash hash, int iterations
|
||||||
try {
|
try {
|
||||||
mem.asTypedList(passphrase.length).setAll(0, passphrase);
|
mem.asTypedList(passphrase.length).setAll(0, passphrase);
|
||||||
saltMem.asTypedList(salt.length).setAll(0, salt);
|
saltMem.asTypedList(salt.length).setAll(0, salt);
|
||||||
PKCS5_PBKDF2_HMAC(mem, passphrase.length, saltMem, salt.length, iterations, hash.ptr, outLen, outMem);
|
PKCS5_PBKDF2_HMAC(mem, passphrase.length, saltMem, salt.length, iterations,
|
||||||
|
hash.ptr, outLen, outMem);
|
||||||
return Uint8List.fromList(outMem.asTypedList(outLen));
|
return Uint8List.fromList(outMem.asTypedList(outLen));
|
||||||
} finally {
|
} finally {
|
||||||
malloc.free(mem);
|
malloc.free(mem);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ class CryptoKey {}
|
||||||
@JS()
|
@JS()
|
||||||
@anonymous
|
@anonymous
|
||||||
class Pbkdf2Params {
|
class Pbkdf2Params {
|
||||||
external factory Pbkdf2Params({String name, String hash, Uint8List salt, int iterations});
|
external factory Pbkdf2Params(
|
||||||
|
{String name, String hash, Uint8List salt, int iterations});
|
||||||
String name;
|
String name;
|
||||||
String hash;
|
String hash;
|
||||||
Uint8List salt;
|
Uint8List salt;
|
||||||
|
|
@ -63,16 +64,20 @@ Future<dynamic> exportKey(String algorithm, CryptoKey key) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JS('crypto.subtle.deriveKey')
|
@JS('crypto.subtle.deriveKey')
|
||||||
external dynamic _deriveKey(dynamic algorithm, CryptoKey baseKey, dynamic derivedKeyAlgorithm, bool extractable, List<String> keyUsages);
|
external dynamic _deriveKey(dynamic algorithm, CryptoKey baseKey,
|
||||||
|
dynamic derivedKeyAlgorithm, bool extractable, List<String> keyUsages);
|
||||||
|
|
||||||
Future<ByteBuffer> deriveKey(dynamic algorithm, CryptoKey baseKey, dynamic derivedKeyAlgorithm, bool extractable, List<String> keyUsages) {
|
Future<ByteBuffer> deriveKey(dynamic algorithm, CryptoKey baseKey,
|
||||||
return promiseToFuture(_deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages));
|
dynamic derivedKeyAlgorithm, bool extractable, List<String> keyUsages) {
|
||||||
|
return promiseToFuture(_deriveKey(
|
||||||
|
algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JS('crypto.subtle.deriveBits')
|
@JS('crypto.subtle.deriveBits')
|
||||||
external dynamic _deriveBits(dynamic algorithm, CryptoKey baseKey, int length);
|
external dynamic _deriveBits(dynamic algorithm, CryptoKey baseKey, int length);
|
||||||
|
|
||||||
Future<ByteBuffer> deriveBits(dynamic algorithm, CryptoKey baseKey, int length) {
|
Future<ByteBuffer> deriveBits(
|
||||||
|
dynamic algorithm, CryptoKey baseKey, int length) {
|
||||||
return promiseToFuture(_deriveBits(algorithm, baseKey, length));
|
return promiseToFuture(_deriveBits(algorithm, baseKey, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,5 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export 'fake_database_native.dart' if (dart.library.js) 'fake_database_web.dart';
|
export 'fake_database_native.dart'
|
||||||
|
if (dart.library.js) 'fake_database_web.dart';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue