From 39056765a4896b0be8424e94dd8d9f24c9997cf1 Mon Sep 17 00:00:00 2001 From: Andreas Reiter Date: Tue, 31 May 2016 14:19:51 +0200 Subject: [PATCH 1/3] Update to crypto v1.1.1 --- lib/pbkdf2.dart | 52 +++++++++++++++++++++++----------------- pubspec.yaml | 2 +- test/pbkdf2_test.dart | 55 +++++++++++++++++++++++-------------------- 3 files changed, 62 insertions(+), 47 deletions(-) diff --git a/lib/pbkdf2.dart b/lib/pbkdf2.dart index 7f36db1..54dac10 100644 --- a/lib/pbkdf2.dart +++ b/lib/pbkdf2.dart @@ -1,6 +1,7 @@ library pbkdf2; import 'package:crypto/crypto.dart'; +import 'dart:async'; class PBKDF2 { Hash hash; @@ -8,20 +9,20 @@ class PBKDF2 { PBKDF2({Hash this.hash}); - List generateKey(String password, String salt, int c, int dkLen) { - var PRF = hash.newInstance(); - PRF.add([1, 2, 3]); - var blockSize = PRF.close().length; - if (dkLen > ((2 << 31) - 1) * blockSize) { - throw "derived key too long"; + Future> generateKey(String password, String salt, int c, int dkLen) async { + + var digestSize = hash.convert([1,2,3]).bytes.length; + + if (dkLen > ((2 << 31) - 1) * digestSize) { + return new Future.error("derived key too long"); } - var numberOfBlocks = (dkLen / blockSize).ceil(); - var sizeOfLastBlock = dkLen - (numberOfBlocks - 1) * blockSize; + var numberOfBlocks = (dkLen / digestSize).ceil(); + var sizeOfLastBlock = dkLen - (numberOfBlocks - 1) * digestSize; var key = []; for (var i = 1; i <= numberOfBlocks; i++) { - var block = _computeBlock(password, salt, c, i); + var block = await _computeBlock(password, salt, c, i); if (i < numberOfBlocks) { key.addAll(block); } else { @@ -31,28 +32,37 @@ class PBKDF2 { return key; } - List _computeBlock(String password, String salt, int iterations, int blockNumber) { - var hmac = new HMAC(hash, password.codeUnits); - hmac.add(salt.codeUnits); - _writeBlockNumber(hmac, blockNumber); - var lastDigest = hmac.close(); - var result = lastDigest; + Future> _computeBlock(String password, String salt, int iterations, int blockNumber) async { + var hmac = new Hmac(hash, password.codeUnits); + var digestStream = new StreamController(); + var hmacSink = hmac.startChunkedConversion(digestStream); + + hmacSink.add(salt.codeUnits); + _writeBlockNumber(hmacSink, blockNumber); + hmacSink.close(); + var lastDigest = await digestStream.stream.first; + + var result = lastDigest.bytes; for (var i = 1; i < iterations; i++) { - hmac = new HMAC(hash, password.codeUnits); - hmac.add(lastDigest); - var newDigest = hmac.close(); - _xorLists(result, newDigest); + hmac = new Hmac(hash, password.codeUnits); + digestStream = new StreamController(); + hmacSink = hmac.startChunkedConversion(digestStream); + hmacSink.add(lastDigest.bytes); + hmacSink.close(); + + var newDigest = await digestStream.stream.first; + _xorLists(result, newDigest.bytes); lastDigest = newDigest; } return result; } - _writeBlockNumber(HMAC hmac, int blockNumber) { + _writeBlockNumber(var hmacSink, int blockNumber) { _blockList[0] = blockNumber >> 24; _blockList[1] = blockNumber >> 16; _blockList[2] = blockNumber >> 8; _blockList[3] = blockNumber; - hmac.add(_blockList); + hmacSink.add(_blockList); } _xorLists(List list1, List list2) { diff --git a/pubspec.yaml b/pubspec.yaml index ed3cb9e..f28e06c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,6 +4,6 @@ author: James Ots homepage: https://github.com/jamesots/pbkdf2 description: Implementation of PBKDF2 key derivation function dependencies: - crypto: ">=0.9.0 <0.10.0" + crypto: '>=1.1.1 <1.2.0' dev_dependencies: unittest: ">=0.10.0 <0.11.0" diff --git a/test/pbkdf2_test.dart b/test/pbkdf2_test.dart index 58e4db1..b75b27f 100644 --- a/test/pbkdf2_test.dart +++ b/test/pbkdf2_test.dart @@ -1,6 +1,6 @@ import 'package:pbkdf2/pbkdf2.dart'; import 'package:unittest/unittest.dart'; -import 'package:crypto/crypto.dart'; +import 'package:crypto/crypto.dart' as crypto; List encodeBytes(String bytes) { var byteList = bytes.split(" "); @@ -13,48 +13,53 @@ List encodeBytes(String bytes) { main() { group("PBKDF2", () { - test("Should disallow large values of dkLen", () { - var sha = new SHA1(); - sha.add([1]); - var hLen = sha.close().length; - var gen = new PBKDF2(hash: sha); - expect(() => gen.generateKey("password", "salt", 1, ((2 << 31) - 1) * hLen + 1), throws); + test("Should disallow large values of dkLen", () async { + var digestSize = crypto.sha1.convert([1,2,3]).bytes.length; + var gen = new PBKDF2(hash: crypto.sha1); + + expect(gen.generateKey("password", "salt", 1, ((2 << 31) - 1) * digestSize + 1), throws); + }); - test("Should work with RFC6070 test vectors 1", () { - var gen = new PBKDF2(hash: new SHA1()); - var output = gen.generateKey("password", "salt", 1, 20); + test("Should work with RFC6070 test vectors 1", () async { + var gen = new PBKDF2(hash: crypto.sha1); + var output = await gen.generateKey("password", "salt", 1, 20); expect(output, encodeBytes("0c 60 c8 0f 96 1f 0e 71 f3 a9 b5 24 af 60 12 06 2f e0 37 a6")); }); - test("Should work with RFC6070 test vectors 2", () { - var gen = new PBKDF2(hash: new SHA1()); - var output = gen.generateKey("password", "salt", 2, 20); + + test("Should work with RFC6070 test vectors 2", () async { + var gen = new PBKDF2(hash: crypto.sha1); + var output = await gen.generateKey("password", "salt", 2, 20); expect(output, encodeBytes("ea 6c 01 4d c7 2d 6f 8c cd 1e d9 2a ce 1d 41 f0 d8 de 89 57")); }); - test("Should work with RFC6070 test vectors 3", () { - var gen = new PBKDF2(hash: new SHA1()); - var output = gen.generateKey("password", "salt", 4096, 20); + + test("Should work with RFC6070 test vectors 3", () async { + var gen = new PBKDF2(hash: crypto.sha1); + var output = await gen.generateKey("password", "salt", 4096, 20); expect(output, encodeBytes("4b 00 79 01 b7 65 48 9a be ad 49 d9 26 f7 21 d0 65 a4 29 c1")); }); + // This test may take a few minutes to run - test("Should work with RFC6070 test vectors 4", () { - var gen = new PBKDF2(hash: new SHA1()); - var output = gen.generateKey("password", "salt", 16777216, 20); + test("Should work with RFC6070 test vectors 4", () async { + var gen = new PBKDF2(hash: crypto.sha1); + var output = await gen.generateKey("password", "salt", 16777216, 20); expect(output, encodeBytes("ee fe 3d 61 cd 4d a4 e4 e9 94 5b 3d 6b a2 15 8c 26 34 e9 84")); }); + + - test("Should work with RFC6070 test vectors 5", () { - var gen = new PBKDF2(hash: new SHA1()); - var output = gen.generateKey("passwordPASSWORDpassword", "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25); + test("Should work with RFC6070 test vectors 5", () async { + var gen = new PBKDF2(hash: crypto.sha1); + var output = await gen.generateKey("passwordPASSWORDpassword", "saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25); expect(output, encodeBytes("3d 2e ec 4f e4 1c 84 9b 80 c8 d8 36 62 c0 e4 4a 8b 29 1a 96 4c f2 f0 70 38")); }); - test("Should work with RFC6070 test vectors 6", () { - var gen = new PBKDF2(hash: new SHA1()); - var output = gen.generateKey("pass\u0000word", "sa\u0000lt", 4096, 16); + test("Should work with RFC6070 test vectors 6", () async { + var gen = new PBKDF2(hash: crypto.sha1); + var output = await gen.generateKey("pass\u0000word", "sa\u0000lt", 4096, 16); expect(output, encodeBytes("56 fa 6a a7 55 48 09 9d cc 37 d7 f0 34 25 e0 c3")); }); }); From 489a6811d996bb52dba11a98f5aead1b103f75e7 Mon Sep 17 00:00:00 2001 From: Andreas Reiter Date: Wed, 22 Jun 2016 12:21:40 +0200 Subject: [PATCH 2/3] Error in transforming (2<<31)-1 to js via dart2js, inserted static value --- lib/pbkdf2.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pbkdf2.dart b/lib/pbkdf2.dart index 54dac10..b9af9a1 100644 --- a/lib/pbkdf2.dart +++ b/lib/pbkdf2.dart @@ -13,7 +13,7 @@ class PBKDF2 { var digestSize = hash.convert([1,2,3]).bytes.length; - if (dkLen > ((2 << 31) - 1) * digestSize) { + if (dkLen > (4294967295 /*(2<<31)-1*/) * digestSize) { return new Future.error("derived key too long"); } From 5cbe2e3903f6466b33732383143369ec4b86b2af Mon Sep 17 00:00:00 2001 From: Andreas Reiter Date: Mon, 15 May 2017 11:43:30 +0200 Subject: [PATCH 3/3] Update crypto to 2.0.0 --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index f28e06c..ed31a56 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,6 +4,6 @@ author: James Ots homepage: https://github.com/jamesots/pbkdf2 description: Implementation of PBKDF2 key derivation function dependencies: - crypto: '>=1.1.1 <1.2.0' + crypto: '^2.0.0' dev_dependencies: unittest: ">=0.10.0 <0.11.0"