Skip to content

Commit

Permalink
feat(Crypto): Implement asymmetric encoding/decoding using `tweennac…
Browse files Browse the repository at this point in the history
…l` and `Ed25519` keypair (#466)

* feat(Add nacl box implementtation): ]

* feat(Crypto): Implement asymetric encoding/decoding using tweennacl and Ed25519 keypair

Converts a 32-byte Ed25519 public key into a 32-byte Curve25519 public key.Converts a 64-byte
Ed25519 secret key (or just the first 32-byte part of it, which is the secret value) into a 32-byte
Curve25519 secret key

#465

* chore(merge): Fix conflict
  • Loading branch information
nduchak committed Nov 7, 2019
1 parent 1994e9d commit 62b54b1
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 1 deletion.
54 changes: 53 additions & 1 deletion es/utils/crypto.js
Expand Up @@ -24,10 +24,12 @@
import bs58check from 'bs58check'
import * as RLP from 'rlp'
import { blake2b } from 'blakejs'
import ed2curve from 'ed2curve'
import nacl from 'tweetnacl'
import aesjs from 'aes-js'
import { leftPad, rightPad, toBytes } from './bytes'
import shajs from 'sha.js'

import { leftPad, rightPad, toBytes } from './bytes'
import { decode as decodeNode } from '../tx/builder/helpers'

const Ecb = aesjs.ModeOfOperation.ecb
Expand Down Expand Up @@ -659,3 +661,53 @@ export function deserialize (binary, opts = { prettyTags: false }) {
})
}
}

/**
* This function encrypts a message using base58check encoded and 'ak' prefixed
* publicKey such that only the corresponding secretKey will
* be able to decrypt
* @rtype (msg: String, publicKey: String) => Object
* @param {Buffer} msg - Data to encode
* @param {String} publicKey - Public key
* @return {Object}
*/
export function encryptData (msg, publicKey) {
const ephemeralKeyPair = nacl.box.keyPair()
const pubKeyUInt8Array = decodeBase58Check(assertedType(publicKey, 'ak'))
const nonce = nacl.randomBytes(nacl.box.nonceLength)

const encryptedMessage = nacl.box(
Buffer.from(msg),
nonce,
ed2curve.convertPublicKey(pubKeyUInt8Array),
ephemeralKeyPair.secretKey
)

return {
ciphertext: Buffer.from(encryptedMessage).toString('hex'),
ephemPubKey: Buffer.from(ephemeralKeyPair.publicKey).toString('hex'),
nonce: Buffer.from(nonce).toString('hex'),
version: 'x25519-xsalsa20-poly1305'
}
}

/**
* This function decrypt a message using secret key
* @rtype (secretKey: String, encryptedData: Object) => Buffer|null
* @param {String} secretKey - Secret key
* @param {Object} encryptedData - Encrypted data
* @return {Buffer|null}
*/
export function decryptData (secretKey, encryptedData) {
const receiverSecretKeyUint8Array = ed2curve.convertSecretKey(Buffer.from(secretKey, 'hex'))
const nonce = Buffer.from(encryptedData.nonce, 'hex')
const ciphertext = Buffer.from(encryptedData.ciphertext, 'hex')
const ephemPubKey = Buffer.from(encryptedData.ephemPubKey, 'hex')
const decrypted = nacl.box.open(
ciphertext,
nonce,
ephemPubKey,
receiverSecretKeyUint8Array
)
return decrypted ? Buffer.from(decrypted) : decrypted
}
16 changes: 16 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -38,6 +38,7 @@
"blakejs": "^1.1.0",
"bs58check": "^2.1.1",
"commander": "^4.0.0",
"ed2curve": "^0.2.1",
"joi-browser": "^13.4.0",
"libsodium-wrappers-sumo": "0.7.6",
"ramda": "^0.26.1",
Expand Down
26 changes: 26 additions & 0 deletions test/unit/crypto.js
Expand Up @@ -159,4 +159,30 @@ describe('crypto', () => {
buildTxHash(txRaw).should.be.equal(expectedHash)
buildTxHash(rlpEncodedTx).should.be.equal(expectedHash)
})
describe('Encrypt data using nacl box asymmetric encryption', async () => {
const { publicKey, secretKey } = Crypto.generateKeyPair()
const msgString = 'Test string'
const msgBuffer = Buffer.from(msgString)

it('Encrypt String/Buffer and decrypt', () => {
const encryptedString = Crypto.encryptData(msgString, publicKey)
const encryptedBuffer = Crypto.encryptData(msgBuffer, publicKey)

const decryptedString = Crypto.decryptData(secretKey, encryptedString)
const decryptedBuffer = Crypto.decryptData(secretKey, encryptedBuffer)
Buffer.from(decryptedString).toString().should.be.equal(msgString)
decryptedBuffer.equals(msgBuffer).should.be.equal(true)
})
it('Decrypt with wrong secret', () => {
const keyPair = Crypto.generateKeyPair()

const encryptedString = Crypto.encryptData(msgString, keyPair.publicKey)
const encryptedBuffer = Crypto.encryptData(msgBuffer, keyPair.publicKey)

const decryptedString = Crypto.decryptData(secretKey, encryptedString)
const decryptedBuffer = Crypto.decryptData(secretKey, encryptedBuffer)
const isNull = decryptedBuffer === null && decryptedString === null
isNull.should.be.equal(true)
})
})
})

0 comments on commit 62b54b1

Please sign in to comment.