@toruslabs/eccrypto
Advanced tools
Comparing version 2.1.1 to 2.2.0
390
browser.js
"use strict"; | ||
var EC = require("elliptic").ec; | ||
var ec = new EC("secp256k1"); | ||
var browserCrypto = global.crypto || global.msCrypto || {}; | ||
var subtle = browserCrypto.subtle || browserCrypto.webkitSubtle; | ||
var nodeCrypto = require('crypto'); | ||
const EC_GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex'); | ||
const EC = require("elliptic").ec; | ||
const ec = new EC("secp256k1"); | ||
const browserCrypto = global.crypto || global.msCrypto || {}; | ||
const subtle = browserCrypto.subtle || browserCrypto.webkitSubtle; | ||
const nodeCrypto = require("crypto"); | ||
const EC_GROUP_ORDER = Buffer.from("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", "hex"); | ||
const ZERO32 = Buffer.alloc(32, 0); | ||
function assert(condition, message) { | ||
@@ -19,14 +15,14 @@ if (!condition) { | ||
} | ||
function isScalar (x) { | ||
function isScalar(x) { | ||
return Buffer.isBuffer(x) && x.length === 32; | ||
} | ||
function isValidPrivateKey(privateKey) { | ||
if (!isScalar(privateKey)) | ||
{ | ||
if (!isScalar(privateKey)) { | ||
return false; | ||
} | ||
return privateKey.compare(ZERO32) > 0 && // > 0 | ||
privateKey.compare(EC_GROUP_ORDER) < 0; // < G | ||
return ( | ||
privateKey.compare(ZERO32) > 0 && | ||
// > 0 | ||
privateKey.compare(EC_GROUP_ORDER) < 0 | ||
); // < G | ||
} | ||
@@ -39,6 +35,7 @@ | ||
} | ||
var res = 0; | ||
for (var i = 0; i < b1.length; i++) { | ||
res |= b1[i] ^ b2[i]; // jshint ignore:line | ||
let res = 0; | ||
for (let i = 0; i < b1.length; i++) { | ||
res |= b1[i] ^ b2[i]; // jshint ignore:line | ||
} | ||
return res === 0; | ||
@@ -51,4 +48,4 @@ } | ||
function randomBytes(size) { | ||
var arr = new Uint8Array(size); | ||
if (typeof browserCrypto.getRandomValues === 'undefined') { | ||
const arr = new Uint8Array(size); | ||
if (typeof browserCrypto.getRandomValues === "undefined") { | ||
return Buffer.from(nodeCrypto.randomBytes(size)); | ||
@@ -61,69 +58,73 @@ } else { | ||
function sha512(msg) { | ||
return new Promise(function(resolve) { | ||
var hash = nodeCrypto.createHash('sha512'); | ||
var result = hash.update(msg).digest(); | ||
resolve(new Uint8Array(result)); | ||
}); | ||
async function sha512(msg) { | ||
if (subtle) { | ||
const hash = await subtle.digest("SHA-512", msg); | ||
const result = new Uint8Array(hash); | ||
return result; | ||
} | ||
const hash = nodeCrypto.createHash("sha512"); | ||
const result = hash.update(msg).digest(); | ||
return new Uint8Array(result); | ||
} | ||
function getAes(op) { | ||
return function(iv, key, data) { | ||
return new Promise(function(resolve) { | ||
if (subtle) { | ||
var importAlgorithm = {name: "AES-CBC"}; | ||
var keyp = subtle.importKey("raw", key, importAlgorithm, false, [op]); | ||
return keyp.then(function(cryptoKey) { | ||
var encAlgorithm = {name: "AES-CBC", iv: iv}; | ||
return subtle[op](encAlgorithm, cryptoKey, data); | ||
}).then(function(result) { | ||
resolve(Buffer.from(new Uint8Array(result))); | ||
}); | ||
} else { | ||
if (op === 'encrypt') { | ||
var cipher = nodeCrypto.createCipheriv('aes-256-cbc', key, iv); | ||
let firstChunk = cipher.update(data); | ||
let secondChunk = cipher.final(); | ||
resolve(Buffer.concat([firstChunk, secondChunk])); | ||
} | ||
else if (op === 'decrypt') { | ||
var decipher = nodeCrypto.createDecipheriv('aes-256-cbc', key, iv); | ||
let firstChunk = decipher.update(data); | ||
let secondChunk = decipher.final(); | ||
resolve(Buffer.concat([firstChunk, secondChunk])); | ||
} | ||
} | ||
}); | ||
return async function (iv, key, data) { | ||
if (subtle) { | ||
const importAlgorithm = { | ||
name: "AES-CBC", | ||
}; | ||
const cryptoKey = await subtle.importKey("raw", key, importAlgorithm, false, [op]); | ||
const encAlgorithm = { | ||
name: "AES-CBC", | ||
iv: iv, | ||
}; | ||
const result = await subtle[op](encAlgorithm, cryptoKey, data); | ||
return Buffer.from(new Uint8Array(result)); | ||
} else if (op === "encrypt") { | ||
const cipher = nodeCrypto.createCipheriv("aes-256-cbc", key, iv); | ||
let firstChunk = cipher.update(data); | ||
let secondChunk = cipher.final(); | ||
return Buffer.concat([firstChunk, secondChunk]); | ||
} else if (op === "decrypt") { | ||
const decipher = nodeCrypto.createDecipheriv("aes-256-cbc", key, iv); | ||
let firstChunk = decipher.update(data); | ||
let secondChunk = decipher.final(); | ||
return Buffer.concat([firstChunk, secondChunk]); | ||
} | ||
}; | ||
} | ||
const aesCbcEncrypt = getAes("encrypt"); | ||
const aesCbcDecrypt = getAes("decrypt"); | ||
var aesCbcEncrypt = getAes("encrypt"); | ||
var aesCbcDecrypt = getAes("decrypt"); | ||
function hmacSha256Sign(key, msg) { | ||
return new Promise(function(resolve) { | ||
var hmac = nodeCrypto.createHmac('sha256', Buffer.from(key)); | ||
hmac.update(msg); | ||
var result = hmac.digest(); | ||
resolve(result); | ||
}); | ||
async function hmacSha256Sign(key, msg) { | ||
if (subtle) { | ||
const importAlgorithm = { | ||
name: "HMAC", | ||
hash: { | ||
name: "SHA-256", | ||
}, | ||
}; | ||
const cryptoKey = await subtle.importKey("raw", new Uint8Array(key), importAlgorithm, false, ["sign", "verify"]); | ||
const sig = await subtle.sign("HMAC", cryptoKey, msg); | ||
const result = Buffer.from(new Uint8Array(sig)); | ||
return result; | ||
} | ||
const hmac = nodeCrypto.createHmac("sha256", Buffer.from(key)); | ||
hmac.update(msg); | ||
const result = hmac.digest(); | ||
return result; | ||
} | ||
function hmacSha256Verify(key, msg, sig) { | ||
return new Promise(function(resolve) { | ||
var hmac = nodeCrypto.createHmac('sha256', Buffer.from(key)); | ||
hmac.update(msg); | ||
var expectedSig = hmac.digest(); | ||
resolve(equalConstTime(expectedSig, sig)); | ||
}); | ||
async function hmacSha256Verify(key, msg, sig) { | ||
const expectedSig = await hmacSha256Sign(key, msg); | ||
return equalConstTime(expectedSig, sig); | ||
} | ||
/** | ||
* Generate a new valid private key. Will use the window.crypto or window.msCrypto as source | ||
* depending on your browser. | ||
* @return {Buffer} A 32-byte private key. | ||
* @function | ||
*/ | ||
* Generate a new valid private key. Will use the window.crypto or window.msCrypto as source | ||
* depending on your browser. | ||
* @return {Buffer} A 32-byte private key. | ||
* @function | ||
*/ | ||
exports.generatePrivate = function () { | ||
var privateKey = randomBytes(32); | ||
let privateKey = randomBytes(32); | ||
while (!isValidPrivateKey(privateKey)) { | ||
@@ -135,3 +136,3 @@ privateKey = randomBytes(32); | ||
var getPublic = exports.getPublic = function(privateKey) { | ||
const getPublic = (exports.getPublic = function (privateKey) { | ||
// This function has sync API so we throw an error immediately. | ||
@@ -143,3 +144,3 @@ assert(privateKey.length === 32, "Bad private key"); | ||
return Buffer.from(ec.keyFromPrivate(privateKey).getPublic("arr")); | ||
}; | ||
}); | ||
@@ -149,3 +150,4 @@ /** | ||
*/ | ||
var getPublicCompressed = exports.getPublicCompressed = function(privateKey) { // jshint ignore:line | ||
exports.getPublicCompressed = function (privateKey) { | ||
// jshint ignore:line | ||
assert(privateKey.length === 32, "Bad private key"); | ||
@@ -163,140 +165,116 @@ assert(isValidPrivateKey(privateKey), "Bad private key"); | ||
// <http://caniuse.com/#feat=cryptography>). | ||
exports.sign = function(privateKey, msg) { | ||
return new Promise(function(resolve) { | ||
assert(privateKey.length === 32, "Bad private key"); | ||
assert(isValidPrivateKey(privateKey), "Bad private key"); | ||
assert(msg.length > 0, "Message should not be empty"); | ||
assert(msg.length <= 32, "Message is too long"); | ||
resolve(Buffer.from(ec.sign(msg, privateKey, {canonical: true}).toDER())); | ||
}); | ||
exports.sign = async function (privateKey, msg) { | ||
assert(privateKey.length === 32, "Bad private key"); | ||
assert(isValidPrivateKey(privateKey), "Bad private key"); | ||
assert(msg.length > 0, "Message should not be empty"); | ||
assert(msg.length <= 32, "Message is too long"); | ||
return Buffer.from( | ||
ec | ||
.sign(msg, privateKey, { | ||
canonical: true, | ||
}) | ||
.toDER() | ||
); | ||
}; | ||
exports.verify = function(publicKey, msg, sig) { | ||
return new Promise(function(resolve, reject) { | ||
assert(publicKey.length === 65 || publicKey.length === 33, "Bad public key"); | ||
if (publicKey.length === 65) | ||
{ | ||
assert(publicKey[0] === 4, "Bad public key"); | ||
} | ||
if (publicKey.length === 33) | ||
{ | ||
assert(publicKey[0] === 2 || publicKey[0] === 3, "Bad public key"); | ||
} | ||
assert(msg.length > 0, "Message should not be empty"); | ||
assert(msg.length <= 32, "Message is too long"); | ||
if (ec.verify(msg, sig, publicKey)) { | ||
resolve(null); | ||
} else { | ||
reject(new Error("Bad signature")); | ||
} | ||
}); | ||
exports.verify = async function (publicKey, msg, sig) { | ||
assert(publicKey.length === 65 || publicKey.length === 33, "Bad public key"); | ||
if (publicKey.length === 65) { | ||
assert(publicKey[0] === 4, "Bad public key"); | ||
} | ||
if (publicKey.length === 33) { | ||
assert(publicKey[0] === 2 || publicKey[0] === 3, "Bad public key"); | ||
} | ||
assert(msg.length > 0, "Message should not be empty"); | ||
assert(msg.length <= 32, "Message is too long"); | ||
if (ec.verify(msg, sig, publicKey)) { | ||
return null; | ||
} else { | ||
throw new Error("Bad signature"); | ||
} | ||
}; | ||
const deriveUnpadded = (exports.derive = async function (privateKeyA, publicKeyB) { | ||
assert(Buffer.isBuffer(privateKeyA), "Bad private key"); | ||
assert(Buffer.isBuffer(publicKeyB), "Bad public key"); | ||
assert(privateKeyA.length === 32, "Bad private key"); | ||
assert(isValidPrivateKey(privateKeyA), "Bad private key"); | ||
assert(publicKeyB.length === 65 || publicKeyB.length === 33, "Bad public key"); | ||
if (publicKeyB.length === 65) { | ||
assert(publicKeyB[0] === 4, "Bad public key"); | ||
} | ||
if (publicKeyB.length === 33) { | ||
assert(publicKeyB[0] === 2 || publicKeyB[0] === 3, "Bad public key"); | ||
} | ||
const keyA = ec.keyFromPrivate(privateKeyA); | ||
const keyB = ec.keyFromPublic(publicKeyB); | ||
const Px = keyA.derive(keyB.getPublic()); // BN instance | ||
return Buffer.from(Px.toArray()); | ||
}); | ||
var deriveUnpadded = exports.derive = function(privateKeyA, publicKeyB) { | ||
return new Promise(function(resolve) { | ||
assert(Buffer.isBuffer(privateKeyA), "Bad private key"); | ||
assert(Buffer.isBuffer(publicKeyB), "Bad public key"); | ||
assert(privateKeyA.length === 32, "Bad private key"); | ||
assert(isValidPrivateKey(privateKeyA), "Bad private key"); | ||
assert(publicKeyB.length === 65 || publicKeyB.length === 33, "Bad public key"); | ||
if (publicKeyB.length === 65) | ||
{ | ||
assert(publicKeyB[0] === 4, "Bad public key"); | ||
} | ||
if (publicKeyB.length === 33) | ||
{ | ||
assert(publicKeyB[0] === 2 || publicKeyB[0] === 3, "Bad public key"); | ||
} | ||
var keyA = ec.keyFromPrivate(privateKeyA); | ||
var keyB = ec.keyFromPublic(publicKeyB); | ||
var Px = keyA.derive(keyB.getPublic()); // BN instance | ||
resolve(Buffer.from(Px.toArray())); | ||
}); | ||
}; | ||
const derivePadded = (exports.derivePadded = async function (privateKeyA, publicKeyB) { | ||
assert(Buffer.isBuffer(privateKeyA), "Bad private key"); | ||
assert(Buffer.isBuffer(publicKeyB), "Bad public key"); | ||
assert(privateKeyA.length === 32, "Bad private key"); | ||
assert(isValidPrivateKey(privateKeyA), "Bad private key"); | ||
assert(publicKeyB.length === 65 || publicKeyB.length === 33, "Bad public key"); | ||
if (publicKeyB.length === 65) { | ||
assert(publicKeyB[0] === 4, "Bad public key"); | ||
} | ||
if (publicKeyB.length === 33) { | ||
assert(publicKeyB[0] === 2 || publicKeyB[0] === 3, "Bad public key"); | ||
} | ||
const keyA = ec.keyFromPrivate(privateKeyA); | ||
const keyB = ec.keyFromPublic(publicKeyB); | ||
const Px = keyA.derive(keyB.getPublic()); // BN instance | ||
return Buffer.from(Px.toString(16, 64), "hex"); | ||
}); | ||
var derivePadded = exports.derivePadded = function(privateKeyA, publicKeyB) { | ||
return new Promise(function(resolve) { | ||
assert(Buffer.isBuffer(privateKeyA), "Bad private key"); | ||
assert(Buffer.isBuffer(publicKeyB), "Bad public key"); | ||
assert(privateKeyA.length === 32, "Bad private key"); | ||
assert(isValidPrivateKey(privateKeyA), "Bad private key"); | ||
assert(publicKeyB.length === 65 || publicKeyB.length === 33, "Bad public key"); | ||
if (publicKeyB.length === 65) | ||
{ | ||
assert(publicKeyB[0] === 4, "Bad public key"); | ||
} | ||
if (publicKeyB.length === 33) | ||
{ | ||
assert(publicKeyB[0] === 2 || publicKeyB[0] === 3, "Bad public key"); | ||
} | ||
var keyA = ec.keyFromPrivate(privateKeyA); | ||
var keyB = ec.keyFromPublic(publicKeyB); | ||
var Px = keyA.derive(keyB.getPublic()); // BN instance | ||
resolve(Buffer.from(Px.toString(16, 64), 'hex')); | ||
}); | ||
}; | ||
exports.encrypt = function(publicKeyTo, msg, opts) { | ||
exports.encrypt = async function (publicKeyTo, msg, opts) { | ||
opts = opts || {}; | ||
// Tmp variables to save context from flat promises; | ||
var iv, ephemPublicKey, ciphertext, macKey; | ||
return new Promise(function(resolve) { | ||
var ephemPrivateKey = opts.ephemPrivateKey || randomBytes(32); | ||
// There is a very unlikely possibility that it is not a valid key | ||
while(!isValidPrivateKey(ephemPrivateKey)) | ||
{ | ||
ephemPrivateKey = opts.ephemPrivateKey || randomBytes(32); | ||
} | ||
ephemPublicKey = getPublic(ephemPrivateKey); | ||
resolve(deriveUnpadded(ephemPrivateKey, publicKeyTo)); | ||
}).then(function(Px) { | ||
return sha512(Px); | ||
}).then(function(hash) { | ||
iv = opts.iv || randomBytes(16); | ||
var encryptionKey = hash.slice(0, 32); | ||
macKey = hash.slice(32); | ||
return aesCbcEncrypt(iv, encryptionKey, msg); | ||
}).then(function(data) { | ||
ciphertext = data; | ||
var dataToMac = Buffer.concat([iv, ephemPublicKey, ciphertext]); | ||
return hmacSha256Sign(macKey, dataToMac); | ||
}).then(function(mac) { | ||
return { | ||
iv: iv, | ||
ephemPublicKey: ephemPublicKey, | ||
ciphertext: ciphertext, | ||
mac: mac, | ||
}; | ||
}); | ||
let iv, ephemPublicKey, ciphertext, macKey; | ||
let ephemPrivateKey = opts.ephemPrivateKey || randomBytes(32); | ||
// There is a very unlikely possibility that it is not a valid key | ||
while (!isValidPrivateKey(ephemPrivateKey)) { | ||
ephemPrivateKey = opts.ephemPrivateKey || randomBytes(32); | ||
} | ||
ephemPublicKey = getPublic(ephemPrivateKey); | ||
const Px = await deriveUnpadded(ephemPrivateKey, publicKeyTo); | ||
const hash = await sha512(Px); | ||
iv = opts.iv || randomBytes(16); | ||
const encryptionKey = hash.slice(0, 32); | ||
macKey = hash.slice(32); | ||
const data = aesCbcEncrypt(iv, encryptionKey, msg); | ||
ciphertext = data; | ||
const dataToMac = Buffer.concat([iv, ephemPublicKey, ciphertext]); | ||
const mac = await hmacSha256Sign(macKey, dataToMac); | ||
return { | ||
iv: iv, | ||
ephemPublicKey: ephemPublicKey, | ||
ciphertext: ciphertext, | ||
mac: mac, | ||
}; | ||
}; | ||
const decrypt = function(privateKey, opts, padding = false) { | ||
const decrypt = async function (privateKey, opts) { | ||
let padding = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
// Tmp variable to save context from flat promises; | ||
var encryptionKey; | ||
let encryptionKey; | ||
const derive = padding ? derivePadded : deriveUnpadded; | ||
return derive(privateKey, opts.ephemPublicKey).then(function(Px) { | ||
return sha512(Px); | ||
}).then(function(hash) { | ||
encryptionKey = hash.slice(0, 32); | ||
var macKey = hash.slice(32); | ||
var dataToMac = Buffer.concat([ | ||
opts.iv, | ||
opts.ephemPublicKey, | ||
opts.ciphertext | ||
]); | ||
return hmacSha256Verify(macKey, dataToMac, opts.mac); | ||
}).then(function(macGood) { | ||
if (!macGood && padding === false) { | ||
return decrypt(privateKey, opts, true); | ||
} else if (!macGood && padding === true) { | ||
throw new Error("bad MAC after trying padded"); | ||
} | ||
return aesCbcDecrypt(opts.iv, encryptionKey, opts.ciphertext).then(function(msg) { | ||
return Buffer.from(new Uint8Array(msg)); | ||
}); | ||
}) | ||
const Px = await derive(privateKey, opts.ephemPublicKey); | ||
const hash = await sha512(Px); | ||
encryptionKey = hash.slice(0, 32); | ||
const macKey = hash.slice(32); | ||
const dataToMac = Buffer.concat([opts.iv, opts.ephemPublicKey, opts.ciphertext]); | ||
const macGood = await hmacSha256Verify(macKey, dataToMac, opts.mac); | ||
if (!macGood && padding === false) { | ||
return decrypt(privateKey, opts, true); | ||
} else if (!macGood && padding === true) { | ||
throw new Error("bad MAC after trying padded"); | ||
} | ||
const msg = await aesCbcDecrypt(opts.iv, encryptionKey, opts.ciphertext); | ||
return Buffer.from(new Uint8Array(msg)); | ||
}; | ||
exports.decrypt = decrypt; | ||
{ | ||
"name": "@toruslabs/eccrypto", | ||
"version": "2.1.1", | ||
"version": "2.2.0", | ||
"description": "JavaScript Elliptic curve cryptography library, includes fix to browser.js so that encrypt/decrypt works", | ||
"main": "browser.js", | ||
"browser": "browser.js", | ||
"main": "dist/browser.js", | ||
"browser": "dist/browser.js", | ||
"types": "types.d.ts", | ||
"scripts": { | ||
"test": "ECCRYPTO_NO_FALLBACK=1 mocha && xvfb-run -a karma start && jshint .", | ||
"build": "babel -d dist browser.js", | ||
"test": "ECCRYPTO_NO_FALLBACK=1 mocha && karma start", | ||
"m": "mocha", | ||
"k": "xvfb-run -a karma start", | ||
"kc": "xvfb-run -a karma start --browsers Chromium", | ||
"kf": "xvfb-run -a karma start --browsers Firefox", | ||
"j": "jshint ." | ||
"k": "karma start", | ||
"kc": "karma start --browsers Chromium", | ||
"kf": "karma start --browsers Firefox" | ||
}, | ||
@@ -39,6 +39,11 @@ "repository": { | ||
"devDependencies": { | ||
"@babel/cli": "^7.21.5", | ||
"@babel/core": "^7.21.5", | ||
"@babel/plugin-transform-runtime": "^7.21.4", | ||
"@babel/preset-env": "^7.21.5", | ||
"@babel/runtime": "^7.21.5", | ||
"browserify": "^17.0.0", | ||
"buffer-equal": "^1.0.1", | ||
"chai": "^4.3.7", | ||
"jshint": "^2.13.6", | ||
"eslint": "^8.39.0", | ||
"karma": "^6.4.1", | ||
@@ -49,2 +54,3 @@ "karma-browserify": "^8.1.0", | ||
"karma-firefox-launcher": "^2.1.2", | ||
"karma-safari-launcher": "^1.0.0", | ||
"karma-mocha": "^2.0.1", | ||
@@ -51,0 +57,0 @@ "karma-mocha-reporter": "^2.2.5", |
281
test.js
@@ -5,3 +5,2 @@ var expect = require("chai").expect; | ||
var eccrypto = require("./"); | ||
var assert = require('assert'); // deleteme | ||
@@ -27,14 +26,16 @@ var msg = createHash("sha256").update("test").digest(); | ||
describe("Key conversion", function() { | ||
it("should allow to convert private key to public", function() { | ||
describe("Key conversion", function () { | ||
it("should allow to convert private key to public", function () { | ||
expect(Buffer.isBuffer(publicKey)).to.be.true; | ||
expect(publicKey.toString("hex")).to.equal("041b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f70beaf8f588b541507fed6a642c5ab42dfdf8120a7f639de5122d47a69a8e8d1"); | ||
expect(publicKey.toString("hex")).to.equal( | ||
"041b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f70beaf8f588b541507fed6a642c5ab42dfdf8120a7f639de5122d47a69a8e8d1" | ||
); | ||
}); | ||
it("shouwld allow to convert private key to compressed public", function() { | ||
expect(Buffer.isBuffer(publicKeyCompressed)).to.be.true; | ||
expect(publicKeyCompressed.toString("hex")).to.equal("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f"); | ||
it("shouwld allow to convert private key to compressed public", function () { | ||
expect(Buffer.isBuffer(publicKeyCompressed)).to.be.true; | ||
expect(publicKeyCompressed.toString("hex")).to.equal("031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f"); | ||
}); | ||
it("should throw on invalid private key", function() { | ||
it("should throw on invalid private key", function () { | ||
expect(eccrypto.getPublic.bind(null, Buffer.from("00", "hex"))).to.throw(Error); | ||
@@ -45,7 +46,9 @@ expect(eccrypto.getPublic.bind(null, Buffer.from("test"))).to.throw(Error); | ||
describe("ECDSA", function() { | ||
it("should allow to sign and verify message", function() { | ||
return eccrypto.sign(privateKey, msg).then(function(sig) { | ||
describe("ECDSA", function () { | ||
it("should allow to sign and verify message", function () { | ||
return eccrypto.sign(privateKey, msg).then(function (sig) { | ||
expect(Buffer.isBuffer(sig)).to.be.true; | ||
expect(sig.toString("hex")).to.equal("3044022078c15897a34de6566a0d396fdef660698c59fef56d34ee36bef14ad89ee0f6f8022016e02e8b7285d93feafafbe745702f142973a77d5c2fa6293596357e17b3b47c"); | ||
expect(sig.toString("hex")).to.equal( | ||
"3044022078c15897a34de6566a0d396fdef660698c59fef56d34ee36bef14ad89ee0f6f8022016e02e8b7285d93feafafbe745702f142973a77d5c2fa6293596357e17b3b47c" | ||
); | ||
return eccrypto.verify(publicKey, msg, sig); | ||
@@ -55,6 +58,8 @@ }); | ||
it("should allow to sign and verify message using a compressed public key", function() { | ||
return eccrypto.sign(privateKey, msg).then(function(sig) { | ||
it("should allow to sign and verify message using a compressed public key", function () { | ||
return eccrypto.sign(privateKey, msg).then(function (sig) { | ||
expect(Buffer.isBuffer(sig)).to.be.true; | ||
expect(sig.toString("hex")).to.equal("3044022078c15897a34de6566a0d396fdef660698c59fef56d34ee36bef14ad89ee0f6f8022016e02e8b7285d93feafafbe745702f142973a77d5c2fa6293596357e17b3b47c"); | ||
expect(sig.toString("hex")).to.equal( | ||
"3044022078c15897a34de6566a0d396fdef660698c59fef56d34ee36bef14ad89ee0f6f8022016e02e8b7285d93feafafbe745702f142973a77d5c2fa6293596357e17b3b47c" | ||
); | ||
return eccrypto.verify(publicKeyCompressed, msg, sig); | ||
@@ -64,6 +69,6 @@ }); | ||
it("shouldn't verify incorrect signature", function(done) { | ||
eccrypto.sign(privateKey, msg).then(function(sig) { | ||
it("shouldn't verify incorrect signature", function (done) { | ||
eccrypto.sign(privateKey, msg).then(function (sig) { | ||
expect(Buffer.isBuffer(sig)).to.be.true; | ||
eccrypto.verify(publicKey, otherMsg, sig).catch(function() { | ||
eccrypto.verify(publicKey, otherMsg, sig).catch(function () { | ||
done(); | ||
@@ -74,9 +79,9 @@ }); | ||
it("should reject promise on invalid key when signing", function(done) { | ||
it("should reject promise on invalid key when signing", function (done) { | ||
var k4 = Buffer.from("test"); | ||
var k192 = Buffer.from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "hex"); | ||
var k384 = Buffer.from("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "hex"); | ||
eccrypto.sign(k4, msg).catch(function() { | ||
eccrypto.sign(k192, msg).catch(function() { | ||
eccrypto.sign(k384, msg).catch(function() { | ||
eccrypto.sign(k4, msg).catch(function () { | ||
eccrypto.sign(k192, msg).catch(function () { | ||
eccrypto.sign(k384, msg).catch(function () { | ||
done(); | ||
@@ -88,10 +93,10 @@ }); | ||
it("should reject promise on invalid key when verifying", function(done) { | ||
eccrypto.sign(privateKey, msg).then(function(sig) { | ||
it("should reject promise on invalid key when verifying", function (done) { | ||
eccrypto.sign(privateKey, msg).then(function (sig) { | ||
expect(Buffer.isBuffer(sig)).to.be.true; | ||
eccrypto.verify(Buffer.from("test"), msg, sig).catch(function() { | ||
eccrypto.verify(Buffer.from("test"), msg, sig).catch(function () { | ||
var badKey = Buffer.alloc(65); | ||
publicKey.copy(badKey); | ||
badKey[0] ^= 1; | ||
eccrypto.verify(badKey, msg, sig).catch(function() { | ||
eccrypto.verify(badKey, msg, sig).catch(function () { | ||
done(); | ||
@@ -103,7 +108,7 @@ }); | ||
it("should reject promise on invalid sig when verifying", function(done) { | ||
eccrypto.sign(privateKey, msg).then(function(sig) { | ||
it("should reject promise on invalid sig when verifying", function (done) { | ||
eccrypto.sign(privateKey, msg).then(function (sig) { | ||
expect(Buffer.isBuffer(sig)).to.be.true; | ||
sig[0] ^= 1; | ||
eccrypto.verify(publicKey, msg, sig).catch(function() { | ||
eccrypto.verify(publicKey, msg, sig).catch(function () { | ||
done(); | ||
@@ -114,6 +119,8 @@ }); | ||
it("should allow to sign and verify messages less than 32 bytes", function() { | ||
return eccrypto.sign(privateKey, shortMsg).then(function(sig) { | ||
it("should allow to sign and verify messages less than 32 bytes", function () { | ||
return eccrypto.sign(privateKey, shortMsg).then(function (sig) { | ||
expect(Buffer.isBuffer(sig)).to.be.true; | ||
expect(sig.toString("hex")).to.equal("304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa"); | ||
expect(sig.toString("hex")).to.equal( | ||
"304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa" | ||
); | ||
return eccrypto.verify(publicKey, shortMsg, sig); | ||
@@ -123,7 +130,10 @@ }); | ||
it("shouldn't sign and verify messages longer than 32 bytes", function(done) { | ||
it("shouldn't sign and verify messages longer than 32 bytes", function (done) { | ||
var longMsg = Buffer.alloc(40); | ||
var someSig = Buffer.from("304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa", "hex"); | ||
eccrypto.sign(privateKey, longMsg).catch(function() { | ||
eccrypto.verify(privateKey, longMsg, someSig).catch(function(e) { | ||
var someSig = Buffer.from( | ||
"304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa", | ||
"hex" | ||
); | ||
eccrypto.sign(privateKey, longMsg).catch(function () { | ||
eccrypto.verify(privateKey, longMsg, someSig).catch(function (e) { | ||
expect(e.message).to.not.match(/bad signature/i); | ||
@@ -135,7 +145,10 @@ done(); | ||
it("shouldn't sign and verify empty messages", function(done) { | ||
it("shouldn't sign and verify empty messages", function (done) { | ||
var emptyMsg = Buffer.alloc(0); | ||
var someSig = Buffer.from("304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa", "hex"); | ||
eccrypto.sign(privateKey, emptyMsg).catch(function() { | ||
eccrypto.verify(publicKey, emptyMsg, someSig).catch(function(e) { | ||
var someSig = Buffer.from( | ||
"304402204737396b697e5a3400e3aedd203d8be89879f97708647252bd0c17752ff4c8f302201d52ef234de82ce0719679fa220334c83b80e21b8505a781d32d94a27d9310aa", | ||
"hex" | ||
); | ||
eccrypto.sign(privateKey, emptyMsg).catch(function () { | ||
eccrypto.verify(publicKey, emptyMsg, someSig).catch(function (e) { | ||
expect(e.message).to.not.match(/bad signature/i); | ||
@@ -148,9 +161,9 @@ done(); | ||
describe("ECDH", function() { | ||
it("should derive shared secret from privkey A and pubkey B", function() { | ||
return eccrypto.derive(privateKeyA, publicKeyB).then(function(Px) { | ||
describe("ECDH", function () { | ||
it("should derive shared secret from privkey A and pubkey B", function () { | ||
return eccrypto.derive(privateKeyA, publicKeyB).then(function (Px) { | ||
expect(Buffer.isBuffer(Px)).to.be.true; | ||
expect(Px.length).to.equal(32); | ||
expect(Px.toString("hex")).to.equal("aca78f27d5f23b2e7254a0bb8df128e7c0f922d47ccac72814501e07b7291886"); | ||
return eccrypto.derive(privateKeyB, publicKeyA).then(function(Px2) { | ||
return eccrypto.derive(privateKeyB, publicKeyA).then(function (Px2) { | ||
expect(Buffer.isBuffer(Px2)).to.be.true; | ||
@@ -163,8 +176,8 @@ expect(Px2.length).to.equal(32); | ||
it("should derive shared secret from privkey A and compressed pubkey B", function() { | ||
return eccrypto.derive(privateKeyA, publicKeyBCompressed).then(function(Px) { | ||
it("should derive shared secret from privkey A and compressed pubkey B", function () { | ||
return eccrypto.derive(privateKeyA, publicKeyBCompressed).then(function (Px) { | ||
expect(Buffer.isBuffer(Px)).to.be.true; | ||
expect(Px.length).to.equal(32); | ||
expect(Px.toString("hex")).to.equal("aca78f27d5f23b2e7254a0bb8df128e7c0f922d47ccac72814501e07b7291886"); | ||
return eccrypto.derive(privateKeyB, publicKeyA).then(function(Px2) { | ||
return eccrypto.derive(privateKeyB, publicKeyA).then(function (Px2) { | ||
expect(Buffer.isBuffer(Px2)).to.be.true; | ||
@@ -177,7 +190,7 @@ expect(Px2.length).to.equal(32); | ||
it("should reject promise on bad keys", function(done) { | ||
eccrypto.derive(Buffer.from("test"), publicKeyB).catch(function() { | ||
eccrypto.derive(publicKeyB, publicKeyB).catch(function() { | ||
eccrypto.derive(privateKeyA, privateKeyA).catch(function() { | ||
eccrypto.derive(privateKeyB, Buffer.from("test")).catch(function() { | ||
it("should reject promise on bad keys", function (done) { | ||
eccrypto.derive(Buffer.from("test"), publicKeyB).catch(function () { | ||
eccrypto.derive(publicKeyB, publicKeyB).catch(function () { | ||
eccrypto.derive(privateKeyA, privateKeyA).catch(function () { | ||
eccrypto.derive(privateKeyB, Buffer.from("test")).catch(function () { | ||
done(); | ||
@@ -190,4 +203,4 @@ }); | ||
it("should reject promise on bad arguments", function(done) { | ||
eccrypto.derive({}, {}).catch(function(e) { | ||
it("should reject promise on bad arguments", function (done) { | ||
eccrypto.derive({}, {}).catch(function (e) { | ||
expect(e.message).to.match(/Bad private key/i); | ||
@@ -199,3 +212,3 @@ done(); | ||
describe("ECIES", function() { | ||
describe("ECIES", function () { | ||
var ephemPrivateKey = Buffer.alloc(32); | ||
@@ -208,8 +221,7 @@ ephemPrivateKey.fill(4); | ||
var mac = Buffer.from("dbb14a9b53dbd6b763dba24dc99520f570cdf8095a8571db4bf501b535fda1ed", "hex"); | ||
var encOpts = {ephemPrivateKey: ephemPrivateKey, iv: iv}; | ||
var decOpts = {iv: iv, ephemPublicKey: ephemPublicKey, ciphertext: ciphertext, mac: mac}; | ||
var encOpts = { ephemPrivateKey: ephemPrivateKey, iv: iv }; | ||
var decOpts = { iv: iv, ephemPublicKey: ephemPublicKey, ciphertext: ciphertext, mac: mac }; | ||
it("should encrypt", function() { | ||
return eccrypto.encrypt(publicKeyB, Buffer.from("test"), encOpts) | ||
.then(function(enc) { | ||
it("should encrypt", function () { | ||
return eccrypto.encrypt(publicKeyB, Buffer.from("test"), encOpts).then(function (enc) { | ||
expect(bufferEqual(enc.iv, iv)).to.be.true; | ||
@@ -222,5 +234,4 @@ expect(bufferEqual(enc.ephemPublicKey, ephemPublicKey)).to.be.true; | ||
it("should decrypt", function() { | ||
return eccrypto.decrypt(privateKeyB, decOpts) | ||
.then(function(msg) { | ||
it("should decrypt", function () { | ||
return eccrypto.decrypt(privateKeyB, decOpts).then(function (msg) { | ||
expect(msg.toString()).to.equal("test"); | ||
@@ -230,29 +241,37 @@ }); | ||
it("should encrypt and decrypt", function() { | ||
return eccrypto.encrypt(publicKeyA, Buffer.from("to a")).then(function(enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}).then(function(msg) { | ||
expect(msg.toString()).to.equal("to a"); | ||
}); | ||
it("should encrypt and decrypt", function () { | ||
return eccrypto | ||
.encrypt(publicKeyA, Buffer.from("to a")) | ||
.then(function (enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}) | ||
.then(function (msg) { | ||
expect(msg.toString()).to.equal("to a"); | ||
}); | ||
}); | ||
it("should encrypt and decrypt", function() { | ||
return eccrypto.encrypt(publicKeyA, Buffer.from("to a")).then(function(enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}).then(function(msg) { | ||
expect(msg.toString()).to.equal("to a"); | ||
}); | ||
it("should encrypt and decrypt", function () { | ||
return eccrypto | ||
.encrypt(publicKeyA, Buffer.from("to a")) | ||
.then(function (enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}) | ||
.then(function (msg) { | ||
expect(msg.toString()).to.equal("to a"); | ||
}); | ||
}); | ||
it("should encrypt and decrypt with message size > 15", function() { | ||
return eccrypto.encrypt(publicKeyA, Buffer.from("message size that is greater than 15 for sure =)")).then(function(enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}).then(function(msg) { | ||
expect(msg.toString()).to.equal("message size that is greater than 15 for sure =)"); | ||
}); | ||
it("should encrypt and decrypt with message size > 15", function () { | ||
return eccrypto | ||
.encrypt(publicKeyA, Buffer.from("message size that is greater than 15 for sure =)")) | ||
.then(function (enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}) | ||
.then(function (msg) { | ||
expect(msg.toString()).to.equal("message size that is greater than 15 for sure =)"); | ||
}); | ||
}); | ||
it("should encrypt with compressed public key", function() { | ||
return eccrypto.encrypt(publicKeyBCompressed, Buffer.from("test"), encOpts) | ||
.then(function(enc) { | ||
it("should encrypt with compressed public key", function () { | ||
return eccrypto.encrypt(publicKeyBCompressed, Buffer.from("test"), encOpts).then(function (enc) { | ||
expect(bufferEqual(enc.iv, iv)).to.be.true; | ||
@@ -265,8 +284,11 @@ expect(bufferEqual(enc.ephemPublicKey, ephemPublicKey)).to.be.true; | ||
it("should encrypt and decrypt with compressed public key", function() { | ||
return eccrypto.encrypt(publicKeyACompressed, Buffer.from("to a")).then(function(enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}).then(function(msg) { | ||
expect(msg.toString()).to.equal("to a"); | ||
}); | ||
it("should encrypt and decrypt with compressed public key", function () { | ||
return eccrypto | ||
.encrypt(publicKeyACompressed, Buffer.from("to a")) | ||
.then(function (enc) { | ||
return eccrypto.decrypt(privateKeyA, enc); | ||
}) | ||
.then(function (msg) { | ||
expect(msg.toString()).to.equal("to a"); | ||
}); | ||
}); | ||
@@ -277,13 +299,15 @@ | ||
var publicKey = eccrypto.getPublic(privateKey); | ||
return eccrypto.encrypt(publicKey, Buffer.from("generated private key")) | ||
.then(function(enc) { return eccrypto.decrypt(privateKey, enc); }) | ||
.then(function(msg) { | ||
expect(msg.toString()).to.equal("generated private key"); | ||
}); | ||
return eccrypto | ||
.encrypt(publicKey, Buffer.from("generated private key")) | ||
.then(function (enc) { | ||
return eccrypto.decrypt(privateKey, enc); | ||
}) | ||
.then(function (msg) { | ||
expect(msg.toString()).to.equal("generated private key"); | ||
}); | ||
}); | ||
it("should reject promise on bad private key when decrypting", function(done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function(enc) { | ||
eccrypto.decrypt(privateKeyB, enc).catch(function() { | ||
it("should reject promise on bad private key when decrypting", function (done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function (enc) { | ||
eccrypto.decrypt(privateKeyB, enc).catch(function () { | ||
done(); | ||
@@ -294,6 +318,6 @@ }); | ||
it("should reject promise on bad IV when decrypting", function(done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function(enc) { | ||
it("should reject promise on bad IV when decrypting", function (done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function (enc) { | ||
enc.iv[0] ^= 1; | ||
eccrypto.decrypt(privateKeyA, enc).catch(function() { | ||
eccrypto.decrypt(privateKeyA, enc).catch(function () { | ||
done(); | ||
@@ -304,6 +328,6 @@ }); | ||
it("should reject promise on bad R when decrypting", function(done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function(enc) { | ||
it("should reject promise on bad R when decrypting", function (done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function (enc) { | ||
enc.ephemPublicKey[0] ^= 1; | ||
eccrypto.decrypt(privateKeyA, enc).catch(function() { | ||
eccrypto.decrypt(privateKeyA, enc).catch(function () { | ||
done(); | ||
@@ -314,6 +338,6 @@ }); | ||
it("should reject promise on bad ciphertext when decrypting", function(done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function(enc) { | ||
it("should reject promise on bad ciphertext when decrypting", function (done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function (enc) { | ||
enc.ciphertext[0] ^= 1; | ||
eccrypto.decrypt(privateKeyA, enc).catch(function() { | ||
eccrypto.decrypt(privateKeyA, enc).catch(function () { | ||
done(); | ||
@@ -324,10 +348,10 @@ }); | ||
it("should reject promise on bad MAC when decrypting", function(done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function(enc) { | ||
it("should reject promise on bad MAC when decrypting", function (done) { | ||
eccrypto.encrypt(publicKeyA, Buffer.from("test")).then(function (enc) { | ||
var origMac = enc.mac; | ||
enc.mac = mac.slice(1); | ||
eccrypto.decrypt(privateKeyA, enc).catch(function() { | ||
eccrypto.decrypt(privateKeyA, enc).catch(function () { | ||
enc.mac = origMac; | ||
enc.mac[10] ^= 1; | ||
eccrypto.decrypt(privateKeyA, enc).catch(function() { | ||
eccrypto.decrypt(privateKeyA, enc).catch(function () { | ||
done(); | ||
@@ -339,19 +363,24 @@ }); | ||
it("should successfully decrypt if bad MAC is caused by inconsistent padding in derive", function(done) { | ||
it("should successfully decrypt if bad MAC is caused by inconsistent padding in derive", function (done) { | ||
var encryption = { | ||
ciphertext: Buffer.from('e614aff7db97b01d4b0d5cfb1387b4763cb369f74d743bed95020330d57e3ae91a574bd7ae89da0885eb5f6e332a296f', 'hex'), | ||
ephemPublicKey: Buffer.from('04fb0a7c19defeaeeb34defbc47be3c9a4c1de500895c1e1e8ce6d0991595217f8e76c4594968e8c77d83c26f4f1ee496c40c7ac48816a4ee2edf38c550d8916a0', 'hex'), | ||
iv: Buffer.from('456f0c039cb2224849082c3d0feebec1', 'hex'), | ||
mac: Buffer.from('df7352dcdf2ee10c939276791515340479b526920a155b8ac932a5a26ea4c924', 'hex') | ||
ciphertext: Buffer.from("e614aff7db97b01d4b0d5cfb1387b4763cb369f74d743bed95020330d57e3ae91a574bd7ae89da0885eb5f6e332a296f", "hex"), | ||
ephemPublicKey: Buffer.from( | ||
"04fb0a7c19defeaeeb34defbc47be3c9a4c1de500895c1e1e8ce6d0991595217f8e76c4594968e8c77d83c26f4f1ee496c40c7ac48816a4ee2edf38c550d8916a0", | ||
"hex" | ||
), | ||
iv: Buffer.from("456f0c039cb2224849082c3d0feebec1", "hex"), | ||
mac: Buffer.from("df7352dcdf2ee10c939276791515340479b526920a155b8ac932a5a26ea4c924", "hex"), | ||
}; | ||
var decryptionKey = Buffer.from('78bb3f8efcd59ebc8c4f0dee865ba10e375869921c62caa5b3b46699504bb280', 'hex'); | ||
eccrypto.decrypt(decryptionKey, encryption) | ||
.then(function(msg) { | ||
done(); | ||
}).catch(function(e) { | ||
done(e); | ||
}); | ||
}) | ||
var decryptionKey = Buffer.from("78bb3f8efcd59ebc8c4f0dee865ba10e375869921c62caa5b3b46699504bb280", "hex"); | ||
eccrypto | ||
.decrypt(decryptionKey, encryption) | ||
.then(function (msg) { | ||
done(); | ||
}) | ||
.catch(function (e) { | ||
done(e); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47901
10
860
18
1