Skip to content
This repository has been archived by the owner on Jul 21, 2023. It is now read-only.

Commit

Permalink
fix: replace node buffers with uint8arrays (#180)
Browse files Browse the repository at this point in the history
* fix: replace node buffers with uint8arrays

All usage of node buffers have been replaced with uint8arrays.

BREAKING CHANGES:

- Where node Buffers were returned, now Uint8Arrays are

* chore: remove commented code
  • Loading branch information
achingbrain authored Aug 7, 2020
1 parent 8b3dc56 commit a0f387a
Show file tree
Hide file tree
Showing 35 changed files with 344 additions and 349 deletions.
97 changes: 50 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ This repo contains the JavaScript implementation of the crypto primitives needed
## Table of Contents

- [js-libp2p-crypto](#js-libp2p-crypto)
- [Lead Maintainer](#Lead-Maintainer)
- [Table of Contents](#Table-of-Contents)
- [Install](#Install)
- [API](#API)
- [Lead Maintainer](#lead-maintainer)
- [Table of Contents](#table-of-contents)
- [Install](#install)
- [Usage](#usage)
- [Web Crypto API](#web-crypto-api)
- [API](#api)
- [`crypto.aes`](#cryptoaes)
- [`crypto.aes.create(key, iv)`](#cryptoaescreatekey-iv)
- [`decrypt(data)`](#decryptdata)
Expand All @@ -32,18 +34,19 @@ This repo contains the JavaScript implementation of the crypto primitives needed
- [`crypto.hmac.create(hash, secret)`](#cryptohmaccreatehash-secret)
- [`digest(data)`](#digestdata)
- [`crypto.keys`](#cryptokeys)
- [`crypto.keys.generateKeyPair(type, bits)`](#cryptokeysgenerateKeyPairtype-bits)
- [`crypto.keys.generateEphemeralKeyPair(curve)`](#cryptokeysgenerateEphemeralKeyPaircurve)
- [`crypto.keys.keyStretcher(cipherType, hashType, secret)`](#cryptokeyskeyStretchercipherType-hashType-secret)
- [`crypto.keys.marshalPublicKey(key, [type])`](#cryptokeysmarshalPublicKeykey-type)
- [`crypto.keys.unmarshalPublicKey(buf)`](#cryptokeysunmarshalPublicKeybuf)
- [`crypto.keys.marshalPrivateKey(key, [type])`](#cryptokeysmarshalPrivateKeykey-type)
- [`crypto.keys.unmarshalPrivateKey(buf)`](#cryptokeysunmarshalPrivateKeybuf)
- [`crypto.keys.import(pem, password)`](#cryptokeysimportpem-password)
- [`crypto.randomBytes(number)`](#cryptorandomBytesnumber)
- [`crypto.pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keySize-hash)
- [Contribute](#Contribute)
- [License](#License)
- [`crypto.keys.generateKeyPair(type, bits)`](#cryptokeysgeneratekeypairtype-bits)
- [`crypto.keys.generateEphemeralKeyPair(curve)`](#cryptokeysgenerateephemeralkeypaircurve)
- [`crypto.keys.keyStretcher(cipherType, hashType, secret)`](#cryptokeyskeystretcherciphertype-hashtype-secret)
- [`crypto.keys.marshalPublicKey(key, [type])`](#cryptokeysmarshalpublickeykey-type)
- [`crypto.keys.unmarshalPublicKey(buf)`](#cryptokeysunmarshalpublickeybuf)
- [`crypto.keys.marshalPrivateKey(key, [type])`](#cryptokeysmarshalprivatekeykey-type)
- [`crypto.keys.unmarshalPrivateKey(buf)`](#cryptokeysunmarshalprivatekeybuf)
- [`crypto.keys.import(encryptedKey, password)`](#cryptokeysimportencryptedkey-password)
- [`privateKey.export(password, format)`](#privatekeyexportpassword-format)
- [`crypto.randomBytes(number)`](#cryptorandombytesnumber)
- [`crypto.pbkdf2(password, salt, iterations, keySize, hash)`](#cryptopbkdf2password-salt-iterations-keysize-hash)
- [Contribute](#contribute)
- [License](#license)

## Install

Expand Down Expand Up @@ -82,49 +85,49 @@ This uses `CTR` mode.

#### `crypto.aes.create(key, iv)`

- `key: Buffer` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used.
- `iv: Buffer` Must have length `16`.
- `key: Uint8Array` The key, if length `16` then `AES 128` is used. For length `32`, `AES 256` is used.
- `iv: Uint8Array` Must have length `16`.

Returns `Promise<{decrypt<Function>, encrypt<Function>}>`

##### `decrypt(data)`

- `data: Buffer`
- `data: Uint8Array`

Returns `Promise<Buffer>`
Returns `Promise<Uint8Array>`

##### `encrypt(data)`

- `data: Buffer`
- `data: Uint8Array`

Returns `Promise<Buffer>`
Returns `Promise<Uint8Array>`

```js
const crypto = require('libp2p-crypto')

// Setting up Key and IV

// A 16 bytes array, 128 Bits, AES-128 is chosen
const key128 = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
const key128 = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])

// A 16 bytes array, 128 Bits,
const IV = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])
const IV = Uint8Array.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15])

async function main () {
const decryptedMessage = 'Hello, world!'

// Encrypting
const cipher = await crypto.aes.create(key128, IV)
const encryptedBuffer = await cipher.encrypt(Buffer.from(decryptedMessage))
const encryptedBuffer = await cipher.encrypt(Uint8Array.from(decryptedMessage))
console.log(encryptedBuffer)
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
// prints: <Uint8Array 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>

// Decrypting
const decipher = await crypto.aes.create(key128, IV)
const decryptedBuffer = await cipher.decrypt(encryptedBuffer)

console.log(decryptedBuffer)
// prints: <Buffer 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>
// prints: <Uint8Array 42 f1 67 d9 2e 42 d0 32 9e b1 f8 3c>

console.log(decryptedBuffer.toString('utf-8'))
// prints: Hello, world!
Expand All @@ -140,15 +143,15 @@ Exposes an interface to the Keyed-Hash Message Authentication Code (HMAC) as def
#### `crypto.hmac.create(hash, secret)`

- `hash: String`
- `secret: Buffer`
- `secret: Uint8Array`

Returns `Promise<{digest<Function>}>`

##### `digest(data)`

- `data: Buffer`
- `data: Uint8Array`

Returns `Promise<Buffer>`
Returns `Promise<Uint8Array>`

Example:

Expand All @@ -157,8 +160,8 @@ const crypto = require('libp2p-crypto')

async function main () {
const hash = 'SHA1' // 'SHA256' || 'SHA512'
const hmac = await crypto.hmac.create(hash, Buffer.from('secret'))
const sig = await hmac.digest(Buffer.from('hello world'))
const hmac = await crypto.hmac.create(hash, uint8ArrayFromString('secret'))
const sig = await hmac.digest(uint8ArrayFromString('hello world'))
console.log(sig)
}

Expand All @@ -178,7 +181,7 @@ Currently the `'RSA'`, `'ed25519'`, and `secp256k1` types are supported, althoug
- `type: String`, see [Supported Key Types](#supported-key-types) above.
- `bits: Number` Minimum of 1024

Returns `Promise<{privateKey<Buffer>, publicKey<Buffer>}>`
Returns `Promise<{privateKey<Uint8Array>, publicKey<Uint8Array>}>`

Generates a keypair of the given type and bitsize.

Expand All @@ -196,7 +199,7 @@ Resolves to an object of the form:

```js
{
key: Buffer,
key: Uint8Array,
genSharedKey: Function
}
```
Expand All @@ -205,7 +208,7 @@ Resolves to an object of the form:

- `cipherType: String`, one of `'AES-128'`, `'AES-256'`, `'Blowfish'`
- `hashType: String`, one of `'SHA1'`, `SHA256`, `SHA512`
- `secret: Buffer`
- `secret: Uint8Array`

Returns `Promise`

Expand All @@ -216,14 +219,14 @@ Resolves to an object of the form:
```js
{
k1: {
iv: Buffer,
cipherKey: Buffer,
macKey: Buffer
iv: Uint8Array,
cipherKey: Uint8Array,
macKey: Uint8Array
},
k2: {
iv: Buffer,
cipherKey: Buffer,
macKey: Buffer
iv: Uint8Array,
cipherKey: Uint8Array,
macKey: Uint8Array
}
}
```
Expand All @@ -233,13 +236,13 @@ Resolves to an object of the form:
- `key: keys.rsa.RsaPublicKey | keys.ed25519.Ed25519PublicKey | keys.secp256k1.Secp256k1PublicKey`
- `type: String`, see [Supported Key Types](#supported-key-types) above. Defaults to 'rsa'.

Returns `Buffer`
Returns `Uint8Array`

Converts a public key object into a protobuf serialized public key.

### `crypto.keys.unmarshalPublicKey(buf)`

- `buf: Buffer`
- `buf: Uint8Array`

Returns `RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey`

Expand All @@ -250,13 +253,13 @@ Converts a protobuf serialized public key into its representative object.
- `key: keys.rsa.RsaPrivateKey | keys.ed25519.Ed25519PrivateKey | keys.secp256k1.Secp256k1PrivateKey`
- `type: String`, see [Supported Key Types](#supported-key-types) above.

Returns `Buffer`
Returns `Uint8Array`

Converts a private key object into a protobuf serialized private key.

### `crypto.keys.unmarshalPrivateKey(buf)`

- `buf: Buffer`
- `buf: Uint8Array`

Returns `Promise<RsaPrivateKey|Ed25519PrivateKey|Secp256k1PrivateKey>`

Expand Down Expand Up @@ -284,9 +287,9 @@ Exports the password protected `PrivateKey`. RSA keys will be exported as passwo

- `number: Number`

Returns `Buffer`
Returns `Uint8Array`

Generates a Buffer with length `number` populated by random bytes.
Generates a Uint8Array with length `number` populated by random bytes.

### `crypto.pbkdf2(password, salt, iterations, keySize, hash)`

Expand Down
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,18 @@
],
"license": "MIT",
"dependencies": {
"buffer": "^5.5.0",
"err-code": "^2.0.0",
"is-typedarray": "^1.0.0",
"iso-random-stream": "^1.1.0",
"keypair": "^1.0.1",
"multibase": "^1.0.1",
"multicodec": "^1.0.4",
"multihashing-async": "^0.8.1",
"multibase": "^3.0.0",
"multicodec": "^2.0.0",
"multihashing-async": "^2.0.1",
"node-forge": "^0.9.1",
"pem-jwk": "^2.0.0",
"protons": "^1.2.1",
"protons": "^2.0.0",
"secp256k1": "^4.0.0",
"uint8arrays": "^1.0.0",
"uint8arrays": "^1.1.0",
"ursa-optional": "^0.10.1"
},
"devDependencies": {
Expand Down
20 changes: 11 additions & 9 deletions src/aes/ciphers-browser.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
'use strict'
const { Buffer } = require('buffer')

require('node-forge/lib/aes')
const forge = require('node-forge/lib/forge')
const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayFromString = require('uint8arrays/from-string')

module.exports = {
createCipheriv: (mode, key, iv) => {
const cipher2 = forge.cipher.createCipher('AES-CTR', key.toString('binary'))
cipher2.start({ iv: iv.toString('binary') })
const cipher2 = forge.cipher.createCipher('AES-CTR', uint8ArrayToString(key, 'ascii'))
cipher2.start({ iv: uint8ArrayToString(iv, 'ascii') })
return {
update: (data) => {
cipher2.update(forge.util.createBuffer(data.toString('binary')))
return Buffer.from(cipher2.output.getBytes(), 'binary')
cipher2.update(forge.util.createBuffer(uint8ArrayToString(data, 'ascii')))
return uint8ArrayFromString(cipher2.output.getBytes(), 'ascii')
}
}
},
createDecipheriv: (mode, key, iv) => {
const cipher2 = forge.cipher.createDecipher('AES-CTR', key.toString('binary'))
cipher2.start({ iv: iv.toString('binary') })
const cipher2 = forge.cipher.createDecipher('AES-CTR', uint8ArrayToString(key, 'ascii'))
cipher2.start({ iv: uint8ArrayToString(iv, 'ascii') })
return {
update: (data) => {
cipher2.update(forge.util.createBuffer(data.toString('binary')))
return Buffer.from(cipher2.output.getBytes(), 'binary')
cipher2.update(forge.util.createBuffer(uint8ArrayToString(data, 'ascii')))
return uint8ArrayFromString(cipher2.output.getBytes(), 'ascii')
}
}
}
Expand Down
Loading

0 comments on commit a0f387a

Please sign in to comment.