├── .gitignore ├── .npmignore ├── .travis.yml ├── .zuul.yml ├── LICENSE ├── README.md ├── index.js ├── package.json └── test ├── aes.js ├── create-hash.js ├── create-hmac.js ├── dh.js ├── ecdh.js ├── index.js ├── node └── dh.js ├── pbkdf2.js ├── public-encrypt.js ├── random-bytes.js ├── random-fill.js └── sign.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | example 2 | test 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | matrix: 4 | include: 5 | - node_js: '0.10' 6 | env: TEST_SUITE=unit 7 | - node_js: '0.11' 8 | env: TEST_SUITE=unit 9 | - node_js: '0.12' 10 | env: TEST_SUITE=unit 11 | - node_js: '4' 12 | env: TEST_SUITE=unit 13 | - node_js: '4' 14 | env: TEST_SUITE=standard 15 | - node_js: '4' 16 | env: TEST_SUITE=browser BROWSER_NAME=ie BROWSER_VERSION="10..latest" 17 | - node_js: '4' 18 | env: TEST_SUITE=browser BROWSER_NAME=chrome BROWSER_VERSION="44..beta" 19 | - node_js: '4' 20 | env: TEST_SUITE=browser BROWSER_NAME=firefox BROWSER_VERSION="40..latest" 21 | - node_js: '4' 22 | env: TEST_SUITE=browser BROWSER_NAME=iphone BROWSER_VERSION="8.0..latest" 23 | - node_js: '4' 24 | env: TEST_SUITE=browser BROWSER_NAME=safari BROWSER_VERSION="5..latest" 25 | - node_js: '4' 26 | env: TEST_SUITE=browser BROWSER_NAME=android BROWSER_VERSION="4.0..latest" 27 | script: "npm run-script $TEST_SUITE" 28 | env: 29 | global: 30 | - secure: YHNUDQmx/WiW3gmDcRCfb6KLDeio7Mr5tqPY2kHPdZlBSytsQjNk75ytM4U6Cu8Uk8iEIoj/aFlxiVMpJNA8J4QSUyW/YkbVaIz0+1oywoV0Ht8aRBfZ1jvXfX6789+1Q9c4xaMkYYbJpXSh9JcirsiwmqWd4+IDd7hcESodsDQ= 31 | - secure: Nhj5yejKZxUbtHGZta+GjYWqXGaOZB7ainTkOuGcpXM+OwwjeDpYlTBrwS90Q7hqens7KXVzQM09aDbadpsDCsOo1nyaEigMtomAorZ1UC1CpEoVz1ZuikF9bEhb+/7M9pzuL1fX+Ke9Dx4mPPeb8sf/2SrAu1RqXkSwZV/duAc= 32 | -------------------------------------------------------------------------------- /.zuul.yml: -------------------------------------------------------------------------------- 1 | ui: tape 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013 Dominic Tarr 4 | 5 | Permission is hereby granted, free of charge, 6 | to any person obtaining a copy of this software and 7 | associated documentation files (the "Software"), to 8 | deal in the Software without restriction, including 9 | without limitation the rights to use, copy, modify, 10 | merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom 12 | the Software is furnished to do so, 13 | subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice 16 | shall be included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 22 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-crypto 2 | 3 | Note: this module is a clone of [crypto-browserify](https://github.com/crypto-browserify/crypto-browserify), with randombytes replaced. 4 | 5 | A port of node's `crypto` module to React Native. 6 | 7 | ## DEPRECATED 8 | 9 | you should probably use a combination of: 10 | - react-native-get-random-values to shim getRandomValues 11 | - crypto-browserify 12 | 13 | ## install 14 | 15 | Because this module depends on some node core modules, and react-native doesn't currently have a [resolve.alias a la webpack](https://productpains.com/post/react-native/packager-support-resolvealias-ala-webpack), you will need to use [rn-nodeify](https://github.com/tradle/rn-nodeify) for your shimming needs. 16 | 17 | A suggested workflow: 18 | 19 | 1. Install 20 | ```sh 21 | npm i --save react-native-crypto 22 | # install peer deps 23 | npm i --save react-native-randombytes 24 | react-native link react-native-randombytes # on RN >= 0.60, instead do: cd iOS && pod install 25 | # install latest rn-nodeify 26 | npm i --save-dev rn-nodeify 27 | # install node core shims and recursively hack package.json files 28 | # in ./node_modules to add/update the "browser"/"react-native" field with relevant mappings 29 | ./node_modules/.bin/rn-nodeify --hack --install 30 | ``` 31 | 32 | 2. `rn-nodeify` will create a `shim.js` in the project root directory 33 | ```js 34 | // index.ios.js or index.android.js 35 | // make sure you use `import` and not require! 36 | import './shim.js' 37 | import crypto from 'crypto' 38 | // ...the rest of your code 39 | ``` 40 | 41 | ## example 42 | 43 | see https://github.com/mvayngrib/rncryptoexample 44 | 45 | ## the crypto in this box 46 | 47 | What follows is unedited text from crypto-browserify 48 | 49 | The goal of this module is to reimplement node's crypto module so that it can run in react-native supported environments. 50 | 51 | Here is the subset that is currently implemented: 52 | 53 | * createHash (sha1, sha224, sha256, sha384, sha512, md5, rmd160) 54 | * createHmac (sha1, sha224, sha256, sha384, sha512, md5, rmd160) 55 | * pbkdf2 56 | * pbkdf2Sync 57 | * randomBytes 58 | * pseudoRandomBytes 59 | * createCipher (aes) 60 | * createDecipher (aes) 61 | * createDiffieHellman 62 | * createSign (rsa, ecdsa) 63 | * createVerify (rsa, ecdsa) 64 | * createECDH (secp256k1) 65 | * publicEncrypt/privateDecrypt (rsa) 66 | * randomFillSync 67 | * randomFill 68 | 69 | ## todo 70 | 71 | these features from node's `crypto` are still unimplemented. 72 | 73 | * createCredentials 74 | * scryptSync 75 | 76 | these features would benefit from native implementations 77 | 78 | * pbkdf2 79 | * createSign 80 | * createVerify 81 | * createECDH 82 | * publicEncrypto/privateDecrypt (rsa) 83 | 84 | ## contributions 85 | 86 | If you are interested in writing a feature, please implement as a new module, 87 | which will be incorporated into crypto-browserify as a dependency. 88 | 89 | All deps must be compatible with node's crypto 90 | (generate example inputs and outputs with node, 91 | and save base64 strings inside JSON, so that tests can run in the browser. 92 | see [sha.js](https://github.com/dominictarr/sha.js) 93 | 94 | Crypto is _extra serious_ so please do not hesitate to review the code, 95 | and post comments if you do. 96 | 97 | ## License 98 | 99 | MIT 100 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | import { randomBytes } from 'react-native-randombytes' 4 | exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes 5 | 6 | // implement window.getRandomValues(), for packages that rely on it 7 | if (typeof window === 'object') { 8 | if (!window.crypto) window.crypto = {} 9 | if (!window.crypto.getRandomValues) { 10 | window.crypto.getRandomValues = function getRandomValues (arr) { 11 | let orig = arr 12 | if (arr.byteLength != arr.length) { 13 | // Get access to the underlying raw bytes 14 | arr = new Uint8Array(arr.buffer) 15 | } 16 | const bytes = randomBytes(arr.length) 17 | for (var i = 0; i < bytes.length; i++) { 18 | arr[i] = bytes[i] 19 | } 20 | 21 | return orig 22 | } 23 | } 24 | } 25 | 26 | exports.createHash = exports.Hash = require('create-hash') 27 | exports.createHmac = exports.Hmac = require('create-hmac') 28 | 29 | var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(Object.keys(require('browserify-sign/algos'))) 30 | exports.getHashes = function () { 31 | return hashes 32 | } 33 | 34 | var p = require('pbkdf2') 35 | exports.pbkdf2 = p.pbkdf2 36 | exports.pbkdf2Sync = p.pbkdf2Sync 37 | 38 | var aes = require('browserify-cipher') 39 | ;[ 40 | 'Cipher', 41 | 'createCipher', 42 | 'Cipheriv', 43 | 'createCipheriv', 44 | 'Decipher', 45 | 'createDecipher', 46 | 'Decipheriv', 47 | 'createDecipheriv', 48 | 'getCiphers', 49 | 'listCiphers' 50 | ].forEach(function (key) { 51 | exports[key] = aes[key] 52 | }) 53 | 54 | var dh = require('diffie-hellman') 55 | ;[ 56 | 'DiffieHellmanGroup', 57 | 'createDiffieHellmanGroup', 58 | 'getDiffieHellman', 59 | 'createDiffieHellman', 60 | 'DiffieHellman' 61 | ].forEach(function (key) { 62 | exports[key] = dh[key] 63 | }) 64 | 65 | var sign = require('browserify-sign') 66 | ;[ 67 | 'createSign', 68 | 'Sign', 69 | 'createVerify', 70 | 'Verify' 71 | ].forEach(function (key) { 72 | exports[key] = sign[key] 73 | }) 74 | 75 | exports.createECDH = require('create-ecdh') 76 | 77 | var publicEncrypt = require('public-encrypt') 78 | 79 | ;[ 80 | 'publicEncrypt', 81 | 'privateEncrypt', 82 | 'publicDecrypt', 83 | 'privateDecrypt' 84 | ].forEach(function (key) { 85 | exports[key] = publicEncrypt[key] 86 | }) 87 | 88 | var rf = require('randomfill') 89 | 90 | exports.randomFill = rf.randomFill 91 | exports.randomFillSync = rf.randomFillSync 92 | 93 | // the least I can do is make error messages for the rest of the node.js/crypto api. 94 | ;[ 95 | 'createCredentials' 96 | ].forEach(function (name) { 97 | exports[name] = function () { 98 | throw new Error([ 99 | 'sorry, ' + name + ' is not implemented yet', 100 | 'we accept pull requests', 101 | 'https://github.com/crypto-browserify/crypto-browserify' 102 | ].join('\n')) 103 | } 104 | }) 105 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Dominic Tarr (dominictarr.com)", 3 | "name": "react-native-crypto", 4 | "description": "implementation of crypto for React Native", 5 | "version": "2.2.0", 6 | "homepage": "https://github.com/tradle/react-native-crypto", 7 | "repository": { 8 | "type": "git", 9 | "url": "git://github.com/tradle/react-native-crypto.git" 10 | }, 11 | "scripts": { 12 | "standard": "standard", 13 | "test": "npm run standard && npm run unit", 14 | "unit": "Echo 'tests not set up for React Native yet'" 15 | }, 16 | "engines": { 17 | "node": "*" 18 | }, 19 | "dependencies": { 20 | "browserify-cipher": "^1.0.0", 21 | "browserify-sign": "^4.0.4", 22 | "create-ecdh": "^4.0.0", 23 | "create-hash": "^1.1.0", 24 | "create-hmac": "^1.1.0", 25 | "diffie-hellman": "^5.0.0", 26 | "inherits": "^2.0.1", 27 | "pbkdf2": "3.0.8", 28 | "public-encrypt": "^4.0.0", 29 | "randomfill": "^1.0.3" 30 | }, 31 | "peerDependencies": { 32 | "react-native-randombytes": ">=2.0.0 <4.0.0" 33 | }, 34 | "devDependencies": { 35 | "hash-test-vectors": "~1.3.2", 36 | "pseudorandombytes": "^2.0.0", 37 | "standard": "^5.0.2", 38 | "tape": "~2.3.2", 39 | "zuul": "^3.6.0" 40 | }, 41 | "optionalDependencies": {}, 42 | "keywords": [ 43 | "react-native", 44 | "react-component", 45 | "ios" 46 | ], 47 | "license": "MIT" 48 | } 49 | -------------------------------------------------------------------------------- /test/aes.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var crypto = require('browserify-cipher/browser') 3 | var randomBytes = require('pseudorandombytes') 4 | 5 | function runIt (i) { 6 | crypto.listCiphers().forEach(function (cipher) { 7 | test('run: ' + i, function (t) { 8 | t.test('ciphers: ' + cipher, function (t) { 9 | t.plan(1) 10 | var data = randomBytes(562) 11 | var password = randomBytes(20) 12 | var crypter = crypto.createCipher(cipher, password) 13 | var decrypter = crypto.createDecipher(cipher, password) 14 | var out = [] 15 | out.push(decrypter.update(crypter.update(data))) 16 | out.push(decrypter.update(crypter.final())) 17 | if (cipher.indexOf('gcm') > -1) { 18 | decrypter.setAuthTag(crypter.getAuthTag()) 19 | } 20 | out.push(decrypter.final()) 21 | t.equals(data.toString('hex'), Buffer.concat(out).toString('hex')) 22 | }) 23 | }) 24 | }) 25 | if (i < 4) { 26 | setTimeout(runIt, 0, i + 1) 27 | } 28 | } 29 | runIt(1) 30 | test('getCiphers', function (t) { 31 | t.plan(1) 32 | t.ok(crypto.getCiphers().length, 'get ciphers returns an array') 33 | }) 34 | 35 | test('through crypto browserify works', function (t) { 36 | t.plan(2) 37 | var crypto = require('../') 38 | var cipher = 'aes-128-ctr' 39 | var data = randomBytes(562) 40 | var password = randomBytes(20) 41 | var crypter = crypto.createCipher(cipher, password) 42 | var decrypter = crypto.createDecipher(cipher, password) 43 | var out = [] 44 | out.push(decrypter.update(crypter.update(data))) 45 | out.push(decrypter.update(crypter.final())) 46 | out.push(decrypter.final()) 47 | t.equals(data.toString('hex'), Buffer.concat(out).toString('hex')) 48 | t.ok(crypto.getCiphers().length, 'get ciphers returns an array') 49 | }) 50 | -------------------------------------------------------------------------------- /test/create-hash.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | 3 | var algorithms = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'] 4 | var encodings = ['hex', 'base64'] // FIXME: test binary 5 | var vectors = require('hash-test-vectors') 6 | 7 | testLib('createHash in crypto-browserify', require('../').createHash) 8 | testLib('create-hash/browser', require('create-hash/browser')) 9 | 10 | function testLib (name, createHash) { 11 | algorithms.forEach(function (algorithm) { 12 | runTest(name, createHash, algorithm) 13 | }) 14 | } 15 | function runTest (name, createHash, algorithm) { 16 | test(name + ' test ' + algorithm + ' against test vectors', function (t) { 17 | run(0) 18 | function run (i) { 19 | if (i >= vectors.length) { 20 | return t.end() 21 | } 22 | var obj = vectors[i] 23 | 24 | var input = new Buffer(obj.input, 'base64') 25 | var node = obj[algorithm] 26 | var js = createHash(algorithm).update(input).digest('hex') 27 | if (js !== node) { 28 | t.equal(js, node, algorithm + '(testVector[' + i + ']) == ' + node) 29 | } 30 | 31 | encodings.forEach(function (encoding) { 32 | var input = new Buffer(obj.input, 'base64').toString(encoding) 33 | var node = obj[algorithm] 34 | var js = createHash(algorithm).update(input, encoding).digest('hex') 35 | if (js !== node) { 36 | t.equal(js, node, algorithm + '(testVector[' + i + '], ' + encoding + ') == ' + node) 37 | } 38 | }) 39 | input = new Buffer(obj.input, 'base64') 40 | node = obj[algorithm] 41 | var hash = createHash(algorithm) 42 | hash.end(input) 43 | js = hash.read().toString('hex') 44 | if (js !== node) { 45 | t.equal(js, node, algorithm + '(testVector[' + i + ']) == ' + node) 46 | } 47 | setTimeout(run, 0, i + 1) 48 | } 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /test/create-hmac.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | 3 | var algorithms = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'] 4 | var vectors = require('hash-test-vectors/hmac') 5 | testLib('createHmac in crypto-browserify', require('../').createHmac) 6 | testLib('create-hmac/browser', require('create-hmac/browser')) 7 | 8 | function testLib (name, createHmac) { 9 | algorithms.forEach(function (alg) { 10 | test(name + ' hmac(' + alg + ')', function (t) { 11 | run(0) 12 | function run (i) { 13 | if (i >= vectors.length) { 14 | return t.end() 15 | } 16 | var input = vectors[i] 17 | var output = createHmac(alg, new Buffer(input.key, 'hex')) 18 | .update(input.data, 'hex').digest() 19 | 20 | output = input.truncate ? output.slice(0, input.truncate) : output 21 | output = output.toString('hex') 22 | if (output !== input[alg]) { 23 | t.equal(output, input[alg]) 24 | } 25 | setTimeout(run, 0, i + 1) 26 | } 27 | }) 28 | 29 | test('hmac(' + alg + ')', function (t) { 30 | run(0) 31 | function run (i) { 32 | if (i >= vectors.length) { 33 | return t.end() 34 | } 35 | var input = vectors[i] 36 | var hmac = createHmac(alg, new Buffer(input.key, 'hex')) 37 | 38 | hmac.end(input.data, 'hex') 39 | var output = hmac.read() 40 | 41 | output = input.truncate ? output.slice(0, input.truncate) : output 42 | output = output.toString('hex') 43 | if (output !== input[alg]) { 44 | t.equal(output, input[alg]) 45 | } 46 | setTimeout(run, 0, i + 1) 47 | } 48 | }) 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /test/dh.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var crypto = require('diffie-hellman/browser') 3 | 4 | test('diffie-hellman mod groups', function (t) { 5 | [ 6 | 'modp1', 'modp2', 'modp5', 'modp14', 'modp15', 'modp16' 7 | ].forEach(function (mod) { 8 | t.test(mod, function (t) { 9 | t.plan(3) 10 | var dh1 = crypto.getDiffieHellman(mod) 11 | var p1 = dh1.getPrime().toString('hex') 12 | dh1.generateKeys() 13 | var dh2 = crypto.getDiffieHellman(mod) 14 | var p2 = dh2.getPrime().toString('hex') 15 | dh2.generateKeys() 16 | t.equals(p1, p2, 'equal primes') 17 | var pubk1 = dh1.getPublicKey() 18 | var pubk2 = dh2.getPublicKey() 19 | t.notEquals(pubk1, pubk2, 'diff public keys') 20 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 21 | var pub2 = dh2.computeSecret(dh1.getPublicKey()).toString('hex') 22 | t.equals(pub1, pub2, 'equal secrets') 23 | }) 24 | }) 25 | }) 26 | 27 | test('diffie-hellman key lengths', function (t) { 28 | [ 29 | 64, 65, 192 30 | ].forEach(function (len) { 31 | t.test('' + len, function (t) { 32 | t.plan(3) 33 | var dh2 = crypto.createDiffieHellman(len) 34 | var prime2 = dh2.getPrime() 35 | var p2 = prime2.toString('hex') 36 | var dh1 = crypto.createDiffieHellman(prime2) 37 | var p1 = dh1.getPrime().toString('hex') 38 | dh1.generateKeys() 39 | dh2.generateKeys() 40 | t.equals(p1, p2, 'equal primes') 41 | var pubk1 = dh1.getPublicKey() 42 | var pubk2 = dh2.getPublicKey() 43 | t.notEquals(pubk1, pubk2, 'diff public keys') 44 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 45 | var pub2 = dh2.computeSecret(dh1.getPublicKey()).toString('hex') 46 | t.equals(pub1, pub2, 'equal secrets') 47 | }) 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /test/ecdh.js: -------------------------------------------------------------------------------- 1 | var mods = [ 2 | 'secp256k1', 3 | 'secp224r1', 4 | 'prime256v1', 5 | 'prime192v1' 6 | ] 7 | var test = require('tape') 8 | var _crypto = require('../') 9 | var createECDH1 = _crypto.createECDH 10 | var createECDH2 = require('create-ecdh/browser') 11 | 12 | mods.forEach(function (mod) { 13 | test('createECDH: ' + mod + ' uncompressed', function (t) { 14 | t.plan(2) 15 | var dh1 = createECDH1(mod) 16 | dh1.generateKeys() 17 | var dh2 = createECDH2(mod) 18 | dh2.generateKeys() 19 | var pubk1 = dh1.getPublicKey() 20 | var pubk2 = dh2.getPublicKey() 21 | t.notEquals(pubk1.toString('hex'), pubk2.toString('hex'), 'diff public keys') 22 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 23 | var pub2 = dh2.computeSecret(pubk1).toString('hex') 24 | t.equals(pub1, pub2, 'equal secrets') 25 | }) 26 | 27 | test('createECDH: ' + mod + ' compressed', function (t) { 28 | t.plan(2) 29 | var dh1 = createECDH1(mod) 30 | dh1.generateKeys() 31 | var dh2 = createECDH2(mod) 32 | dh2.generateKeys() 33 | var pubk1 = dh1.getPublicKey(null, 'compressed') 34 | var pubk2 = dh2.getPublicKey(null, 'compressed') 35 | t.notEquals(pubk1.toString('hex'), pubk2.toString('hex'), 'diff public keys') 36 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 37 | var pub2 = dh2.computeSecret(pubk1).toString('hex') 38 | t.equals(pub1, pub2, 'equal secrets') 39 | }) 40 | 41 | test('createECDH: ' + mod + ' set stuff', function (t) { 42 | t.plan(5) 43 | var dh1 = createECDH1(mod) 44 | var dh2 = createECDH2(mod) 45 | dh1.generateKeys() 46 | dh2.generateKeys() 47 | dh1.setPrivateKey(dh2.getPrivateKey()) 48 | dh1.setPublicKey(dh2.getPublicKey()) 49 | var priv1 = dh1.getPrivateKey('hex') 50 | var priv2 = dh2.getPrivateKey('hex') 51 | t.equals(priv1, priv2, 'same private key') 52 | var pubk1 = dh1.getPublicKey() 53 | var pubk2 = dh2.getPublicKey() 54 | t.equals(pubk1.toString('hex'), pubk2.toString('hex'), 'same public keys, uncompressed') 55 | t.equals(dh1.getPublicKey('hex', 'compressed'), dh2.getPublicKey('hex', 'compressed'), 'same public keys compressed') 56 | t.equals(dh1.getPublicKey('hex', 'hybrid'), dh2.getPublicKey('hex', 'hybrid'), 'same public keys hybrid') 57 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 58 | var pub2 = dh2.computeSecret(pubk1).toString('hex') 59 | t.equals(pub1, pub2, 'equal secrets') 60 | }) 61 | }) 62 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 2 | require('./create-hash') 3 | require('./create-hmac') 4 | if (!process.browser) { 5 | require('./dh') 6 | } 7 | 8 | require('./pbkdf2') 9 | try { 10 | require('randombytes')(8) 11 | require('./ecdh') 12 | require('./public-encrypt') 13 | require('./random-bytes') 14 | require('./sign') 15 | } catch (e) { 16 | console.log('no secure rng avaiable') 17 | } 18 | require('./aes') 19 | -------------------------------------------------------------------------------- /test/node/dh.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var cryptoB = require('../../') 3 | var crypto = require('crypto') 4 | 5 | test('diffie-hellman mod groups', function (t) { 6 | [ 7 | 'modp1', 'modp2', 'modp5', 'modp14', 'modp15', 'modp16' 8 | ].forEach(function (mod) { 9 | t.test(mod, function (t) { 10 | t.plan(3) 11 | var dh1 = cryptoB.getDiffieHellman(mod) 12 | var p1 = dh1.getPrime().toString('hex') 13 | dh1.generateKeys() 14 | 15 | var dh2 = crypto.getDiffieHellman(mod) 16 | var p2 = dh2.getPrime().toString('hex') 17 | dh2.generateKeys() 18 | t.equals(p1, p2, 'equal primes') 19 | var pubk1 = dh1.getPublicKey() 20 | var pubk2 = dh2.getPublicKey() 21 | t.notEquals(pubk1, pubk2, 'diff public keys') 22 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 23 | var pub2 = dh2.computeSecret(pubk1).toString('hex') 24 | t.equals(pub1, pub2, 'equal secrets') 25 | }) 26 | }) 27 | }) 28 | 29 | test('diffie-hellman key lengths', function (t) { 30 | [ 31 | 64, 65, 192 32 | ].forEach(function (len) { 33 | t.test('' + len, function (t) { 34 | t.plan(3) 35 | var dh2 = cryptoB.createDiffieHellman(len) 36 | var prime2 = dh2.getPrime() 37 | var p2 = prime2.toString('hex') 38 | var dh1 = crypto.createDiffieHellman(prime2) 39 | var p1 = dh1.getPrime().toString('hex') 40 | dh1.generateKeys() 41 | dh2.generateKeys() 42 | t.equals(p1, p2, 'equal primes') 43 | var pubk1 = dh1.getPublicKey() 44 | var pubk2 = dh2.getPublicKey() 45 | t.notEquals(pubk1, pubk2, 'diff public keys') 46 | var pub1 = dh1.computeSecret(pubk2).toString('hex') 47 | var pub2 = dh2.computeSecret(dh1.getPublicKey()).toString('hex') 48 | t.equals(pub1, pub2, 'equal secrets') 49 | }) 50 | }) 51 | }) 52 | -------------------------------------------------------------------------------- /test/pbkdf2.js: -------------------------------------------------------------------------------- 1 | var tape = require('tape') 2 | var crypto = require('pbkdf2/browser') 3 | 4 | var vectors = require('hash-test-vectors/pbkdf2') 5 | 6 | tape('pbkdf2', function (t) { 7 | vectors.forEach(function (input) { 8 | // skip inputs that will take way too long 9 | if (input.iterations > 10000) return 10 | 11 | var key = crypto.pbkdf2Sync(input.password, input.salt, input.iterations, input.length) 12 | 13 | if (key.toString('hex') !== input.sha1) { 14 | console.log(input) 15 | } 16 | 17 | t.equal(key.toString('hex'), input.sha1) 18 | }) 19 | 20 | t.end() 21 | }) 22 | -------------------------------------------------------------------------------- /test/public-encrypt.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var crypto1 = require('../') 3 | var rsa = { 4 | 'private': '2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949456a77494241414b422f6779376d6a615767506546645659445a5752434139424e69763370506230657332372b464b593068737a4c614f7734374578430a744157704473483438545841667948425977424c67756179666b344c4749757078622b43474d62526f337845703043626659314a62793236543976476a5243310a666f484444554a4738347561526279487161663469367a74346756522b786c4145496a6b614641414b38634f6f58415431435671474c4c6c6a554363684c38500a6a61486a2f7972695a2f53377264776c49334c6e41427877776d4c726d522f7637315774706d4f2f614e47384e2b31706f2b5177616768546b79513539452f5a0a7641754f6b4657486f6b32712f523650594161326a645a397a696d3046714f502b6e6b5161454452624246426d4271547635664647666b32577341664b662f520a47302f5646642b5a654d353235315465547658483639356e6c53476175566c3941674d42414145436766344c725748592f6c35346f7554685a577676627275670a70667a36734a583267396c3779586d576c455773504543566f2f375355627059467074364f5a7939397a53672b494b624771574b6664686f4b725477495674430a4c30595a304e6c6d646e414e53497a30726f785147375a786b4c352b764853772f506d443978345577662b437a38684154436d4e42763171633630646b7975570a34434c71653732716154695657526f4f316961675167684e634c6f6f36765379363545784c614344545068613779753276773468465a705769456a57346478660a7246644c696978353242433836596c416c784d452f724c6738494a5676696c62796f39615764586d784f6155544c527636506b4644312f6756647738563951720a534c4e39466c4b326b6b6a695830647a6f6962765a7733744d6e74337979644178305838372b734d5256616843316270336b56507a3448793045575834514a2f0a504d33317647697549546b324e43643531445874314c746e324f503546614a536d4361456a6830586b5534716f7559796a585774384275364254436c327675610a466730556a6939432b496b504c6d61554d624d494f7761546b386357714c74685378734c6537304a354f6b477267664b554d2f772b4248483150742f506a7a6a0a432b2b6c306b6946614f5644566141563947704c504c43426f4b2f50433952622f72784d4d6f43434e774a2f4e5a756564496e793277334c4d69693737682f540a7a53766572674e47686a5936526e7661386c4c584a36646c726b6350417970733367577778716a344e5230542b474d3062445550564c62374d303758563753580a7637564a476d35324a625247774d3173732b72385854544e656d65476b2b5752784737546774734d715947584c66423851786b2f66352f4d63633030546c38750a7758464e7366784a786d7436416273547233673336774a2f49684f6e69627a3941642b6e63686c426e4e3351655733434b48717a61523138766f717674566d320a6b4a66484b31357072482f7353476d786d6945476772434a545a78744462614e434f372f56426a6e4b756455554968434177734c747571302f7a7562397641640a384731736366497076357161534e7a6d4b6f5838624f77417276725336775037794b726354737557496c484438724a5649374945446e516f5470354738664b310a68774a2f4d4968384d35763072356455594576366f494a5747636c65364148314a6d73503557496166677137325a32323838704863434648774e59384467394a0a3736517377564c6e556850546c6d6d33454f4f50474574616d32694144357230416679746c62346c624e6f51736a32737a65584f4e4458422b366f7565616a680a564e454c55723848635350356c677a525a6a4a57366146497a6a394c44526d516e55414f6a475358564f517445774a2f4d43515a374e2f763464494b654452410a3864385545785a332b674748756d7a697a7447524a30745172795a483250616b50354937562b316c377145556e4a3263336d462b65317634314570394c4376680a627a72504b773964786831386734622b37624d707357506e7372614b6836697078633761614f615a5630447867657a347a635a753050316f6c4f30634e334b4d0a6e784a305064733352386241684e43446453324a5a61527035513d3d0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a', 5 | 'public': '2d2d2d2d2d424547494e20525341205055424c4943204b45592d2d2d2d2d0a4d49494242674b422f6779376d6a615767506546645659445a5752434139424e69763370506230657332372b464b593068737a4c614f773437457843744157700a4473483438545841667948425977424c67756179666b344c4749757078622b43474d62526f337845703043626659314a62793236543976476a524331666f48440a44554a4738347561526279487161663469367a74346756522b786c4145496a6b614641414b38634f6f58415431435671474c4c6c6a554363684c38506a61486a0a2f7972695a2f53377264776c49334c6e41427877776d4c726d522f7637315774706d4f2f614e47384e2b31706f2b5177616768546b79513539452f5a7641754f0a6b4657486f6b32712f523650594161326a645a397a696d3046714f502b6e6b5161454452624246426d4271547635664647666b32577341664b662f5247302f560a46642b5a654d353235315465547658483639356e6c53476175566c3941674d424141453d0a2d2d2d2d2d454e4420525341205055424c4943204b45592d2d2d2d2d0a' 6 | } 7 | var crypto2 = require('public-encrypt/browser') 8 | rsa.private = new Buffer(rsa.private, 'hex') 9 | rsa.public = new Buffer(rsa.public, 'hex') 10 | var encrypted = '0bcd6462ad7a563be2d42b0b73e0b0a163886304e7723b025f97605144fe1781e84acdc4031327d6bccd67fe13183e8fbdc8c5fe947b49d011ce3ebb08b11e83b87a77328ca57ee77cfdc78743b0749366643d7a21b2abcd4aa32dee9832938445540ee3007b7a70191c8dc9ff2ad76fe8dfaa5362d9d2c4b31a67b816d7b7970a293cb95bf3437a301bedb9f431b7075aa2f9df77b4385bea2a37982beda467260b384a58258b5eb4e36a0e0bf7dff83589636f5f97bf542084f0f76868c9f3f989a27fee5b8cd2bfee0bae1eae958df7c3184e5a40fda101196214f371606feca4330b221f30577804bbd4f61578a84e85dcd298849f509e630d275280' 11 | 12 | test('publicEncrypt/privateDecrypt', function (t) { 13 | t.test('can decrypt', function (t) { 14 | t.plan(2) 15 | // note encryption is ranomized so can't test to see if they encrypt the same 16 | t.equals(crypto1.privateDecrypt(rsa.private, new Buffer(encrypted, 'hex')).toString(), 'hello there I am a nice message', 'decrypt it properly') 17 | t.equals(crypto2.privateDecrypt(rsa.private, new Buffer(encrypted, 'hex')).toString(), 'hello there I am a nice message', 'decrypt it properly') 18 | }) 19 | t.test('can round trip', function (t) { 20 | t.plan(2) 21 | var msg = 'this is a message' 22 | // note encryption is ranomized so can't test to see if they encrypt the same 23 | t.equals(crypto1.privateDecrypt(rsa.private, crypto2.publicEncrypt(rsa.public, new Buffer(msg))).toString(), msg, 'round trip it') 24 | t.equals(crypto2.privateDecrypt(rsa.private, crypto1.publicEncrypt(rsa.public, new Buffer(msg))).toString(), msg, 'round trip it') 25 | }) 26 | }) 27 | 28 | test('privateEncrypt/publicDecrypt', function (t) { 29 | t.test('can round trip', function (t) { 30 | t.plan(2) 31 | var msg = 'this is a message' 32 | // note encryption is ranomized so can't test to see if they encrypt the same 33 | t.equals(crypto1.publicDecrypt(rsa.public, crypto2.privateEncrypt(rsa.private, new Buffer(msg))).toString(), msg, 'round trip it') 34 | t.equals(crypto2.publicDecrypt(rsa.public, crypto1.privateEncrypt(rsa.private, new Buffer(msg))).toString(), msg, 'round trip it') 35 | }) 36 | }) 37 | -------------------------------------------------------------------------------- /test/random-bytes.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var crypto = require('../') 3 | 4 | var randomBytesFunctions = { 5 | randomBytes: require('randombytes'), 6 | pseudoRandomBytes: crypto.pseudoRandomBytes 7 | } 8 | 9 | for (var randomBytesName in randomBytesFunctions) { 10 | // Both randomBytes and pseudoRandomBytes should provide the same interface 11 | var randomBytes = randomBytesFunctions[randomBytesName] 12 | 13 | test('get error message', function (t) { 14 | try { 15 | var b = randomBytes(10) 16 | t.ok(Buffer.isBuffer(b)) 17 | t.end() 18 | } catch (err) { 19 | t.ok(/not supported/.test(err.message), '"not supported" is in error message') 20 | t.end() 21 | } 22 | }) 23 | 24 | test(randomBytesName, function (t) { 25 | t.plan(5) 26 | t.equal(randomBytes(10).length, 10) 27 | t.ok(Buffer.isBuffer(randomBytes(10))) 28 | randomBytes(10, function (ex, bytes) { 29 | t.error(ex) 30 | t.equal(bytes.length, 10) 31 | t.ok(Buffer.isBuffer(bytes)) 32 | t.end() 33 | }) 34 | }) 35 | 36 | test(randomBytesName + ' seem random', function (t) { 37 | var L = 1000 38 | var b = randomBytes(L) 39 | 40 | var mean = [].reduce.call(b, function (a, b) { return a + b }, 0) / L 41 | 42 | // test that the random numbers are plausably random. 43 | // Math.random() will pass this, but this will catch 44 | // terrible mistakes such as this blunder: 45 | // https://github.com/dominictarr/crypto-browserify/commit/3267955e1df7edd1680e52aeede9a89506ed2464#commitcomment-7916835 46 | 47 | // this doesn't check that the bytes are in a random *order* 48 | // but it's better than nothing. 49 | 50 | var expected = 256 / 2 51 | var smean = Math.sqrt(mean) 52 | 53 | // console.log doesn't work right on testling, *grumble grumble* 54 | console.log(JSON.stringify([expected - smean, mean, expected + smean])) 55 | t.ok(mean < expected + smean) 56 | t.ok(mean > expected - smean) 57 | 58 | t.end() 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /test/random-fill.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var crypto = require('../') 3 | var Buffer = require('safe-buffer').Buffer 4 | 5 | test('get error message', function (t) { 6 | try { 7 | var b = crypto.randomFillSync(Buffer.alloc(10)) 8 | t.ok(Buffer.isBuffer(b)) 9 | t.end() 10 | } catch (err) { 11 | t.ok(/not supported/.test(err.message), '"not supported" is in error message') 12 | t.end() 13 | } 14 | }) 15 | 16 | test('randomfill', function (t) { 17 | t.plan(5) 18 | t.equal(crypto.randomFillSync(Buffer.alloc(10)).length, 10) 19 | t.ok(Buffer.isBuffer(crypto.randomFillSync(Buffer.alloc(10)))) 20 | crypto.randomFill(Buffer.alloc(10), function (ex, bytes) { 21 | t.error(ex) 22 | t.equal(bytes.length, 10) 23 | t.ok(Buffer.isBuffer(bytes)) 24 | t.end() 25 | }) 26 | }) 27 | 28 | test('seems random', function (t) { 29 | var L = 1000 30 | var b = crypto.randomFillSync(Buffer.alloc(L)) 31 | 32 | var mean = [].reduce.call(b, function (a, b) { 33 | return a + b 34 | }, 0) / L 35 | 36 | // test that the random numbers are plausably random. 37 | // Math.random() will pass this, but this will catch 38 | // terrible mistakes such as this blunder: 39 | // https://github.com/dominictarr/crypto-browserify/commit/3267955e1df7edd1680e52aeede9a89506ed2464#commitcomment-7916835 40 | 41 | // this doesn't check that the bytes are in a random *order* 42 | // but it's better than nothing. 43 | 44 | var expected = 256 / 2 45 | var smean = Math.sqrt(mean) 46 | 47 | // console.log doesn't work right on testling, *grumble grumble* 48 | console.log(JSON.stringify([expected - smean, mean, expected + smean])) 49 | t.ok(mean < expected + smean) 50 | t.ok(mean > expected - smean) 51 | 52 | t.end() 53 | }) 54 | -------------------------------------------------------------------------------- /test/sign.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var nodeCrypto = require('../') 3 | var ourCrypto = require('browserify-sign/browser') 4 | 5 | var rsa = { 6 | 'private': '2d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949456a77494241414b422f6779376d6a615767506546645659445a5752434139424e69763370506230657332372b464b593068737a4c614f7734374578430a744157704473483438545841667948425977424c67756179666b344c4749757078622b43474d62526f337845703043626659314a62793236543976476a5243310a666f484444554a4738347561526279487161663469367a74346756522b786c4145496a6b614641414b38634f6f58415431435671474c4c6c6a554363684c38500a6a61486a2f7972695a2f53377264776c49334c6e41427877776d4c726d522f7637315774706d4f2f614e47384e2b31706f2b5177616768546b79513539452f5a0a7641754f6b4657486f6b32712f523650594161326a645a397a696d3046714f502b6e6b5161454452624246426d4271547635664647666b32577341664b662f520a47302f5646642b5a654d353235315465547658483639356e6c53476175566c3941674d42414145436766344c725748592f6c35346f7554685a577676627275670a70667a36734a583267396c3779586d576c455773504543566f2f375355627059467074364f5a7939397a53672b494b624771574b6664686f4b725477495674430a4c30595a304e6c6d646e414e53497a30726f785147375a786b4c352b764853772f506d443978345577662b437a38684154436d4e42763171633630646b7975570a34434c71653732716154695657526f4f316961675167684e634c6f6f36765379363545784c614344545068613779753276773468465a705769456a57346478660a7246644c696978353242433836596c416c784d452f724c6738494a5676696c62796f39615764586d784f6155544c527636506b4644312f6756647738563951720a534c4e39466c4b326b6b6a695830647a6f6962765a7733744d6e74337979644178305838372b734d5256616843316270336b56507a3448793045575834514a2f0a504d33317647697549546b324e43643531445874314c746e324f503546614a536d4361456a6830586b5534716f7559796a585774384275364254436c327675610a466730556a6939432b496b504c6d61554d624d494f7761546b386357714c74685378734c6537304a354f6b477267664b554d2f772b4248483150742f506a7a6a0a432b2b6c306b6946614f5644566141563947704c504c43426f4b2f50433952622f72784d4d6f43434e774a2f4e5a756564496e793277334c4d69693737682f540a7a53766572674e47686a5936526e7661386c4c584a36646c726b6350417970733367577778716a344e5230542b474d3062445550564c62374d303758563753580a7637564a476d35324a625247774d3173732b72385854544e656d65476b2b5752784737546774734d715947584c66423851786b2f66352f4d63633030546c38750a7758464e7366784a786d7436416273547233673336774a2f49684f6e69627a3941642b6e63686c426e4e3351655733434b48717a61523138766f717674566d320a6b4a66484b31357072482f7353476d786d6945476772434a545a78744462614e434f372f56426a6e4b756455554968434177734c747571302f7a7562397641640a384731736366497076357161534e7a6d4b6f5838624f77417276725336775037794b726354737557496c484438724a5649374945446e516f5470354738664b310a68774a2f4d4968384d35763072356455594576366f494a5747636c65364148314a6d73503557496166677137325a32323838704863434648774e59384467394a0a3736517377564c6e556850546c6d6d33454f4f50474574616d32694144357230416679746c62346c624e6f51736a32737a65584f4e4458422b366f7565616a680a564e454c55723848635350356c677a525a6a4a57366146497a6a394c44526d516e55414f6a475358564f517445774a2f4d43515a374e2f763464494b654452410a3864385545785a332b674748756d7a697a7447524a30745172795a483250616b50354937562b316c377145556e4a3263336d462b65317634314570394c4376680a627a72504b773964786831386734622b37624d707357506e7372614b6836697078633761614f615a5630447867657a347a635a753050316f6c4f30634e334b4d0a6e784a305064733352386241684e43446453324a5a61527035513d3d0a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a', 7 | 'public': '2d2d2d2d2d424547494e20525341205055424c4943204b45592d2d2d2d2d0a4d49494242674b422f6779376d6a615767506546645659445a5752434139424e69763370506230657332372b464b593068737a4c614f773437457843744157700a4473483438545841667948425977424c67756179666b344c4749757078622b43474d62526f337845703043626659314a62793236543976476a524331666f48440a44554a4738347561526279487161663469367a74346756522b786c4145496a6b614641414b38634f6f58415431435671474c4c6c6a554363684c38506a61486a0a2f7972695a2f53377264776c49334c6e41427877776d4c726d522f7637315774706d4f2f614e47384e2b31706f2b5177616768546b79513539452f5a7641754f0a6b4657486f6b32712f523650594161326a645a397a696d3046714f502b6e6b5161454452624246426d4271547635664647666b32577341664b662f5247302f560a46642b5a654d353235315465547658483639356e6c53476175566c3941674d424141453d0a2d2d2d2d2d454e4420525341205055424c4943204b45592d2d2d2d2d0a' 8 | } 9 | 10 | var ec = { 11 | 'private': '2d2d2d2d2d424547494e2045432050524956415445204b45592d2d2d2d2d0a4d485143415145454944463658763853762f2f77475557442b6337383070704772553051645a5743417a78415150515838722f756f416347425375424241414b0a6f55514451674145495a656f7744796c6c73344b2f7766426a4f313862596f37674778386e595152696a6134652f71454d696b4f484a616937676565557265550a7235586b792f4178377332644774656773504e7350674765354d705176673d3d0a2d2d2d2d2d454e442045432050524956415445204b45592d2d2d2d2d0a', 12 | 'public': '2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d465977454159484b6f5a497a6a3043415159464b34454541416f4451674145495a656f7744796c6c73344b2f7766426a4f313862596f37674778386e5951520a696a6134652f71454d696b4f484a616937676565557265557235586b792f4178377332644774656773504e7350674765354d705176673d3d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a' 13 | } 14 | 15 | rsa.private = new Buffer(rsa.private, 'hex') 16 | rsa.public = new Buffer(rsa.public, 'hex') 17 | ec.private = new Buffer(ec.private, 'hex') 18 | ec.public = new Buffer(ec.public, 'hex') 19 | 20 | function testit (keys, message, scheme) { 21 | var pub = keys.public 22 | var priv = keys.private 23 | test(message.toString(), function (t) { 24 | t.test('js sign and verify', function (t) { 25 | t.plan(t) 26 | var mySign = ourCrypto.createSign(scheme) 27 | var mySig = mySign.update(message).sign(priv) 28 | var myVer = ourCrypto.createVerify(scheme) 29 | t.ok(myVer.update(message).verify(pub, mySig), 'validates') 30 | }) 31 | 32 | t.test('node sign and verify', function (t) { 33 | t.plan(t) 34 | var mySign = nodeCrypto.createSign(scheme) 35 | var mySig = mySign.update(message).sign(priv) 36 | var myVer = nodeCrypto.createVerify(scheme) 37 | t.ok(myVer.update(message).verify(pub, mySig), 'validates') 38 | }) 39 | 40 | t.test('node sign and js verify', function (t) { 41 | t.plan(t) 42 | var mySign = nodeCrypto.createSign(scheme) 43 | var mySig = mySign.update(message).sign(priv) 44 | var myVer = ourCrypto.createVerify(scheme) 45 | t.ok(myVer.update(message).verify(pub, mySig), 'validates') 46 | }) 47 | 48 | t.test('js sign and node verify', function (t) { 49 | t.plan(t) 50 | var mySign = ourCrypto.createSign(scheme) 51 | var mySig = mySign.update(message).sign(priv) 52 | var myVer = nodeCrypto.createVerify(scheme) 53 | t.ok(myVer.update(message).verify(pub, mySig), 'validates') 54 | }) 55 | }) 56 | } 57 | 58 | testit(rsa, new Buffer('rsa with sha256'), 'RSA-SHA256') 59 | testit(ec, new Buffer('ec with sha1'), 'ecdsa-with-SHA1') 60 | --------------------------------------------------------------------------------