diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 37865d2fd..8d248db81 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -28,6 +28,11 @@ END USER NOTES:
Here is a signed list of file names and version history.
+2016-11-27: status ACTIVE
+bitaddress.org-v3.2.3-SHA256-c9a0bb3ed50aa75a5ae9c606d81e3fd41a4ff686ad38ad5379e2402f481e79a4.html
+ - wallet details: show error when checksum validation fails
+ - wallet details: show error when private key outside of curve range
+
2016-08-21: status ACTIVE
bitaddress.org-v3.2.2-SHA256-f4d047c264a2b71946de319482a9365e56d8d7289dd85a352da3b1448b7647df.html
- version bump for unix line endings
diff --git a/CHANGELOG.txt.asc b/CHANGELOG.txt.asc
index 00a219cfc..fdca8f95f 100644
--- a/CHANGELOG.txt.asc
+++ b/CHANGELOG.txt.asc
@@ -31,6 +31,11 @@ END USER NOTES:
Here is a signed list of file names and version history.
+2016-11-27: status ACTIVE
+bitaddress.org-v3.2.3-SHA256-c9a0bb3ed50aa75a5ae9c606d81e3fd41a4ff686ad38ad5379e2402f481e79a4.html
+ - wallet details: show error when checksum validation fails
+ - wallet details: show error when private key outside of curve range
+
2016-08-21: status ACTIVE
bitaddress.org-v3.2.2-SHA256-f4d047c264a2b71946de319482a9365e56d8d7289dd85a352da3b1448b7647df.html
- version bump for unix line endings
@@ -333,11 +338,11 @@ bitaddress.org-v0.1-SHA1-f40e706490f3eb2be56c31ddbf4c8646cd51ef40.html
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
-iQEcBAEBAgAGBQJXuj+4AAoJEIdJe5Fjl09a7wEIAJIfRmwqcr1oniY/arJpr+e6
-a97QMVgpzFrj2G3k8odW6MMowjnWOeYmzhdiNQ+9crmKUFjElrzzUEOg0Mh32Ix3
-iNVspXlHwgYfc5Xj7qtkWRPCoZ9u4TmOY5HA0gL7nsPZOrEbXjbYlknTTJertbpN
-gNZBaCxKQD2U4goUVXMyby9+3lnam6IOegpOqWQRxq8ZmPo+bbtjWpifp9roSaoG
-6fJb6T3fEx3aXcwamJktkh5Xh6WivUJnkR8vgLLbWEN4M1HXg1hCqipMnw9cw/U/
-FXSCSOv5Iw0thYTBhqR2NeRWdUEu81l95t9HXxjIKc75ej4J14QaPSDgt46PQvA=
-=3IgE
+iQEcBAEBAgAGBQJYOz4QAAoJEIdJe5Fjl09ar74IAMiOx4/c/q7UaTEjlAQDmseh
+CxSRHHQUwGaZG6z9pwt9ecdKht4t3Y2+CufcPmoV7A1Vq2EtoXFxEibwDwLuTzYL
+pqcUZCV+fwd0PGGz69mL0iGrMJHy0lhBZb4lb+2P6fXz4D35n1Dnq1jHGAOzcFEF
+B2++ja2s8QJwd1S1xtOhBshVZDTHc8YYgv1JJSKDpJNeGSFHx9IapOv4ydETbhfT
+L7kp9z6TKZ5khkRUCGR2qL4BzlTA/lSDj/cgVb6tRQmIgusRMjvJP076nEqiJ4TX
+8YZrObi2yXM7bD8iBXIabc3W2r/R9olw+pCxI+ZuFEOU+UVndCRpP7XEMsTp4aw=
+=/wYY
-----END PGP SIGNATURE-----
diff --git a/bitaddress.org.html b/bitaddress.org.html
index d8804c99c..044161519 100644
--- a/bitaddress.org.html
+++ b/bitaddress.org.html
@@ -5720,19 +5720,23 @@
this.priv = BigInteger.fromByteArrayUnsigned(input);
} else if ("string" == typeof input) {
var bytes = null;
- if (ECKey.isWalletImportFormat(input)) {
- bytes = ECKey.decodeWalletImportFormat(input);
- } else if (ECKey.isCompressedWalletImportFormat(input)) {
- bytes = ECKey.decodeCompressedWalletImportFormat(input);
- this.compressed = true;
- } else if (ECKey.isMiniFormat(input)) {
- bytes = Crypto.SHA256(input, { asBytes: true });
- } else if (ECKey.isHexFormat(input)) {
- bytes = Crypto.util.hexToBytes(input);
- } else if (ECKey.isBase64Format(input)) {
- bytes = Crypto.util.base64ToBytes(input);
+ try{
+ if (ECKey.isWalletImportFormat(input)) {
+ bytes = ECKey.decodeWalletImportFormat(input);
+ } else if (ECKey.isCompressedWalletImportFormat(input)) {
+ bytes = ECKey.decodeCompressedWalletImportFormat(input);
+ this.compressed = true;
+ } else if (ECKey.isMiniFormat(input)) {
+ bytes = Crypto.SHA256(input, { asBytes: true });
+ } else if (ECKey.isHexFormat(input)) {
+ bytes = Crypto.util.hexToBytes(input);
+ } else if (ECKey.isBase64Format(input)) {
+ bytes = Crypto.util.base64ToBytes(input);
+ }
+ } catch (exc1) {
+ this.setError(exc1);
}
-
+
if (ECKey.isBase6Format(input)) {
this.priv = new BigInteger(input, 6);
} else if (bytes == null || bytes.length != 32) {
@@ -5744,7 +5748,21 @@
}
this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed;
- KeyPool.push(this);
+ try {
+ // check not zero
+ if (this.priv != null && BigInteger.ZERO.compareTo(this.priv) == 0) this.setError("Error: BigInteger equal to zero.");
+ // valid range [0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140])
+ var hexKeyRangeLimit = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140";
+ var rangeLimitBytes = Crypto.util.hexToBytes(hexKeyRangeLimit);
+ var limitBigInt = BigInteger.fromByteArrayUnsigned(rangeLimitBytes);
+ if (this.priv != null && limitBigInt.compareTo(this.priv) < 0) this.setError("Error: BigInteger outside of curve range.")
+
+ if (this.priv != null) {
+ KeyPool.push(this);
+ }
+ } catch (exc2) {
+ this.setError(exc2);
+ }
};
ECKey.privateKeyPrefix = 0x80; // mainnet 0x80 testnet 0xEF
@@ -5754,6 +5772,15 @@
*/
ECKey.compressByDefault = false;
+ /**
+ * Set whether the public key should be returned compressed or not.
+ */
+ ECKey.prototype.setError = function (err) {
+ this.error = err;
+ this.priv = null;
+ return this;
+ };
+
/**
* Set whether the public key should be returned compressed or not.
*/
@@ -7033,7 +7060,7 @@
- (3.2.2)
+ (3.2.3)
527B 5C82 B1F6 B2DB 72A0
ECBF 8749 7B91 6397 4F5A
@@ -10448,7 +10475,10 @@
keyToECKeyWithBrain: function (key) {
var btcKey = new Bitcoin.ECKey(key);
- if (btcKey.priv == null) {
+ if (btcKey.error != null) {
+ alert(translator.get("detailalertnotvalidprivatekey") + "\n" + btcKey.error);
+ }
+ else if (btcKey.priv == null) {
// enforce a minimum passphrase length
if (key.length >= wallets.brainwallet.minPassphraseLength) {
// Deterministic Wallet confirm box to ask if user wants to SHA256 the input to get a private key
@@ -11630,7 +11660,64 @@
return false;
}
return true;
- }
+ },
+
+ // test checksum exceptions
+ testUncompressedWifShouldFailChecksum: function () {
+ // original key: 5KjQAHniFiy18SU7eenyJ9EPYUkjrbiBPfDqw987QjT5vehVQZV K->k
+ var key = "5kjQAHniFiy18SU7eenyJ9EPYUkjrbiBPfDqw987QjT5vehVQZV";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error.toString().indexOf("failed") == -1) { //Checksum validation failed!
+ return false;
+ }
+ return true;
+
+ },
+ testCompressedWifShouldFailChecksum: function () {
+ // original key: L5g9E16m5zEBZqQgMBouUfL6VwW49vCks1hgyxrPHkN8jNNdWTTk g->G
+ var key = "L5G9E16m5zEBZqQgMBouUfL6VwW49vCks1hgyxrPHkN8jNNdWTTk";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error.toString().indexOf("failed") == -1) { //Checksum validation failed!
+ return false;
+ }
+ return true;
+
+ },
+ // test range of valid private key values for the secp256k1 curve, when specified in hex is
+ // [0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140]
+ testBigIntegerZeroShouldSetError: function () {
+ var key = "0000000000000000000000000000000000000000000000000000000000000000";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+
+ },
+ testBigIntegerOutOfCurveRangeShouldSetError1: function () {
+ var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+ },
+ testBigIntegerOutOfCurveRangeShouldSetError2: function () {
+ var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364142";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+ },
+ testBigIntegerOutOfCurveRangeShouldSetError3: function () {
+ var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+ }
},
asynchronousTests: {
diff --git a/bitaddress.org.html.sig b/bitaddress.org.html.sig
index 1e29b05b5..ad49c02d4 100644
--- a/bitaddress.org.html.sig
+++ b/bitaddress.org.html.sig
@@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
-iQEcBAABAgAGBQJXuj/DAAoJEIdJe5Fjl09axyIIAJSBaV3/yIX0oTVrvhbdLZrv
-Odno0yBfsmQZNWKAKeQH1dp4FQ82w+9hDSQUczyj6kKfENhlnk+h6aiIXLcDXmth
-7KFbEN2UhsuWW6wfvw5/FqUMnSoqGBAVBBpNi/ZnUxyYlZPDR7eyMJy+vfSQ1leN
-27p2OIlusN30mCR8b32fQ8MOqovKsR4Jx+eGjRsk2aKcSOywE+08rRx9ATISXML8
-aaLQBAPjKgmJGUdWVma+qACJO5qcff7IaxOpXACcylVz3W0oDiPD6tWqT+6tnSNa
-ZpwoJDVkJFTuawcrbrBxTm6Qbh6Dfn/IaEMlRleFT4iqBVk55nKC85EL+JcRXBU=
-=c3ih
+iQEcBAABAgAGBQJYOz47AAoJEIdJe5Fjl09ateQIANi2qaAdLvTsslWSUtLH7fn5
+1Ywej5Dm+qX/TuzIoQ/eAIAKtrJe3KiLioRONDbMqDMovuseQUDB6FBYOlhOSHUd
+636Lwjs/aZW+weEgLnCi54JUj4/T/aaYZrQfzAvSFbj6G3mrc38xtB1anKJ6JmX0
+W482dWJR0+Ew0qB3419DKUtHUf8DjTlPT093H8HCb+DvCeWTxansnGXzAswxEJus
+yio7wUnGNaB9/rcVncU1dUHYsnb0hkstIwmlIIKcgPV/siDWCPXcigTI0IFSRoOW
+SrA+W9E5hWWxSYzzrzbW3iVJksT97ULXQOhzr3hy0ulUzTfqLZJmgNslfdfM3IU=
+=sgFZ
-----END PGP SIGNATURE-----
diff --git a/package.json b/package.json
index 7aac2c0bf..afa5bc8a9 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,8 @@
{
"name": "bitaddress.org",
- "version": "3.2.2",
- "sha1sum": "324a332b3964f1631a4fb6e070b7f5748e5672f8",
- "sha256sum": "f4d047c264a2b71946de319482a9365e56d8d7289dd85a352da3b1448b7647df",
+ "version": "3.2.3",
+ "sha1sum": "b8f7d12ddfef6561603f24a20478fad56abaca49",
+ "sha256sum": "c9a0bb3ed50aa75a5ae9c606d81e3fd41a4ff686ad38ad5379e2402f481e79a4",
"description": "Open Source JavaScript Client-Side Bitcoin Wallet Generator",
"main": "Gruntfile.js",
"dependencies": {
diff --git a/src/bitcoinjs-lib.eckey.js b/src/bitcoinjs-lib.eckey.js
index e1ab37d76..8517e5304 100644
--- a/src/bitcoinjs-lib.eckey.js
+++ b/src/bitcoinjs-lib.eckey.js
@@ -90,19 +90,23 @@ Bitcoin.ECKey = (function () {
this.priv = BigInteger.fromByteArrayUnsigned(input);
} else if ("string" == typeof input) {
var bytes = null;
- if (ECKey.isWalletImportFormat(input)) {
- bytes = ECKey.decodeWalletImportFormat(input);
- } else if (ECKey.isCompressedWalletImportFormat(input)) {
- bytes = ECKey.decodeCompressedWalletImportFormat(input);
- this.compressed = true;
- } else if (ECKey.isMiniFormat(input)) {
- bytes = Crypto.SHA256(input, { asBytes: true });
- } else if (ECKey.isHexFormat(input)) {
- bytes = Crypto.util.hexToBytes(input);
- } else if (ECKey.isBase64Format(input)) {
- bytes = Crypto.util.base64ToBytes(input);
+ try{
+ if (ECKey.isWalletImportFormat(input)) {
+ bytes = ECKey.decodeWalletImportFormat(input);
+ } else if (ECKey.isCompressedWalletImportFormat(input)) {
+ bytes = ECKey.decodeCompressedWalletImportFormat(input);
+ this.compressed = true;
+ } else if (ECKey.isMiniFormat(input)) {
+ bytes = Crypto.SHA256(input, { asBytes: true });
+ } else if (ECKey.isHexFormat(input)) {
+ bytes = Crypto.util.hexToBytes(input);
+ } else if (ECKey.isBase64Format(input)) {
+ bytes = Crypto.util.base64ToBytes(input);
+ }
+ } catch (exc1) {
+ this.setError(exc1);
}
-
+
if (ECKey.isBase6Format(input)) {
this.priv = new BigInteger(input, 6);
} else if (bytes == null || bytes.length != 32) {
@@ -114,7 +118,21 @@ Bitcoin.ECKey = (function () {
}
this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed;
- KeyPool.push(this);
+ try {
+ // check not zero
+ if (this.priv != null && BigInteger.ZERO.compareTo(this.priv) == 0) this.setError("Error: BigInteger equal to zero.");
+ // valid range [0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140])
+ var hexKeyRangeLimit = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140";
+ var rangeLimitBytes = Crypto.util.hexToBytes(hexKeyRangeLimit);
+ var limitBigInt = BigInteger.fromByteArrayUnsigned(rangeLimitBytes);
+ if (this.priv != null && limitBigInt.compareTo(this.priv) < 0) this.setError("Error: BigInteger outside of curve range.")
+
+ if (this.priv != null) {
+ KeyPool.push(this);
+ }
+ } catch (exc2) {
+ this.setError(exc2);
+ }
};
ECKey.privateKeyPrefix = 0x80; // mainnet 0x80 testnet 0xEF
@@ -124,6 +142,15 @@ Bitcoin.ECKey = (function () {
*/
ECKey.compressByDefault = false;
+ /**
+ * Set whether the public key should be returned compressed or not.
+ */
+ ECKey.prototype.setError = function (err) {
+ this.error = err;
+ this.priv = null;
+ return this;
+ };
+
/**
* Set whether the public key should be returned compressed or not.
*/
diff --git a/src/ninja.detailwallet.js b/src/ninja.detailwallet.js
index bfe86e69e..35eab17d6 100644
--- a/src/ninja.detailwallet.js
+++ b/src/ninja.detailwallet.js
@@ -50,7 +50,10 @@
keyToECKeyWithBrain: function (key) {
var btcKey = new Bitcoin.ECKey(key);
- if (btcKey.priv == null) {
+ if (btcKey.error != null) {
+ alert(translator.get("detailalertnotvalidprivatekey") + "\n" + btcKey.error);
+ }
+ else if (btcKey.priv == null) {
// enforce a minimum passphrase length
if (key.length >= wallets.brainwallet.minPassphraseLength) {
// Deterministic Wallet confirm box to ask if user wants to SHA256 the input to get a private key
diff --git a/src/ninja.unittests.js b/src/ninja.unittests.js
index b4cb4c46c..b45b39b32 100644
--- a/src/ninja.unittests.js
+++ b/src/ninja.unittests.js
@@ -837,7 +837,64 @@
return false;
}
return true;
- }
+ },
+
+ // test checksum exceptions
+ testUncompressedWifShouldFailChecksum: function () {
+ // original key: 5KjQAHniFiy18SU7eenyJ9EPYUkjrbiBPfDqw987QjT5vehVQZV K->k
+ var key = "5kjQAHniFiy18SU7eenyJ9EPYUkjrbiBPfDqw987QjT5vehVQZV";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error.toString().indexOf("failed") == -1) { //Checksum validation failed!
+ return false;
+ }
+ return true;
+
+ },
+ testCompressedWifShouldFailChecksum: function () {
+ // original key: L5g9E16m5zEBZqQgMBouUfL6VwW49vCks1hgyxrPHkN8jNNdWTTk g->G
+ var key = "L5G9E16m5zEBZqQgMBouUfL6VwW49vCks1hgyxrPHkN8jNNdWTTk";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error.toString().indexOf("failed") == -1) { //Checksum validation failed!
+ return false;
+ }
+ return true;
+
+ },
+ // test range of valid private key values for the secp256k1 curve, when specified in hex is
+ // [0x1, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140]
+ testBigIntegerZeroShouldSetError: function () {
+ var key = "0000000000000000000000000000000000000000000000000000000000000000";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+
+ },
+ testBigIntegerOutOfCurveRangeShouldSetError1: function () {
+ var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+ },
+ testBigIntegerOutOfCurveRangeShouldSetError2: function () {
+ var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364142";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+ },
+ testBigIntegerOutOfCurveRangeShouldSetError3: function () {
+ var key = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
+ var btcKey = new Bitcoin.ECKey(key);
+ if (btcKey.error == null) {
+ return false;
+ }
+ return true;
+ }
},
asynchronousTests: {