mirror of
https://github.com/fluencelabs/js-libp2p-crypto
synced 2025-03-15 06:31:01 +00:00
inital commit
This commit is contained in:
commit
37edb7d0e4
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
**/node_modules/
|
||||||
|
**/*.log
|
||||||
|
test/repo-tests*
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
build
|
||||||
|
|
||||||
|
# Dependency directory
|
||||||
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
lib
|
||||||
|
dist
|
34
.npmignore
Normal file
34
.npmignore
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
**/node_modules/
|
||||||
|
**/*.log
|
||||||
|
test/repo-tests*
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
build
|
||||||
|
|
||||||
|
# Dependency directory
|
||||||
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
test
|
34
.travis.yml
Normal file
34
.travis.yml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
sudo: false
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 4
|
||||||
|
- 5
|
||||||
|
- stable
|
||||||
|
|
||||||
|
# Make sure we have new NPM.
|
||||||
|
before_install:
|
||||||
|
- npm install -g npm
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm run lint
|
||||||
|
- npm test
|
||||||
|
- npm run coverage
|
||||||
|
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- export DISPLAY=:99.0
|
||||||
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- npm run coverage-publish
|
||||||
|
|
||||||
|
env:
|
||||||
|
- CXX=g++-4.8
|
||||||
|
|
||||||
|
addons:
|
||||||
|
firefox: 'latest'
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.8
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2016 Friedel Ziegelmayer
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# JavaScript libp2p Crytpo
|
||||||
|
|
||||||
|
[](http://ipn.io)
|
||||||
|
[](http://ipfs.io/)
|
||||||
|
[](http://webchat.freenode.net/?channels=%23ipfs)
|
||||||
|
[](https://coveralls.io/github/ipfs/js-libp2p-crypto?branch=master)
|
||||||
|
[](https://travis-ci.org/ipfs/js-libp2p-crypto)
|
||||||
|
[](https://circleci.com/gh/ipfs/js-libp2p-crypto)
|
||||||
|
[](https://david-dm.org/ipfs/js-libp2p-crypto) [](https://github.com/feross/standard)
|
||||||
|
|
||||||
|
> Crypto primitives for libp2p in JavaScript
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This repo contains the JavaScript implementation of the crypto primitives
|
||||||
|
needed for libp2p. This is based on this [go implementation](https://github.com/ipfs/go-libp2p-crypto).
|
||||||
|
|
||||||
|
|
||||||
|
## API
|
12
circle.yml
Normal file
12
circle.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
machine:
|
||||||
|
node:
|
||||||
|
version: stable
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
pre:
|
||||||
|
- google-chrome --version
|
||||||
|
- wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
|
||||||
|
- sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get --only-upgrade install google-chrome-stable
|
||||||
|
- google-chrome --version
|
52
package.json
Normal file
52
package.json
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "js-libp2p-crypto",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Crypto primitives for libp2p",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"jsnext:main": "src/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "aegir-lint",
|
||||||
|
"build": "aegir-build",
|
||||||
|
"test": "aegir-test",
|
||||||
|
"test:node": "aegir-test --env node",
|
||||||
|
"test:browser": "aegir-test --env browser",
|
||||||
|
"release": "aegir-release",
|
||||||
|
"release-minor": "aegir-release --type minor",
|
||||||
|
"release-major": "aegir-release --type major",
|
||||||
|
"coverage": "aegir-coverage",
|
||||||
|
"coverage-publish": "aegir-coverage publish"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"IPFS",
|
||||||
|
"libp2p",
|
||||||
|
"crypto",
|
||||||
|
"rsa"
|
||||||
|
],
|
||||||
|
"author": "Friedel Ziegelmayer <dignifiedqurie@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"aegir": "^3.0.4",
|
||||||
|
"chai": "^3.5.0",
|
||||||
|
"pre-commit": "^1.1.3"
|
||||||
|
},
|
||||||
|
"pre-commit": [
|
||||||
|
"lint",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^4.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/ipfs/js-libp2p-crypto.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/ipfs/js-libp2p-crypto/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/ipfs/js-libp2p-crypto",
|
||||||
|
"dependencies": {
|
||||||
|
"multihashing": "^0.2.1",
|
||||||
|
"node-forge": "^0.6.39",
|
||||||
|
"protocol-buffers": "^3.1.6"
|
||||||
|
}
|
||||||
|
}
|
13
src/crypto.proto
Normal file
13
src/crypto.proto
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
enum KeyType {
|
||||||
|
RSA = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PublicKey {
|
||||||
|
required KeyType Type = 1;
|
||||||
|
required bytes Data = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PrivateKey {
|
||||||
|
required KeyType Type = 1;
|
||||||
|
required bytes Data = 2;
|
||||||
|
}
|
29
src/index.js
Normal file
29
src/index.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const keyGenerators = require('./keys')
|
||||||
|
|
||||||
|
exports.utils = require('./utils')
|
||||||
|
|
||||||
|
// Generates a keypair of the given type and bitsize
|
||||||
|
exports.generateKeyPair = (type, bits) => {
|
||||||
|
let generator = keyGenerators[type.toLowerCase()]
|
||||||
|
if (!generator) {
|
||||||
|
throw new Error('invalid or unsupported key type')
|
||||||
|
}
|
||||||
|
|
||||||
|
return generator(bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates an ephemeral public key and returns a function that will compute
|
||||||
|
// the shared secret key.
|
||||||
|
//
|
||||||
|
// Focuses only on ECDH now, but can be made more general in the future.
|
||||||
|
exports.generateEphemeralKeyPair = (curveName, cb) => {
|
||||||
|
throw new Error('Not implemented')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates a set of keys for each party by stretching the shared key.
|
||||||
|
// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
|
||||||
|
exports.keyStretcher = (cipherType, hashType, secret) => {
|
||||||
|
throw new Error('Not implemented')
|
||||||
|
}
|
5
src/keys/index.js
Normal file
5
src/keys/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
rsa: require('./rsa')
|
||||||
|
}
|
114
src/keys/rsa.js
Normal file
114
src/keys/rsa.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const forge = require('node-forge')
|
||||||
|
const protobuf = require('protocol-buffers')
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const utils = require('../utils')
|
||||||
|
|
||||||
|
const pki = forge.pki
|
||||||
|
const rsa = pki.rsa
|
||||||
|
|
||||||
|
const pbm = protobuf(fs.readFileSync(path.join(__dirname, '../crypto.proto')))
|
||||||
|
|
||||||
|
class RsaPublicKey {
|
||||||
|
constructor (k) {
|
||||||
|
this._key = k
|
||||||
|
}
|
||||||
|
|
||||||
|
verify (data, sig) {
|
||||||
|
const md = forge.md.sha256.create()
|
||||||
|
md.update(data, 'utf8')
|
||||||
|
|
||||||
|
return this._key.verify(md.digest().bytes(), sig)
|
||||||
|
}
|
||||||
|
|
||||||
|
marshal () {
|
||||||
|
return forge.asn1.toDer(pki.privateKeyToAsn1(this._key)).bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
get bytes () {
|
||||||
|
return pbm.PublicKey.encode({
|
||||||
|
Type: pbm.KeyType.RSA,
|
||||||
|
Data: this.marhal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypt (bytes) {
|
||||||
|
return this._key.encrypt(bytes, 'RSAES-PKCS1-V1_5')
|
||||||
|
}
|
||||||
|
|
||||||
|
equals (key) {
|
||||||
|
return this.bytes === key.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
hash () {
|
||||||
|
return utils.keyHash(this.bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RsaPrivateKey {
|
||||||
|
constructor (privKey, pubKey) {
|
||||||
|
this._privateKey = privKey
|
||||||
|
this._publicKey = pubKey
|
||||||
|
}
|
||||||
|
|
||||||
|
genSecret () {
|
||||||
|
return forge.random.getBytesSync(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
sign (message) {
|
||||||
|
const md = forge.md.sha256.create()
|
||||||
|
md.update(message, 'utf8')
|
||||||
|
|
||||||
|
return this._privateKey.sign(md)
|
||||||
|
}
|
||||||
|
|
||||||
|
get public () {
|
||||||
|
return new RsaPublicKey(this._publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
decrypt (bytes) {
|
||||||
|
return this._privateKey.decrypt(bytes, 'RSAES-PKCS1-V1_5')
|
||||||
|
}
|
||||||
|
|
||||||
|
marshal () {
|
||||||
|
return forge.asn1.toDer(pki.privateKeyToAsn1(this._privateKey)).bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
get bytes () {
|
||||||
|
return pbm.PrivateKey.encode({
|
||||||
|
Type: pbm.KeyType.RSA,
|
||||||
|
Data: this.marshal()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
equals (key) {
|
||||||
|
return this.bytes === key.bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
hash () {
|
||||||
|
return utils.keyHash(this.bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalRsaPrivateKey (bytes) {
|
||||||
|
const key = pki.privateKeyFromAsn1(forge.asn1.fromDer(bytes))
|
||||||
|
|
||||||
|
return new RsaPrivateKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
function unmarshalRsaPublicKey (bytes) {
|
||||||
|
const key = pki.publicKeyFromAsn1(forge.asn1.fromDer(bytes))
|
||||||
|
|
||||||
|
return new RsaPublicKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function generateRSAKey (bits, cb) {
|
||||||
|
rsa.generateKeyPair({bits}, (err, keypair) => {
|
||||||
|
if (err) return cb(err)
|
||||||
|
|
||||||
|
cb(null, new RSAKey(keypair.publicKey, keypair.privateKey))
|
||||||
|
})
|
||||||
|
}
|
13
src/utils.js
Normal file
13
src/utils.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const multihashing = require('multihashing')
|
||||||
|
|
||||||
|
// Check the equality of two keys
|
||||||
|
exports.keyEqual = (k1, k2) => {
|
||||||
|
return k1.buffer.equals(k2.buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hashes a key
|
||||||
|
exports.keyHash = (key) => {
|
||||||
|
return multihashing(key.buffer, 'sha2-256')
|
||||||
|
}
|
20
test/index.spec.js
Normal file
20
test/index.spec.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const expect = require('chai').expect
|
||||||
|
|
||||||
|
const crypto = require('../src')
|
||||||
|
|
||||||
|
describe('libp2p-crypto', () => {
|
||||||
|
describe('generateKeyPair', () => {
|
||||||
|
describe('RSA', () => {
|
||||||
|
it('generates a valid key', () => {
|
||||||
|
const key = crypto.generateKeyPair('RSA', 2048)
|
||||||
|
|
||||||
|
expect(key).to.have.property('publicKey')
|
||||||
|
expect(key).to.have.property('privateKey')
|
||||||
|
expect(key).to.have.property('buffer')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user