├── .npmrc ├── algos.js ├── .github ├── workflows │ ├── node-pretest.yml │ ├── rebase.yml │ ├── require-allow-edits.yml │ ├── node-aught.yml │ ├── node-twenties.yml │ └── node-tens.yml └── FUNDING.yml ├── .gitignore ├── browser ├── curves.json ├── index.js ├── verify.js ├── algorithms.json └── sign.js ├── index.js ├── LICENSE ├── README.md ├── .eslintrc ├── package.json ├── test └── index.js └── CHANGELOG.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | allow-same-version=true 3 | message=v%s 4 | -------------------------------------------------------------------------------- /algos.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('./browser/algorithms.json'); 4 | -------------------------------------------------------------------------------- /.github/workflows/node-pretest.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: pretest/posttest' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/pretest.yml@main 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gitignore 2 | .nyc_output 3 | node_modules 4 | 5 | npm-debug.log 6 | 7 | # Only apps should have lockfiles 8 | npm-shrinkwrap.json 9 | package-lock.json 10 | yarn.lock 11 | 12 | .npmignore 13 | -------------------------------------------------------------------------------- /browser/curves.json: -------------------------------------------------------------------------------- 1 | { 2 | "1.3.132.0.10": "secp256k1", 3 | "1.3.132.0.33": "p224", 4 | "1.2.840.10045.3.1.1": "p192", 5 | "1.2.840.10045.3.1.7": "p256", 6 | "1.3.132.0.34": "p384", 7 | "1.3.132.0.35": "p521" 8 | } 9 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var crypto = require('crypto'); 4 | 5 | exports.createSign = crypto.createSign; 6 | exports.Sign = crypto.Sign; 7 | 8 | exports.createVerify = crypto.createVerify; 9 | exports.Verify = crypto.Verify; 10 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | uses: ljharb/actions/.github/workflows/rebase.yml@main 8 | secrets: 9 | token: ${{ secrets.GITHUB_TOKEN }} 10 | -------------------------------------------------------------------------------- /.github/workflows/require-allow-edits.yml: -------------------------------------------------------------------------------- 1 | name: Require “Allow Edits” 2 | 3 | on: [pull_request_target] 4 | 5 | jobs: 6 | _: 7 | name: "Require “Allow Edits”" 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: ljharb/require-allow-edits@main 13 | -------------------------------------------------------------------------------- /.github/workflows/node-aught.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js < 10' 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | tests: 7 | uses: ljharb/actions/.github/workflows/node.yml@main 8 | with: 9 | range: '0.10 - 10' 10 | type: minors 11 | command: npm run tests-only 12 | 13 | node: 14 | name: 'node < 10' 15 | needs: [tests] 16 | runs-on: ubuntu-latest 17 | steps: 18 | - run: true 19 | -------------------------------------------------------------------------------- /.github/workflows/node-twenties.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js >= 20' 2 | 3 | on: [pull_request, push] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | tests: 10 | uses: ljharb/actions/.github/workflows/node.yml@main 11 | with: 12 | range: '>= 20' 13 | type: minors 14 | command: npm run tests-only 15 | 16 | node: 17 | name: 'node >= 20' 18 | needs: [tests] 19 | runs-on: ubuntu-latest 20 | steps: 21 | - run: true 22 | -------------------------------------------------------------------------------- /.github/workflows/node-tens.yml: -------------------------------------------------------------------------------- 1 | name: 'Tests: node.js 10 - 20' 2 | 3 | on: [pull_request, push] 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | tests: 10 | uses: ljharb/actions/.github/workflows/node.yml@main 11 | with: 12 | range: '>= 10 < 20' 13 | type: minors 14 | command: npm run tests-only 15 | 16 | node: 17 | name: 'node 10 - 20' 18 | needs: [tests] 19 | runs-on: ubuntu-latest 20 | steps: 21 | - run: true 22 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ljharb] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/browserify-sign 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2015 Calvin Metcalf and browserify-sign contributors 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # browserify-sign 2 | 3 | [![NPM Package](https://img.shields.io/npm/v/browserify-sign.svg?style=flat-square)](https://www.npmjs.org/package/browserify-sign) 4 | [![Build Status](https://img.shields.io/travis/crypto-browserify/browserify-sign.svg?branch=master&style=flat-square)](https://travis-ci.org/crypto-browserify/browserify-sign) 5 | [![Dependency status](https://img.shields.io/david/crypto-browserify/browserify-sign.svg?style=flat-square)](https://david-dm.org/crypto-browserify/browserify-sign#info=dependencies) 6 | 7 | [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) 8 | 9 | A package to duplicate the functionality of node's crypto public key functions, much of this is based on [Fedor Indutny's](https://github.com/indutny) work on [indutny/tls.js](https://github.com/indutny/tls.js). 10 | 11 | ## LICENSE 12 | 13 | ISC 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | 4 | "extends": "@ljharb", 5 | 6 | "rules": { 7 | "func-style": "warn", 8 | "indent": ["error", 2], 9 | "multiline-comment-style": "off", 10 | "sort-keys": "off", 11 | }, 12 | 13 | "overrides": [ 14 | { 15 | "files": "browser/index.js", 16 | "rules": { 17 | "func-name-matching": "off", 18 | "max-statements-per-line": "off", 19 | "no-underscore-dangle": "warn", 20 | }, 21 | }, 22 | { 23 | "files": "browser/verify.js", 24 | "rules": { 25 | "max-params": "off", 26 | "max-statements": "off", 27 | "max-statements-per-line": "off", 28 | "no-param-reassign": "warn", 29 | "no-plusplus": "warn", 30 | "no-use-before-define": "warn", 31 | } 32 | }, 33 | { 34 | "files": "browser/sign.js", 35 | "rules": { 36 | "max-params": "off", 37 | "max-statements-per-line": "off", 38 | "no-param-reassign": "warn", 39 | "no-plusplus": "warn", 40 | "no-use-before-define": "warn", 41 | } 42 | }, 43 | { 44 | "files": "test/*.js", 45 | "rules": { 46 | "max-lines-per-function": "off", 47 | }, 48 | }, 49 | ], 50 | } 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "browserify-sign", 3 | "version": "4.2.5", 4 | "description": "adds node crypto signing for browsers", 5 | "bugs": { 6 | "url": "https://github.com/crypto-browserify/browserify-sign/issues" 7 | }, 8 | "license": "ISC", 9 | "main": "index.js", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/crypto-browserify/browserify-sign.git" 13 | }, 14 | "scripts": { 15 | "prepack": "npmignore --auto --commentLines=autogenerated", 16 | "prepublish": "not-in-publish || npm run prepublishOnly", 17 | "prepublishOnly": "safe-publish-latest", 18 | "lint": "eslint --ext=js,mjs .", 19 | "tests-only": "nyc tape 'test/**/*.js'", 20 | "pretest": "npm run lint", 21 | "test": "npm run tests-only", 22 | "posttest": "npx npm@\">= 10.2\" audit --production", 23 | "version": "auto-changelog && git add CHANGELOG.md", 24 | "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" 25 | }, 26 | "dependencies": { 27 | "bn.js": "^5.2.2", 28 | "browserify-rsa": "^4.1.1", 29 | "create-hash": "^1.2.0", 30 | "create-hmac": "^1.1.7", 31 | "elliptic": "^6.6.1", 32 | "inherits": "^2.0.4", 33 | "parse-asn1": "^5.1.9", 34 | "readable-stream": "^2.3.8", 35 | "safe-buffer": "^5.2.1" 36 | }, 37 | "devDependencies": { 38 | "@ljharb/eslint-config": "^21.2.0", 39 | "auto-changelog": "^2.5.0", 40 | "encoding": "^0.1.13", 41 | "eslint": "=8.8.0", 42 | "in-publish": "^2.0.1", 43 | "npmignore": "^0.3.1", 44 | "nyc": "^10.3.2", 45 | "safe-publish-latest": "^2.0.0", 46 | "semver": "^6.3.1", 47 | "tape": "^5.9.0" 48 | }, 49 | "browser": "browser/index.js", 50 | "engines": { 51 | "node": ">= 0.10" 52 | }, 53 | "auto-changelog": { 54 | "output": "CHANGELOG.md", 55 | "template": "keepachangelog", 56 | "unreleased": false, 57 | "commitLimit": false, 58 | "backfillLimit": false, 59 | "hideCredit": true 60 | }, 61 | "publishConfig": { 62 | "ignore": [ 63 | ".github/workflows", 64 | ".eslintrc", 65 | "test" 66 | ] 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /browser/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Buffer = require('safe-buffer').Buffer; 4 | var createHash = require('create-hash'); 5 | var stream = require('readable-stream'); 6 | var inherits = require('inherits'); 7 | var sign = require('./sign'); 8 | var verify = require('./verify'); 9 | 10 | var algorithms = require('./algorithms.json'); 11 | Object.keys(algorithms).forEach(function (key) { 12 | algorithms[key].id = Buffer.from(algorithms[key].id, 'hex'); 13 | algorithms[key.toLowerCase()] = algorithms[key]; 14 | }); 15 | 16 | function Sign(algorithm) { 17 | stream.Writable.call(this); 18 | 19 | var data = algorithms[algorithm]; 20 | if (!data) { throw new Error('Unknown message digest'); } 21 | 22 | this._hashType = data.hash; 23 | this._hash = createHash(data.hash); 24 | this._tag = data.id; 25 | this._signType = data.sign; 26 | } 27 | inherits(Sign, stream.Writable); 28 | 29 | Sign.prototype._write = function _write(data, _, done) { 30 | this._hash.update(data); 31 | done(); 32 | }; 33 | 34 | Sign.prototype.update = function update(data, enc) { 35 | this._hash.update(typeof data === 'string' ? Buffer.from(data, enc) : data); 36 | 37 | return this; 38 | }; 39 | 40 | Sign.prototype.sign = function signMethod(key, enc) { 41 | this.end(); 42 | var hash = this._hash.digest(); 43 | var sig = sign(hash, key, this._hashType, this._signType, this._tag); 44 | 45 | return enc ? sig.toString(enc) : sig; 46 | }; 47 | 48 | function Verify(algorithm) { 49 | stream.Writable.call(this); 50 | 51 | var data = algorithms[algorithm]; 52 | if (!data) { throw new Error('Unknown message digest'); } 53 | 54 | this._hash = createHash(data.hash); 55 | this._tag = data.id; 56 | this._signType = data.sign; 57 | } 58 | inherits(Verify, stream.Writable); 59 | 60 | Verify.prototype._write = function _write(data, _, done) { 61 | this._hash.update(data); 62 | done(); 63 | }; 64 | 65 | Verify.prototype.update = function update(data, enc) { 66 | this._hash.update(typeof data === 'string' ? Buffer.from(data, enc) : data); 67 | 68 | return this; 69 | }; 70 | 71 | Verify.prototype.verify = function verifyMethod(key, sig, enc) { 72 | var sigBuffer = typeof sig === 'string' ? Buffer.from(sig, enc) : sig; 73 | 74 | this.end(); 75 | var hash = this._hash.digest(); 76 | return verify(sigBuffer, hash, key, this._signType, this._tag); 77 | }; 78 | 79 | function createSign(algorithm) { 80 | return new Sign(algorithm); 81 | } 82 | 83 | function createVerify(algorithm) { 84 | return new Verify(algorithm); 85 | } 86 | 87 | module.exports = { 88 | Sign: createSign, 89 | Verify: createVerify, 90 | createSign: createSign, 91 | createVerify: createVerify 92 | }; 93 | -------------------------------------------------------------------------------- /browser/verify.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js 4 | var Buffer = require('safe-buffer').Buffer; 5 | var BN = require('bn.js'); 6 | var EC = require('elliptic').ec; 7 | var parseKeys = require('parse-asn1'); 8 | var curves = require('./curves.json'); 9 | 10 | function verify(sig, hash, key, signType, tag) { 11 | var pub = parseKeys(key); 12 | if (pub.type === 'ec') { 13 | // rsa keys can be interpreted as ecdsa ones in openssl 14 | if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong public key type'); } 15 | return ecVerify(sig, hash, pub); 16 | } else if (pub.type === 'dsa') { 17 | if (signType !== 'dsa') { throw new Error('wrong public key type'); } 18 | return dsaVerify(sig, hash, pub); 19 | } 20 | if (signType !== 'rsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong public key type'); } 21 | 22 | hash = Buffer.concat([tag, hash]); 23 | var len = pub.modulus.byteLength(); 24 | var pad = [1]; 25 | var padNum = 0; 26 | while (hash.length + pad.length + 2 < len) { 27 | pad.push(0xff); 28 | padNum += 1; 29 | } 30 | pad.push(0x00); 31 | var i = -1; 32 | while (++i < hash.length) { 33 | pad.push(hash[i]); 34 | } 35 | pad = Buffer.from(pad); 36 | var red = BN.mont(pub.modulus); 37 | sig = new BN(sig).toRed(red); 38 | 39 | sig = sig.redPow(new BN(pub.publicExponent)); 40 | sig = Buffer.from(sig.fromRed().toArray()); 41 | var out = padNum < 8 ? 1 : 0; 42 | len = Math.min(sig.length, pad.length); 43 | if (sig.length !== pad.length) { out = 1; } 44 | 45 | i = -1; 46 | while (++i < len) { out |= sig[i] ^ pad[i]; } 47 | return out === 0; 48 | } 49 | 50 | function ecVerify(sig, hash, pub) { 51 | var curveId = curves[pub.data.algorithm.curve.join('.')]; 52 | if (!curveId) { throw new Error('unknown curve ' + pub.data.algorithm.curve.join('.')); } 53 | 54 | var curve = new EC(curveId); 55 | var pubkey = pub.data.subjectPrivateKey.data; 56 | 57 | return curve.verify(hash, sig, pubkey); 58 | } 59 | 60 | function dsaVerify(sig, hash, pub) { 61 | var p = pub.data.p; 62 | var q = pub.data.q; 63 | var g = pub.data.g; 64 | var y = pub.data.pub_key; 65 | var unpacked = parseKeys.signature.decode(sig, 'der'); 66 | var s = unpacked.s; 67 | var r = unpacked.r; 68 | checkValue(s, q); 69 | checkValue(r, q); 70 | var montp = BN.mont(p); 71 | var w = s.invm(q); 72 | var v = g.toRed(montp) 73 | .redPow(new BN(hash).mul(w).mod(q)) 74 | .fromRed() 75 | .mul(y.toRed(montp).redPow(r.mul(w).mod(q)).fromRed()) 76 | .mod(p) 77 | .mod(q); 78 | return v.cmp(r) === 0; 79 | } 80 | 81 | function checkValue(b, q) { 82 | if (b.cmpn(0) <= 0) { throw new Error('invalid sig'); } 83 | if (b.cmp(q) >= 0) { throw new Error('invalid sig'); } 84 | } 85 | 86 | module.exports = verify; 87 | -------------------------------------------------------------------------------- /browser/algorithms.json: -------------------------------------------------------------------------------- 1 | { 2 | "sha224WithRSAEncryption": { 3 | "sign": "rsa", 4 | "hash": "sha224", 5 | "id": "302d300d06096086480165030402040500041c" 6 | }, 7 | "RSA-SHA224": { 8 | "sign": "ecdsa/rsa", 9 | "hash": "sha224", 10 | "id": "302d300d06096086480165030402040500041c" 11 | }, 12 | "sha256WithRSAEncryption": { 13 | "sign": "rsa", 14 | "hash": "sha256", 15 | "id": "3031300d060960864801650304020105000420" 16 | }, 17 | "RSA-SHA256": { 18 | "sign": "ecdsa/rsa", 19 | "hash": "sha256", 20 | "id": "3031300d060960864801650304020105000420" 21 | }, 22 | "sha384WithRSAEncryption": { 23 | "sign": "rsa", 24 | "hash": "sha384", 25 | "id": "3041300d060960864801650304020205000430" 26 | }, 27 | "RSA-SHA384": { 28 | "sign": "ecdsa/rsa", 29 | "hash": "sha384", 30 | "id": "3041300d060960864801650304020205000430" 31 | }, 32 | "sha512WithRSAEncryption": { 33 | "sign": "rsa", 34 | "hash": "sha512", 35 | "id": "3051300d060960864801650304020305000440" 36 | }, 37 | "RSA-SHA512": { 38 | "sign": "ecdsa/rsa", 39 | "hash": "sha512", 40 | "id": "3051300d060960864801650304020305000440" 41 | }, 42 | "RSA-SHA1": { 43 | "sign": "rsa", 44 | "hash": "sha1", 45 | "id": "3021300906052b0e03021a05000414" 46 | }, 47 | "ecdsa-with-SHA1": { 48 | "sign": "ecdsa", 49 | "hash": "sha1", 50 | "id": "" 51 | }, 52 | "sha256": { 53 | "sign": "ecdsa", 54 | "hash": "sha256", 55 | "id": "" 56 | }, 57 | "sha224": { 58 | "sign": "ecdsa", 59 | "hash": "sha224", 60 | "id": "" 61 | }, 62 | "sha384": { 63 | "sign": "ecdsa", 64 | "hash": "sha384", 65 | "id": "" 66 | }, 67 | "sha512": { 68 | "sign": "ecdsa", 69 | "hash": "sha512", 70 | "id": "" 71 | }, 72 | "DSA-SHA": { 73 | "sign": "dsa", 74 | "hash": "sha1", 75 | "id": "" 76 | }, 77 | "DSA-SHA1": { 78 | "sign": "dsa", 79 | "hash": "sha1", 80 | "id": "" 81 | }, 82 | "DSA": { 83 | "sign": "dsa", 84 | "hash": "sha1", 85 | "id": "" 86 | }, 87 | "DSA-WITH-SHA224": { 88 | "sign": "dsa", 89 | "hash": "sha224", 90 | "id": "" 91 | }, 92 | "DSA-SHA224": { 93 | "sign": "dsa", 94 | "hash": "sha224", 95 | "id": "" 96 | }, 97 | "DSA-WITH-SHA256": { 98 | "sign": "dsa", 99 | "hash": "sha256", 100 | "id": "" 101 | }, 102 | "DSA-SHA256": { 103 | "sign": "dsa", 104 | "hash": "sha256", 105 | "id": "" 106 | }, 107 | "DSA-WITH-SHA384": { 108 | "sign": "dsa", 109 | "hash": "sha384", 110 | "id": "" 111 | }, 112 | "DSA-SHA384": { 113 | "sign": "dsa", 114 | "hash": "sha384", 115 | "id": "" 116 | }, 117 | "DSA-WITH-SHA512": { 118 | "sign": "dsa", 119 | "hash": "sha512", 120 | "id": "" 121 | }, 122 | "DSA-SHA512": { 123 | "sign": "dsa", 124 | "hash": "sha512", 125 | "id": "" 126 | }, 127 | "DSA-RIPEMD160": { 128 | "sign": "dsa", 129 | "hash": "rmd160", 130 | "id": "" 131 | }, 132 | "ripemd160WithRSA": { 133 | "sign": "rsa", 134 | "hash": "rmd160", 135 | "id": "3021300906052b2403020105000414" 136 | }, 137 | "RSA-RIPEMD160": { 138 | "sign": "rsa", 139 | "hash": "rmd160", 140 | "id": "3021300906052b2403020105000414" 141 | }, 142 | "md5WithRSAEncryption": { 143 | "sign": "rsa", 144 | "hash": "md5", 145 | "id": "3020300c06082a864886f70d020505000410" 146 | }, 147 | "RSA-MD5": { 148 | "sign": "rsa", 149 | "hash": "md5", 150 | "id": "3020300c06082a864886f70d020505000410" 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /browser/sign.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // much of this based on https://github.com/indutny/self-signed/blob/gh-pages/lib/rsa.js 4 | var Buffer = require('safe-buffer').Buffer; 5 | var createHmac = require('create-hmac'); 6 | var crt = require('browserify-rsa'); 7 | var EC = require('elliptic').ec; 8 | var BN = require('bn.js'); 9 | var parseKeys = require('parse-asn1'); 10 | var curves = require('./curves.json'); 11 | 12 | var RSA_PKCS1_PADDING = 1; 13 | 14 | function sign(hash, key, hashType, signType, tag) { 15 | var priv = parseKeys(key); 16 | if (priv.curve) { 17 | // rsa keys can be interpreted as ecdsa ones in openssl 18 | if (signType !== 'ecdsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong private key type'); } 19 | return ecSign(hash, priv); 20 | } else if (priv.type === 'dsa') { 21 | if (signType !== 'dsa') { throw new Error('wrong private key type'); } 22 | return dsaSign(hash, priv, hashType); 23 | } 24 | if (signType !== 'rsa' && signType !== 'ecdsa/rsa') { throw new Error('wrong private key type'); } 25 | if (key.padding !== undefined && key.padding !== RSA_PKCS1_PADDING) { throw new Error('illegal or unsupported padding mode'); } 26 | 27 | hash = Buffer.concat([tag, hash]); 28 | var len = priv.modulus.byteLength(); 29 | var pad = [0, 1]; 30 | while (hash.length + pad.length + 1 < len) { pad.push(0xff); } 31 | pad.push(0x00); 32 | var i = -1; 33 | while (++i < hash.length) { pad.push(hash[i]); } 34 | 35 | var out = crt(pad, priv); 36 | return out; 37 | } 38 | 39 | function ecSign(hash, priv) { 40 | var curveId = curves[priv.curve.join('.')]; 41 | if (!curveId) { throw new Error('unknown curve ' + priv.curve.join('.')); } 42 | 43 | var curve = new EC(curveId); 44 | var key = curve.keyFromPrivate(priv.privateKey); 45 | var out = key.sign(hash); 46 | 47 | return Buffer.from(out.toDER()); 48 | } 49 | 50 | function dsaSign(hash, priv, algo) { 51 | var x = priv.params.priv_key; 52 | var p = priv.params.p; 53 | var q = priv.params.q; 54 | var g = priv.params.g; 55 | var r = new BN(0); 56 | var k; 57 | var H = bits2int(hash, q).mod(q); 58 | var s = false; 59 | var kv = getKey(x, q, hash, algo); 60 | while (s === false) { 61 | k = makeKey(q, kv, algo); 62 | r = makeR(g, k, p, q); 63 | s = k.invm(q).imul(H.add(x.mul(r))).mod(q); 64 | if (s.cmpn(0) === 0) { 65 | s = false; 66 | r = new BN(0); 67 | } 68 | } 69 | return toDER(r, s); 70 | } 71 | 72 | function toDER(r, s) { 73 | r = r.toArray(); 74 | s = s.toArray(); 75 | 76 | // Pad values 77 | if (r[0] & 0x80) { r = [0].concat(r); } 78 | if (s[0] & 0x80) { s = [0].concat(s); } 79 | 80 | var total = r.length + s.length + 4; 81 | var res = [ 82 | 0x30, total, 0x02, r.length 83 | ]; 84 | res = res.concat(r, [0x02, s.length], s); 85 | return Buffer.from(res); 86 | } 87 | 88 | function getKey(x, q, hash, algo) { 89 | x = Buffer.from(x.toArray()); 90 | if (x.length < q.byteLength()) { 91 | var zeros = Buffer.alloc(q.byteLength() - x.length); 92 | x = Buffer.concat([zeros, x]); 93 | } 94 | var hlen = hash.length; 95 | var hbits = bits2octets(hash, q); 96 | var v = Buffer.alloc(hlen); 97 | v.fill(1); 98 | var k = Buffer.alloc(hlen); 99 | k = createHmac(algo, k).update(v).update(Buffer.from([0])).update(x).update(hbits).digest(); 100 | v = createHmac(algo, k).update(v).digest(); 101 | k = createHmac(algo, k).update(v).update(Buffer.from([1])).update(x).update(hbits).digest(); 102 | v = createHmac(algo, k).update(v).digest(); 103 | return { k: k, v: v }; 104 | } 105 | 106 | function bits2int(obits, q) { 107 | var bits = new BN(obits); 108 | var shift = (obits.length << 3) - q.bitLength(); 109 | if (shift > 0) { bits.ishrn(shift); } 110 | return bits; 111 | } 112 | 113 | function bits2octets(bits, q) { 114 | bits = bits2int(bits, q); 115 | bits = bits.mod(q); 116 | var out = Buffer.from(bits.toArray()); 117 | if (out.length < q.byteLength()) { 118 | var zeros = Buffer.alloc(q.byteLength() - out.length); 119 | out = Buffer.concat([zeros, out]); 120 | } 121 | return out; 122 | } 123 | 124 | function makeKey(q, kv, algo) { 125 | var t; 126 | var k; 127 | 128 | do { 129 | t = Buffer.alloc(0); 130 | 131 | while (t.length * 8 < q.bitLength()) { 132 | kv.v = createHmac(algo, kv.k).update(kv.v).digest(); 133 | t = Buffer.concat([t, kv.v]); 134 | } 135 | 136 | k = bits2int(t, q); 137 | kv.k = createHmac(algo, kv.k).update(kv.v).update(Buffer.from([0])).digest(); 138 | kv.v = createHmac(algo, kv.k).update(kv.v).digest(); 139 | } while (k.cmp(q) !== -1); 140 | 141 | return k; 142 | } 143 | 144 | function makeR(g, k, p, q) { 145 | return g.toRed(BN.mont(p)).redPow(k).fromRed().mod(q); 146 | } 147 | 148 | module.exports = sign; 149 | module.exports.getKey = getKey; 150 | module.exports.makeKey = makeKey; 151 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Buffer = require('safe-buffer').Buffer; 4 | var asn1 = require('parse-asn1/asn1'); 5 | var test = require('tape'); 6 | var nCrypto = require('crypto'); 7 | var semver = require('semver'); 8 | var BN = require('bn.js'); 9 | var parseKeys = require('parse-asn1'); 10 | 11 | var bCrypto = require('../browser'); 12 | var fixtures = require('./fixtures'); 13 | 14 | var supportsPassphrases = semver.satisfies(process.versions.node, '>= 0.11.8'); 15 | 16 | test('valid RSA fixtures', function (t) { 17 | fixtures.valid.rsa.forEach(function (f) { 18 | var message = Buffer.from(f.message); 19 | var pub = Buffer.from(f['public'], 'base64'); 20 | 21 | t.test('fixture: ' + f.message, { skip: !(nCrypto.getHashes().indexOf(f.scheme) >= 0) }, function (st) { 22 | var priv; 23 | 24 | if (f.passphrase) { 25 | if (!supportsPassphrases) { 26 | st.comment('SKIP skipping passphrase test on a node version that lacks support for it'); 27 | st.end(); 28 | return; 29 | } 30 | priv = { 31 | key: Buffer.from(f['private'], 'base64'), 32 | passphrase: f.passphrase 33 | }; 34 | } else { 35 | priv = Buffer.from(f['private'], 'base64'); 36 | } 37 | 38 | var bSign; 39 | try { 40 | bSign = bCrypto.createSign(f.scheme); 41 | } catch (e) { 42 | st.comment('SKIP skipping unsupported browserify-sign scheme ' + f.scheme); 43 | st.end(); 44 | return; 45 | } 46 | 47 | try { 48 | var nSign = nCrypto.createSign(f.scheme); 49 | } catch (e) { 50 | st.comment('SKIP skipping unsupported node scheme ' + f.scheme); 51 | st.end(); 52 | return; 53 | } 54 | 55 | var bSig = bSign.update(message).sign(priv); 56 | var nSig = nSign.update(message).sign(priv); 57 | 58 | st.equals(bSig.length, nSig.length, 'correct length'); 59 | st.equals(bSig.toString('hex'), nSig.toString('hex'), 'equal sigs'); 60 | st.equals(bSig.toString('hex'), f.signature, 'compare to known'); 61 | 62 | st.ok(nCrypto.createVerify(f.scheme).update(message).verify(pub, nSig), 'node validate node sig'); 63 | st.ok(nCrypto.createVerify(f.scheme).update(message).verify(pub, bSig), 'node validate browser sig'); 64 | 65 | st.ok(bCrypto.createVerify(f.scheme).update(message).verify(pub, nSig), 'browser validate node sig'); 66 | st.ok(bCrypto.createVerify(f.scheme).update(message).verify(pub, bSig), 'browser validate browser sig'); 67 | 68 | st.end(); 69 | }); 70 | }); 71 | }); 72 | 73 | // node has padding support since 8.0 74 | // TODO: figure out why node v8.0 - v8.6 is broken 75 | (semver.satisfies(process.versions.node, '>= 8.6') ? test : test.skip)('padding option', function (t) { 76 | var f = fixtures.valid.rsa[0]; 77 | var message = Buffer.from(f.message); 78 | var priv = { 79 | key: Buffer.from(f['private'], 'base64'), 80 | padding: 11646841 // Some invalid value 81 | }; 82 | 83 | t.test('invalid padding option', function (st) { 84 | var bSign = bCrypto.createSign(f.scheme); 85 | var nSign = nCrypto.createSign(f.scheme); 86 | st['throws']( 87 | function () { bSign.update(message).sign(priv); }, 88 | /illegal or unsupported padding mode/, 89 | 'browser throws exception with proper message' 90 | ); 91 | st['throws']( 92 | function () { nSign.update(message).sign(priv); }, 93 | /illegal or unsupported padding mode/, 94 | 'node throws exception with proper message' 95 | ); 96 | 97 | st.end(); 98 | }); 99 | 100 | t.end(); 101 | }); 102 | 103 | test('valid EC fixtures', function (t) { 104 | fixtures.valid.ec.forEach(function (f) { 105 | var message = Buffer.from(f.message); 106 | var pub = Buffer.from(f['public'], 'base64'); 107 | 108 | t.test('fixture: ' + f.message, { skip: !(nCrypto.getHashes().indexOf(f.scheme) >= 0) }, function (st) { 109 | var priv; 110 | 111 | if (f.passphrase) { 112 | if (!supportsPassphrases) { 113 | st.comment('SKIP skipping passphrase test on a node version that lacks support for it'); 114 | st.end(); 115 | return; 116 | } 117 | priv = { 118 | key: Buffer.from(f['private'], 'base64'), 119 | passphrase: f.passphrase 120 | }; 121 | } else { 122 | priv = Buffer.from(f['private'], 'base64'); 123 | } 124 | 125 | var nSign; 126 | try { 127 | nSign = nCrypto.createSign(f.scheme); 128 | } catch (e) { 129 | st.comment('SKIP skipping unsupported browserify-sign scheme', f.scheme); 130 | st.end(); 131 | return; 132 | } 133 | 134 | var bSign; 135 | try { 136 | bSign = bCrypto.createSign(f.scheme); 137 | } catch (e) { 138 | st.comment('SKIP skipping unsupported node scheme', f.scheme); 139 | st.end(); 140 | return; 141 | } 142 | 143 | var bSig = bSign.update(message).sign(priv); 144 | var nSig = nSign.update(message).sign(priv); 145 | st.notEqual(bSig.toString('hex'), nSig.toString('hex'), 'not equal sigs'); 146 | st.equals(bSig.toString('hex'), f.signature, 'sig is determanistic'); 147 | 148 | var nVer = nCrypto.createVerify(f.scheme); 149 | st.ok(nVer.update(message).verify(pub, bSig), 'node validate browser sig'); 150 | 151 | var bVer = bCrypto.createVerify(f.scheme); 152 | st.ok(bVer.update(message).verify(pub, nSig), 'browser validate node sig'); 153 | 154 | if (f.scheme !== 'DSA' && f.scheme.toLowerCase().indexOf('dsa') === -1) { 155 | st.test(f.message + ' named rsa through', function (s2t) { 156 | var scheme = 'RSA-' + f.scheme.toUpperCase(); 157 | var nSign2 = nCrypto.createSign(scheme); 158 | var bSign2 = bCrypto.createSign(scheme); 159 | 160 | var bSig2 = bSign2.update(message).sign(priv); 161 | var nSig2 = nSign2.update(message).sign(priv); 162 | s2t.notEqual(bSig2.toString('hex'), nSig2.toString('hex'), 'not equal sigs'); 163 | s2t.equals(bSig2.toString('hex'), f.signature, 'sig is determanistic'); 164 | 165 | var nVer2 = nCrypto.createVerify(f.scheme); 166 | s2t.ok(nVer2.update(message).verify(pub, bSig2), 'node validate browser sig'); 167 | 168 | var bVer2 = bCrypto.createVerify(f.scheme); 169 | s2t.ok(bVer2.update(message).verify(pub, nSig2), 'browser validate node sig'); 170 | 171 | s2t.end(); 172 | }); 173 | } 174 | 175 | st.end(); 176 | }); 177 | 178 | var s = parseKeys(pub).data.q; 179 | t.test( 180 | f.message + ' against a fake signature', 181 | { skip: !s || '(this test only applies to DSA signatures and not EC signatures, this is ' + f.scheme + ')' }, 182 | function (st) { 183 | var messageBase64 = Buffer.from(f.message, 'base64'); 184 | 185 | // forge a fake signature 186 | var r = new BN('1'); 187 | 188 | try { 189 | var fakeSig = asn1.signature.encode({ r: r, s: s }, 'der'); 190 | } catch (e) { 191 | st.ifError(e); 192 | st.end(); 193 | return; 194 | } 195 | 196 | var bVer = bCrypto.createVerify(f.scheme); 197 | st['throws']( 198 | function () { bVer.update(messageBase64).verify(pub, fakeSig); }, 199 | Error, 200 | 'fake signature is invalid' 201 | ); 202 | 203 | st.end(); 204 | } 205 | ); 206 | }); 207 | }); 208 | 209 | fixtures.valid.kvectors.forEach(function (f) { 210 | test('kvector algo: ' + f.algo + ' key len: ' + f.key.length + ' msg: ' + f.msg, function (t) { 211 | var key = Buffer.from(f.key, 'base64'); 212 | 213 | var bSig = bCrypto.createSign(f.algo).update(f.msg).sign(key); 214 | var bRS = asn1.signature.decode(bSig, 'der'); 215 | t.equals(bRS.r.toString(16), f.r.toLowerCase(), 'r'); 216 | t.equals(bRS.s.toString(16), f.s.toLowerCase(), 's'); 217 | 218 | t.end(); 219 | }); 220 | }); 221 | 222 | fixtures.invalid.verify.forEach(function (f) { 223 | test(f.description, function (t) { 224 | var sign = Buffer.from(f.signature, 'hex'); 225 | var pub = Buffer.from(f['public'], 'base64'); 226 | var message = Buffer.from(f.message); 227 | 228 | var nVerify = nCrypto.createVerify(f.scheme).update(message).verify(pub, sign); 229 | t.notOk(nVerify, 'node rejects it'); 230 | 231 | var bVerify = bCrypto.createVerify(f.scheme).update(message).verify(pub, sign); 232 | t.notOk(bVerify, 'We reject it'); 233 | 234 | t.end(); 235 | }); 236 | }); 237 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [v4.2.5](https://github.com/browserify/browserify-sign/compare/v4.2.4...v4.2.5) - 2025-09-24 9 | 10 | ### Commits 11 | 12 | - [Tests] clean up tests and convert console info skips to tape skips [`37b083c`](https://github.com/browserify/browserify-sign/commit/37b083c602fb6fcd99e0856cba8859dc6f073f3c) 13 | - [Fix] restore node 0.10 support [`faade86`](https://github.com/browserify/browserify-sign/commit/faade86fe051fc0fb1b59e3694a566116e1e79a7) 14 | - [Deps] update `parse-asn1` [`5a0f159`](https://github.com/browserify/browserify-sign/commit/5a0f159e1d32b5c1088a75dceb301afaf40446f9) 15 | - [actions] drop unsupported nodes from CI [`106be97`](https://github.com/browserify/browserify-sign/commit/106be97da87f296f187c44b9ee857384153b5068) 16 | 17 | ## [v4.2.4](https://github.com/browserify/browserify-sign/compare/v4.2.3...v4.2.4) - 2025-09-22 18 | 19 | ### Commits 20 | 21 | - [actions] split out node 10-20, and 20+ [`17920d9`](https://github.com/browserify/browserify-sign/commit/17920d944f04efee7ae2212e4339485ba306b723) 22 | - [meta] remove `files` field [`6d5b280`](https://github.com/browserify/browserify-sign/commit/6d5b280e0496201ba022874c864b0046a74eb45e) 23 | - [Deps] update `bn.js`, `browserify-rsa`, `elliptic` [`31be0c2`](https://github.com/browserify/browserify-sign/commit/31be0c2459e1aad5158f72576c057603bf8527b6) 24 | - [Dev Deps] update `@ljharb/eslint-config`, `auto-changelog`, `semver`, `tape` [`5f66982`](https://github.com/browserify/browserify-sign/commit/5f6698211aa1d6dddaba8c245f40f63ae28924a3) 25 | - [Tests] replace `aud` with `npm audit` [`d44b24d`](https://github.com/browserify/browserify-sign/commit/d44b24d8691d699ccc76780b106fe9c1bf0d1558) 26 | - [Dev Deps] add missing peer dep [`ab975f4`](https://github.com/browserify/browserify-sign/commit/ab975f4845ea5c931df037e7f0df60f045335ae7) 27 | - [Deps] revert 9e2bf12, now that v3.1.1 is out [`428cf7f`](https://github.com/browserify/browserify-sign/commit/428cf7f3f0d09f1b39312e5e51620ca684b5c1ac) 28 | 29 | ## [v4.2.3](https://github.com/browserify/browserify-sign/compare/v4.2.2...v4.2.3) - 2024-03-05 30 | 31 | ### Commits 32 | 33 | - [patch] widen support to 0.12 [`9247adf`](https://github.com/browserify/browserify-sign/commit/9247adfd261ededfec1c036c9d8f36c4e9f87c0e) 34 | - [patch] drop minimum node support to v1 [`4d0ee49`](https://github.com/browserify/browserify-sign/commit/4d0ee49ae2dc238b877dce9aed7e23fb4cb5088d) 35 | - [Dev Deps] update `aud`, `npmignore`, `tape` [`87f3a35`](https://github.com/browserify/browserify-sign/commit/87f3a35a587b377da2c1987af8d41c57b5afe0a5) 36 | - [actions] remove redundant finisher [`37a4758`](https://github.com/browserify/browserify-sign/commit/37a475856843b7d1b2403fdafac0024ba252e579) 37 | - [Deps] pin `hash-base` to ~3.0, due to a breaking change [`9e2bf12`](https://github.com/browserify/browserify-sign/commit/9e2bf122b70970cb92f69d53e963f18299f14d66) 38 | - [Deps] update `parse-asn1 [`f427270`](https://github.com/browserify/browserify-sign/commit/f427270ac11dc6be29f87d7afb046c16376a5a9c) 39 | - [Deps] update `elliptic` [`fb261ce`](https://github.com/browserify/browserify-sign/commit/fb261cea57f92b3d98bc4d8bc6228c43a5de2e91) 40 | - [Deps] pin `elliptic` due to a breaking change [`168e16f`](https://github.com/browserify/browserify-sign/commit/168e16fcb54886a0281b0c983e1482a097042684) 41 | 42 | ## [v4.2.2](https://github.com/browserify/browserify-sign/compare/v4.2.1...v4.2.2) - 2023-10-25 43 | 44 | ### Fixed 45 | 46 | - [Tests] log when openssl doesn't support cipher [`#37`](https://github.com/browserify/browserify-sign/issues/37) 47 | 48 | ### Commits 49 | 50 | - Only apps should have lockfiles [`09a8995`](https://github.com/browserify/browserify-sign/commit/09a89959393b3c89fedd4f7f3bafa4fec44371d7) 51 | - [eslint] switch to eslint [`83fe463`](https://github.com/browserify/browserify-sign/commit/83fe46374b819e959d56d2c0b931308f7451a664) 52 | - [meta] add `npmignore` and `auto-changelog` [`4418183`](https://github.com/browserify/browserify-sign/commit/44181838e7dcc4d5d0c568f74312ea28f0bcdfd5) 53 | - [meta] fix package.json indentation [`9ac5a5e`](https://github.com/browserify/browserify-sign/commit/9ac5a5eaaac8a11eb70ec2febd13745c8764ae02) 54 | - [Tests] migrate from travis to github actions [`d845d85`](https://github.com/browserify/browserify-sign/commit/d845d855def38e2085d5a21e447a48300f99fa60) 55 | - [Fix] `sign`: throw on unsupported padding scheme [`8767739`](https://github.com/browserify/browserify-sign/commit/8767739a4516289568bcce9fed8a3b7e23478de9) 56 | - [Fix] properly check the upper bound for DSA signatures [`85994cd`](https://github.com/browserify/browserify-sign/commit/85994cd6348b50f2fd1b73c54e20881416f44a30) 57 | - [Tests] handle openSSL not supporting a scheme [`f5f17c2`](https://github.com/browserify/browserify-sign/commit/f5f17c27f9824de40b5ce8ebd8502111203fd6af) 58 | - [Deps] update `bn.js`, `browserify-rsa`, `elliptic`, `parse-asn1`, `readable-stream`, `safe-buffer` [`a67d0eb`](https://github.com/browserify/browserify-sign/commit/a67d0eb4ffceabb366b69da69ce9a223e9d5e96b) 59 | - [Dev Deps] update `nyc`, `standard`, `tape` [`cc5350b`](https://github.com/browserify/browserify-sign/commit/cc5350b96702fcba930e0662cf763844fd2f59bf) 60 | - [Tests] always run coverage; downgrade `nyc` [`75ce1d5`](https://github.com/browserify/browserify-sign/commit/75ce1d5c49a6591dd13422016c07f8f9cae13371) 61 | - [meta] add `safe-publish-latest` [`dcf49ce`](https://github.com/browserify/browserify-sign/commit/dcf49ce85a1a66a6fb31689508d916d7894286a9) 62 | - [Tests] add `npm run posttest` [`75dd8fd`](https://github.com/browserify/browserify-sign/commit/75dd8fd6ce56eb37b12e30807e5f913867b21733) 63 | - [Dev Deps] update `tape` [`3aec038`](https://github.com/browserify/browserify-sign/commit/3aec0386dc8dfba8698be756ec770df863867c84) 64 | - [Tests] skip unsupported schemes [`703c83e`](https://github.com/browserify/browserify-sign/commit/703c83ea72db2f45714fe749c6f04b05243ca9a8) 65 | - [Tests] node < 6 lacks array `includes` [`3aa43cf`](https://github.com/browserify/browserify-sign/commit/3aa43cfbc1fdde8481bcdd3bff581574159b869a) 66 | - [Dev Deps] fix eslint range [`98d4e0d`](https://github.com/browserify/browserify-sign/commit/98d4e0d7ff18871b0ca07415f758a610ccf8ebbe) 67 | 68 | ## [v4.2.1](https://github.com/browserify/browserify-sign/compare/v4.2.0...v4.2.1) - 2020-08-04 69 | 70 | ### Merged 71 | 72 | - bump elliptic [`#58`](https://github.com/browserify/browserify-sign/pull/58) 73 | 74 | ## [v4.2.0](https://github.com/browserify/browserify-sign/compare/v4.1.0...v4.2.0) - 2020-05-18 75 | 76 | ### Merged 77 | 78 | - switch to safe buffer [`#53`](https://github.com/browserify/browserify-sign/pull/53) 79 | 80 | ## [v4.1.0](https://github.com/browserify/browserify-sign/compare/v4.0.4...v4.1.0) - 2020-05-05 81 | 82 | ### Merged 83 | 84 | - update deps, modernise usage, use readable-stream [`#49`](https://github.com/browserify/browserify-sign/pull/49) 85 | 86 | ## [v4.0.4](https://github.com/browserify/browserify-sign/compare/v4.0.3...v4.0.4) - 2017-03-28 87 | 88 | ### Merged 89 | 90 | - Fix algorithms require path, add the extension [`#36`](https://github.com/browserify/browserify-sign/pull/36) 91 | 92 | ### Commits 93 | 94 | - extranious semi-colon [`bf59e00`](https://github.com/browserify/browserify-sign/commit/bf59e00d0370a53876597be91a8ff7bfe855e0fc) 95 | 96 | ## [v4.0.3](https://github.com/browserify/browserify-sign/compare/v4.0.2...v4.0.3) - 2017-03-27 97 | 98 | ### Commits 99 | 100 | - files key in the package.json [`1e0bea0`](https://github.com/browserify/browserify-sign/commit/1e0bea0e263e81b89bf564d7e0c7bddd3b7278f9) 101 | 102 | ## [v4.0.2](https://github.com/browserify/browserify-sign/compare/v4.0.1...v4.0.2) - 2017-03-27 103 | 104 | ### Commits 105 | 106 | - put back in algos [`fd27cd3`](https://github.com/browserify/browserify-sign/commit/fd27cd3e6346c054dec937ae53f341740888e03f) 107 | 108 | ## [v4.0.1](https://github.com/browserify/browserify-sign/compare/v4.0.0...v4.0.1) - 2017-03-27 109 | 110 | ### Merged 111 | 112 | - add support for calling ECDSA signatures RSA signatures, cuz node allows it [`#33`](https://github.com/browserify/browserify-sign/pull/33) 113 | - don't generate a new key in ecSign [`#30`](https://github.com/browserify/browserify-sign/pull/30) 114 | - more ecdsa [`#29`](https://github.com/browserify/browserify-sign/pull/29) 115 | - use json files [`#26`](https://github.com/browserify/browserify-sign/pull/26) 116 | - renaming files [`#25`](https://github.com/browserify/browserify-sign/pull/25) 117 | 118 | ### Commits 119 | 120 | - algorithms as JSON file [`c41a01b`](https://github.com/browserify/browserify-sign/commit/c41a01bcb477df1ab20f6d3a311b7801a3da9ff6) 121 | - add new fixtures [`16edebd`](https://github.com/browserify/browserify-sign/commit/16edebde35421ff376aeb7e8e62cfe5a3c1ffbee) 122 | - curves as JSON file [`f40f060`](https://github.com/browserify/browserify-sign/commit/f40f0602f8dc6c2db8c9c1c02dc095a1e4837b89) 123 | - update tests and travis [`9f6e80b`](https://github.com/browserify/browserify-sign/commit/9f6e80b4e1d748958bf46f7ddcb09bd38e8c3a21) 124 | - remove unused files [`9a76f12`](https://github.com/browserify/browserify-sign/commit/9a76f12f6e673c0e9e87aed0d52f13f0ce644865) 125 | - update package.json [`13f7b67`](https://github.com/browserify/browserify-sign/commit/13f7b67e78584a66d2275fc58978bdf59d365b03) 126 | - update README.md [`b03de58`](https://github.com/browserify/browserify-sign/commit/b03de586a090c38e993f5e20ab94edbaa9b87b88) 127 | - nits [`be99732`](https://github.com/browserify/browserify-sign/commit/be99732907b8ae2ea58b8935b6b33e58502239b2) 128 | - we aparently no longer support 0.10 [`aec5180`](https://github.com/browserify/browserify-sign/commit/aec51801103b2755fc4127d2633a1c4369b3f427) 129 | - better message [`06d76ed`](https://github.com/browserify/browserify-sign/commit/06d76ed4abb2094d8f86c395282ba53f1ffe47a6) 130 | - move browser files to folder [`b648108`](https://github.com/browserify/browserify-sign/commit/b64810806e6f6c9c93624f1faa878ad5750a2e18) 131 | 132 | ## [v4.0.0](https://github.com/browserify/browserify-sign/compare/v3.0.8...v4.0.0) - 2015-11-02 133 | 134 | ### Merged 135 | 136 | - upgrade bn and add 2 curves [`#22`](https://github.com/browserify/browserify-sign/pull/22) 137 | - Add LICENSE file. [`#21`](https://github.com/browserify/browserify-sign/pull/21) 138 | 139 | ### Commits 140 | 141 | - Revert "remove p521" [`0ad9f5c`](https://github.com/browserify/browserify-sign/commit/0ad9f5c5b2bed736a254722d3cd7eb779c4b45b7) 142 | - remove p521 [`352ea17`](https://github.com/browserify/browserify-sign/commit/352ea1757d7bbcf1877757c5dc0101a7903c510c) 143 | - add pack in p521 and update deps [`6e58dc4`](https://github.com/browserify/browserify-sign/commit/6e58dc410fa923344b9b1c7863fbf5c5f8f4f731) 144 | - Create LICENSE [`e31c4a1`](https://github.com/browserify/browserify-sign/commit/e31c4a1e3c66a6124191e52052cadb4710814d71) 145 | - update deps [`7ca87bc`](https://github.com/browserify/browserify-sign/commit/7ca87bc5465a9d19b4a01542eb99d70d97e84c6f) 146 | - patch bn to 4.1.1 [`bd8dc2e`](https://github.com/browserify/browserify-sign/commit/bd8dc2e9eb8bd5cd4b7b255c1914c2f34f594ace) 147 | - LICENSE: add @calvinmetcalf [`153a93f`](https://github.com/browserify/browserify-sign/commit/153a93f0f05c4368c76789df2df4a09ea455a8a9) 148 | - package: adds description [`555b793`](https://github.com/browserify/browserify-sign/commit/555b79372cc4e8c29049e7f2b027f2694f7c7dd5) 149 | 150 | ## [v3.0.8](https://github.com/browserify/browserify-sign/compare/v3.0.3...v3.0.8) - 2015-09-05 151 | 152 | ### Merged 153 | 154 | - Format [`#20`](https://github.com/browserify/browserify-sign/pull/20) 155 | - Fixes unreachable return error [`#19`](https://github.com/browserify/browserify-sign/pull/19) 156 | 157 | ### Fixed 158 | 159 | - adds standard (resolves #15) [`#15`](https://github.com/browserify/browserify-sign/issues/15) 160 | 161 | ### Commits 162 | 163 | - add dsa back in [`1b8014d`](https://github.com/browserify/browserify-sign/commit/1b8014d8edfc228dc1f21e2b98442d1d297be458) 164 | - merge [`6ada8de`](https://github.com/browserify/browserify-sign/commit/6ada8de15ebe83cedbaa2242409dbb1de441b5ed) 165 | - standard format [`4f8a8e9`](https://github.com/browserify/browserify-sign/commit/4f8a8e90122eb1fab9be86cdfdf697989e51a507) 166 | - comment unused functions [`2c68e08`](https://github.com/browserify/browserify-sign/commit/2c68e0828fe5c494ee5b75742bef549171404eea) 167 | - fix use of lowercase constructor [`5032abe`](https://github.com/browserify/browserify-sign/commit/5032abe9eaaef64546f9ed085f9cf23f96eabe9a) 168 | - README: remove TODOs [`dd76c98`](https://github.com/browserify/browserify-sign/commit/dd76c988ce7d1a6ff24e5ea55408d1771aa62380) 169 | - algos: use 2 spaces, not tabs [`7097997`](https://github.com/browserify/browserify-sign/commit/709799742c576a57ead7d3686f00ad21de78112d) 170 | - .travis.yml: update to new targets [`668ab5b`](https://github.com/browserify/browserify-sign/commit/668ab5b2f656854098c95d0f82b4b3b9da9e5c39) 171 | - rm unused exports [`ddc0820`](https://github.com/browserify/browserify-sign/commit/ddc0820c766ceda98dcaf8d8bb99647d86b2fb0b) 172 | - Rename readme.md to README.md [`557119b`](https://github.com/browserify/browserify-sign/commit/557119b51a6f8373bdededdedbd9d86be7801646) 173 | - package: fix bad JSON [`b25808b`](https://github.com/browserify/browserify-sign/commit/b25808bea4860136edd87ced17d6bb6ccc6e143a) 174 | 175 | ## [v3.0.3](https://github.com/browserify/browserify-sign/compare/v3.0.2...v3.0.3) - 2015-08-07 176 | 177 | ### Merged 178 | 179 | - add npmignore [`#17`](https://github.com/browserify/browserify-sign/pull/17) 180 | 181 | ## [v3.0.2](https://github.com/browserify/browserify-sign/compare/v3.0.1...v3.0.2) - 2015-05-20 182 | 183 | ### Merged 184 | 185 | - correct error message [`#12`](https://github.com/browserify/browserify-sign/pull/12) 186 | 187 | ### Commits 188 | 189 | - failing test [`93be166`](https://github.com/browserify/browserify-sign/commit/93be16675c1b276b5aae918d9cdf5825dc47cd4a) 190 | - update deps, fixutres, and verify [`ef78685`](https://github.com/browserify/browserify-sign/commit/ef78685c39f9e234208a96488bdb845ea7ddaa18) 191 | - test our own sigs [`2ea39b2`](https://github.com/browserify/browserify-sign/commit/2ea39b275415bf246ff0521e3a1f1fe99f91c3b5) 192 | - update elleptic all the way [`525ea93`](https://github.com/browserify/browserify-sign/commit/525ea93f74e1543e722c6f967cb394e4b71fbd75) 193 | 194 | ## [v3.0.1](https://github.com/browserify/browserify-sign/compare/v3.0.0...v3.0.1) - 2015-03-11 195 | 196 | ### Commits 197 | 198 | - tests: move all pre-produced data to fixtures, tests only test [`578bd27`](https://github.com/browserify/browserify-sign/commit/578bd275edb23e07d7a2e378d9f4442f29237970) 199 | - inline fixtures [`c7fd8eb`](https://github.com/browserify/browserify-sign/commit/c7fd8eba2e58ccca5b2ba11c9a6cb447ec9b6a58) 200 | - fixtures: convert to pure JSON [`1695735`](https://github.com/browserify/browserify-sign/commit/16957358f2026687035a999e56fcccc7e12c656d) 201 | - passes standard [`2ba9c4c`](https://github.com/browserify/browserify-sign/commit/2ba9c4ce4b3a2fde1252da3b73f9c5dc3fedd491) 202 | - rm node11 attribute [`456236d`](https://github.com/browserify/browserify-sign/commit/456236d0bab2d0f1aa3c365447ff6e6165c2c45e) 203 | - check sign type [`af82685`](https://github.com/browserify/browserify-sign/commit/af826857539b1abf7075d65b21784cfabeff8d2c) 204 | - tests/fixtures: re-compute signatures and assert equality [`69c0dd3`](https://github.com/browserify/browserify-sign/commit/69c0dd307251727c1d0db05868458451961b0215) 205 | - fix tests in node 10 and 3 formatting issues [`a8796b0`](https://github.com/browserify/browserify-sign/commit/a8796b01dc99bbe393be49a1c5d74b71a385e7c3) 206 | - tests: sort requires [`33591b9`](https://github.com/browserify/browserify-sign/commit/33591b9af8307f27178138271d26c020e72c6033) 207 | - more tests [`3db65cf`](https://github.com/browserify/browserify-sign/commit/3db65cf75e990b0bc3f7a6fa1599197977c0a4c8) 208 | - propper node10 test [`b0aa652`](https://github.com/browserify/browserify-sign/commit/b0aa65210afcb299e9a945fdf82a068a4821f5e8) 209 | - fix typo in travis.yml [`4e42f0a`](https://github.com/browserify/browserify-sign/commit/4e42f0ac4c7b9a3cb751f41126b26749354b105d) 210 | 211 | ## [v3.0.0](https://github.com/browserify/browserify-sign/compare/v2.8.0...v3.0.0) - 2015-03-10 212 | 213 | ### Merged 214 | 215 | - Modularize [`#8`](https://github.com/browserify/browserify-sign/pull/8) 216 | 217 | ### Commits 218 | 219 | - modularize format [`d2a3f77`](https://github.com/browserify/browserify-sign/commit/d2a3f77b244ce8e967bd2b3067cdfaee670dfecf) 220 | - better [`5077b98`](https://github.com/browserify/browserify-sign/commit/5077b984edc44440b65579fe100d74ca3e91a823) 221 | - properly check signatures and test for it [`48f8881`](https://github.com/browserify/browserify-sign/commit/48f888175d1c1ab727cebba73def1dec48769375) 222 | - other 3 curves [`b78737b`](https://github.com/browserify/browserify-sign/commit/b78737b27e1bcaae3f771caa89f7161bdc17c1f3) 223 | - determanistic k [`2e1bf48`](https://github.com/browserify/browserify-sign/commit/2e1bf48e180d2ea699225b6e584e3a30c90ba312) 224 | - formatting [`07a8727`](https://github.com/browserify/browserify-sign/commit/07a87278e6eb13539ee0a58262df3213e8cea4da) 225 | - fixed bug with hash shorter then q [`438717a`](https://github.com/browserify/browserify-sign/commit/438717a2f00efbae18ba158b436555d56f2c9bbd) 226 | - sign: s/getKay/getKey [`cec421c`](https://github.com/browserify/browserify-sign/commit/cec421c69d563f4cc51df5d0c323ed294e0df33e) 227 | - make sure everything is strict [`3f10450`](https://github.com/browserify/browserify-sign/commit/3f1045017b95fdb0a0da87fe57b467705edbafdf) 228 | 229 | ## [v2.8.0](https://github.com/browserify/browserify-sign/compare/v2.7.5...v2.8.0) - 2015-01-12 230 | 231 | ### Commits 232 | 233 | - better [`18b953c`](https://github.com/browserify/browserify-sign/commit/18b953c021e88ccdcdab809f93a1d5d2a42d3ea0) 234 | - determanistic k [`9f1c348`](https://github.com/browserify/browserify-sign/commit/9f1c348009475ac7872e9f4e0f014bb15b88101f) 235 | - fixed bug with hash shorter then q [`222dc8e`](https://github.com/browserify/browserify-sign/commit/222dc8ecb01f01999f69634af57ae9e64489dfb0) 236 | 237 | ## [v2.7.5](https://github.com/browserify/browserify-sign/compare/v2.7.4...v2.7.5) - 2015-01-06 238 | 239 | ### Commits 240 | 241 | - update eliptic [`e4e5b42`](https://github.com/browserify/browserify-sign/commit/e4e5b427f7c3be3c1ded12147a66b134ae31eb0c) 242 | 243 | ## [v2.7.4](https://github.com/browserify/browserify-sign/compare/v2.7.3...v2.7.4) - 2015-01-06 244 | 245 | ### Commits 246 | 247 | - update parse-asn1 [`22a3f57`](https://github.com/browserify/browserify-sign/commit/22a3f57340c08211547f14b63ab0cc9ab5d97dc9) 248 | 249 | ## [v2.7.3](https://github.com/browserify/browserify-sign/compare/v2.7.2...v2.7.3) - 2015-01-06 250 | 251 | ### Commits 252 | 253 | - Update bn.js [`4519962`](https://github.com/browserify/browserify-sign/commit/4519962b2d2b73a9a118296de98280411f07fd2d) 254 | 255 | ## [v2.7.2](https://github.com/browserify/browserify-sign/compare/v2.7.1...v2.7.2) - 2015-01-05 256 | 257 | ### Commits 258 | 259 | - aliases for sign and verify [`fcc366f`](https://github.com/browserify/browserify-sign/commit/fcc366ffe2f60e9c20d9b62b2321a96f7e9445d6) 260 | 261 | ## [v2.7.1](https://github.com/browserify/browserify-sign/compare/v2.7.0...v2.7.1) - 2015-01-03 262 | 263 | ### Commits 264 | 265 | - Update bn.js [`c55b4aa`](https://github.com/browserify/browserify-sign/commit/c55b4aa577ef6a9414c366c760206434f97e3cce) 266 | 267 | ## [v2.7.0](https://github.com/browserify/browserify-sign/compare/v2.6.1...v2.7.0) - 2014-12-22 268 | 269 | ### Commits 270 | 271 | - pull out rsa stuff [`0c076ff`](https://github.com/browserify/browserify-sign/commit/0c076ff1ff2aa4b626cdf25911200090a60d86c4) 272 | 273 | ## [v2.6.1](https://github.com/browserify/browserify-sign/compare/v2.6.0...v2.6.1) - 2014-12-19 274 | 275 | ### Commits 276 | 277 | - just use regular stream not readable [`dfdd33d`](https://github.com/browserify/browserify-sign/commit/dfdd33d4bfd4823aa0308aa8215d6a32dfc210e9) 278 | 279 | ## [v2.6.0](https://github.com/browserify/browserify-sign/compare/v2.5.2...v2.6.0) - 2014-12-18 280 | 281 | ### Commits 282 | 283 | - dsa [`e01ff39`](https://github.com/browserify/browserify-sign/commit/e01ff3987ecf80670bb6e5d38ad7a1dc08a429b0) 284 | - varient encoding of password protected keys [`eaaf2d5`](https://github.com/browserify/browserify-sign/commit/eaaf2d53a385d6b13fcff33734675c3d886b5b51) 285 | 286 | ## [v2.5.2](https://github.com/browserify/browserify-sign/compare/v2.5.1...v2.5.2) - 2014-12-17 287 | 288 | ### Commits 289 | 290 | - pull out parseKey [`b25775e`](https://github.com/browserify/browserify-sign/commit/b25775e1f4ed1b3df3ed776f3d0a352f2fa338cf) 291 | 292 | ## [v2.5.1](https://github.com/browserify/browserify-sign/compare/v2.5.0...v2.5.1) - 2014-12-09 293 | 294 | ### Commits 295 | 296 | - circular dependancy [`1c15e75`](https://github.com/browserify/browserify-sign/commit/1c15e75b27a20b34bb7dd32eb833beb57716f69c) 297 | 298 | ## [v2.5.0](https://github.com/browserify/browserify-sign/compare/v2.4.0...v2.5.0) - 2014-11-25 299 | 300 | ### Commits 301 | 302 | - add md5 and ripemd160 also make sure to include algorythm id when verifying [`da03fb0`](https://github.com/browserify/browserify-sign/commit/da03fb07ad10b61f4386560503802e16af8fa80e) 303 | - cross off ecdsa [`1a3e3f3`](https://github.com/browserify/browserify-sign/commit/1a3e3f3e466c3de43ff02fd5434922e3b19fe77b) 304 | 305 | ## [v2.4.0](https://github.com/browserify/browserify-sign/compare/v2.3.0...v2.4.0) - 2014-11-16 306 | 307 | ### Commits 308 | 309 | - eliptical curves [`17745d2`](https://github.com/browserify/browserify-sign/commit/17745d23773baad7b1ec1289d86ac46e87da9323) 310 | - ecdsa with password [`2186465`](https://github.com/browserify/browserify-sign/commit/2186465dab56a1468d13964a3c6b3ef7b2b44437) 311 | - encryption is out of scope [`f975416`](https://github.com/browserify/browserify-sign/commit/f97541615c9853b276a33cf40f394e079f3988b9) 312 | 313 | ## [v2.3.0](https://github.com/browserify/browserify-sign/compare/v2.2.0...v2.3.0) - 2014-11-15 314 | 315 | ### Commits 316 | 317 | - Chinese remainder algorithm [`140a41f`](https://github.com/browserify/browserify-sign/commit/140a41fb482e02716e0d7b79ae390f6979cab031) 318 | 319 | ## [v2.2.0](https://github.com/browserify/browserify-sign/compare/v2.1.0...v2.2.0) - 2014-11-15 320 | 321 | ### Commits 322 | 323 | - passwords! [`8c95b09`](https://github.com/browserify/browserify-sign/commit/8c95b09e5ba43d041f6527e3d62e7e216ec1d5ae) 324 | 325 | ## v2.1.0 - 2014-11-15 326 | 327 | ### Commits 328 | 329 | - in prog [`d55225f`](https://github.com/browserify/browserify-sign/commit/d55225f0c3bd669ad616481dbc347fcab6654db1) 330 | - working! [`130b1e2`](https://github.com/browserify/browserify-sign/commit/130b1e2703f807ff58ebf26612487a9a4d1e875c) 331 | - generic key files [`7bd3f91`](https://github.com/browserify/browserify-sign/commit/7bd3f91d99b79a6077efb7c2239fcde5e2ebe95c) 332 | - node stuff [`342c74f`](https://github.com/browserify/browserify-sign/commit/342c74f0db7ae0ae071f898f1cd8fcce3170b851) 333 | - repo [`7e9b914`](https://github.com/browserify/browserify-sign/commit/7e9b91446c335d41e9e53466f8b4e07b697570ac) 334 | - todo [`15410f2`](https://github.com/browserify/browserify-sign/commit/15410f260d813e07213b4bb51a2d2a747a8fd82a) 335 | - test messages [`735a056`](https://github.com/browserify/browserify-sign/commit/735a056eb785387510bb9f0624ea6528447c4b8b) 336 | - travis .yml file [`173fd78`](https://github.com/browserify/browserify-sign/commit/173fd7806d63d9808a2b1a7167b1fd3780f34a0d) 337 | - travis [`9b562e6`](https://github.com/browserify/browserify-sign/commit/9b562e633e26e266153756cc70e0ba90284a0b3b) 338 | --------------------------------------------------------------------------------