Skip to content
This repository has been archived by the owner on Feb 25, 2019. It is now read-only.

Commit

Permalink
Merge pull request #3 from anvilresearch/linklater-doc
Browse files Browse the repository at this point in the history
API Documentation
  • Loading branch information
christiansmith authored Aug 24, 2017
2 parents 57e1508 + 5b760d5 commit 03ca310
Show file tree
Hide file tree
Showing 7 changed files with 481 additions and 90 deletions.
20 changes: 4 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ available natively in browsers and [via npm][node-webcrypto] in Node.js.
[jwkset]: https://tools.ietf.org/html/rfc7517#section-5
[w3c-webcrypto]: https://www.w3.org/TR/WebCryptoAPI/
[node-webcrypto]: https://www.npmjs.com/package/@trust/webcrypto
[api-docs]: https://anvilresearch.github.io/jwk


## Table of Contents
Expand Down Expand Up @@ -71,24 +72,11 @@ $ npm run karma // Karma (browser)

## API

### JWK
Full documentation available [here][api-docs].

#### new JWK()
#### (static) importKey()
#### sign()
#### verify()
#### encrypt()
#### decrypt()
### Examples

### JWKSet

#### new JWKSet()
#### (static) generateKeys()
#### (static) importKeys()
#### generateKeys()
#### importKeys()
#### filter()
#### find()
TBD

## Contribute

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"sinon-chai": "^2.12.0"
},
"dependencies": {
"@trust/jwa": "^0.4.3",
"@trust/jwa": "^0.4.5",
"@trust/webcrypto": "^0.4.0",
"node-fetch": "^1.7.2",
"sift": "^5.0.0"
Expand Down
179 changes: 127 additions & 52 deletions src/JWK.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ class JWK {
/**
* constructor
*
* @class
* JSON Web Key
* @class JWK
*
* @description
* JSON Web Key ([IETF RFC7517](https://tools.ietf.org/html/rfc7517))
*
* @param {Object} data
* @param {Object} [options={}] - Additional JWK metadata.
*/
constructor (data, options = {}) {
if (!data) {
Expand All @@ -38,75 +43,110 @@ class JWK {
}
}

// Handle object input
if (data.alg && options.alg && data.alg !== options.alg) {
throw new DataError('Conflicting algorithm option')
// Handle options input
let metadata = Object.keys(options)
.filter(key => {
let dataValue = data[key]
let optionsValue = options[key]

} else if (!data.alg && options.alg) {
data.alg = options.alg

} else if (!data.alg && !options.alg) {
throw new DataError('Valid JWA algorithm required for JWK')
}
if (dataValue && optionsValue && dataValue !== optionsValue) {
throw new DataError(`Conflicting '${key}' option`)
}

// Handle kid transferral
if (data.kid && options.kid && data.kid !== options.kid) {
throw new DataError('Conflicting key identifier option')
return !dataValue && optionsValue
})
.reduce((state, key) => {
state[key] = options[key]
return state
}, {})

} else if (!data.kid && options.kid) {
data.kid = options.kid
// Assign input
Object.assign(this, data, metadata)

} else if (!data.kid && !options.kid) {
throw new DataError('Valid JWA key identifier required for JWK')
// Enforce required properties
if (!this.alg) {
throw new DataError('Valid \'alg\' required for JWK')
}

Object.assign(this, data)
if (!this.kid) {
throw new DataError('Valid \'kid\' required for JWK')
}
}

/**
* importKey
*
* @description
* Import a JWK from JSON String or a JS Object.
*
* @param {(String|Object)} data
* @return {Promise}
* @param {Object} [options] - Additional JWK metadata.
* @return {Promise.<JWK>} A promise that resolves the JWK instance.
*/
static importKey (data, options = {}) {
static importKey (data, options) {
return Promise.resolve()
// Create instance
.then(() => new JWK(data, options))
.then(jwk => {
return JWA.importKey(jwk)
.then(({ cryptoKey }) => {
Object.defineProperty(jwk, 'cryptoKey', {
value: cryptoKey,
enumerable: false,
configurable: false
})

return jwk
})
})

// Import CryptoKey and assign to JWK
.then(jwk => JWA.importKey(jwk).then(({ cryptoKey }) => {
Object.defineProperty(jwk, 'cryptoKey', {
value: cryptoKey,
enumerable: false,
configurable: false
})

return jwk
}))
}

/**
* fromCryptoKey
*
* @param {CryptoKey} key
* @param {Object} [options]
* @return {Promise}
* @description
* Import a JWK from a [WebCrypto CryptoKey](https://github.com/anvilresearch/webcrypto).
*
* @param {CryptoKey} key - [WebCrypto CryptoKey]{@link https://github.com/anvilresearch/webcrypto}.
* @param {Object} [options] - Additional JWK metadata.
* @return {Promise.<JWK>} A promise that resolves the JWK instance.
*/
static fromCryptoKey (key, options) {
// Export JWK
return JWA.exportKey('jwk', key)

// Create JWK instance and assign CryptoKey
.then(data => {
let jwk = new JWK(data, options)
Object.defineProperty(jwk, 'cryptoKey', { value: key, enumerable: false, configurable: false })

Object.defineProperty(jwk, 'cryptoKey', {
value: key,
enumerable: false,
configurable: false
})

return jwk
})
}

/**
* sign
*
* @param {(String|Buffer)} data
* @return {Promise}
* @description
* Sign arbitrary data using the JWK.
*
* @example <caption>Signing the string "test"</caption>
* privateJwk.sign('test')
* .then(console.log)
* //
* // (line breaks for display only)
* //
* // => "MEUCIQCHwnGM8IsOJgfQsoPgs3hMd8
* // ahfWHM9ZNvj1K6i2yhKQIgWGOuXX43
* // lSTo-U8Pa8sURR53lv6Osjw-dtoLse
* // lftqQ"
*
* @param {(String|Buffer)} data - The data to sign.
* @return {Promise.<String>} A promise that resolves the base64url encoded signature string.
*/
sign (data) {
let { alg, cryptoKey } = this
Expand All @@ -116,9 +156,21 @@ class JWK {
/**
* verify
*
* @param {(String|Buffer)} data
* @param {String} signature
* @return {Promise}
* @description
* Verify a signature using the JWK.
*
* @example <caption>Verify a signature of the string "test"</caption>
* // base64url encoded signature string
* let signature = `MEUCIQCHwnGM8IsOJgfQsoPgs3hMd8ahfWHM9ZN
* vj1K6i2yhKQIgWGOuXX43lSTo-U8Pa8sURR53lv6Osjw-dtoLselftqQ`
*
* publicJwk.verify('test', signature)
* .then(console.log)
* // => true
*
* @param {(String|Buffer)} data - The data to verify.
* @param {String} signature - A base64url signature string.
* @return {Promise.<Boolean>} A promise that resolves the boolean result of the signature verification.
*/
verify (data, signature) {
let { alg, cryptoKey } = this
Expand All @@ -128,9 +180,19 @@ class JWK {
/**
* encrypt
*
* @param {(String|Object)} data
* @param {(String|Buffer)} aad - integrity protected data
* @return {Promise}
* @description
* Encrypt arbitrary data using the JWK.
*
* @example <caption>Encrypt the string "data"</caption>
* secretJwk.encrypt('data')
* .then(console.log)
* // => { iv: 'u0l3ttqUFDQ8mcRboHv5Vw',
* // ciphertext: 'yq3K4w',
* // tag: 'fHlZ__uuUnHn0ac-Lnrr-A' }
*
* @param {(String|Object)} data - The data to encrypt.
* @param {(String|Buffer)} [aad] - Additional non-encrypted integrity protected data (AES-GCM).
* @return {Promise.<Object>} A promise that resolves an object containing the base64url encoded `iv`, `ciphertext` and `tag` (AES-GCM).
*/
encrypt (data, aad) {
let { alg, cryptoKey } = this
Expand All @@ -140,15 +202,28 @@ class JWK {
/**
* decrypt
*
* @param {(String|Object)} data
* @param {(String|Buffer)} iv
* @param {(String|Buffer)} tag
* @param {(String|Buffer)} aad
* @return {Promise}
* @description
* Decrypt data using the JWK.
*
* @example <caption>Decrypt encrypted string "test"</caption>
* // base64url encoded data
* let ciphertext = 'yq3K4w'
* let iv = 'u0l3ttqUFDQ8mcRboHv5Vw'
* let tag = 'fHlZ__uuUnHn0ac-Lnrr-A'
*
* secretJwk.decrypt(ciphertext, iv, tag)
* .then(console.log)
* // => "data"
*
* @param {(String|Buffer)} ciphertext - The encrypted data to decrypt.
* @param {(String|Buffer)} iv - The initialization vector.
* @param {(String|Buffer)} [tag] - The authorization tag (AES-GCM).
* @param {(String|Buffer)} [aad] - Additional non-encrypted integrity protected data (AES-GCM).
* @return {Promise.<String>} A promise that resolves the plaintext data.
*/
decrypt (data, iv, tag, aad) {
decrypt (ciphertext, iv, tag, aad) {
let { alg, cryptoKey } = this
return JWA.decrypt(alg, cryptoKey, data, iv, tag, aad)
return JWA.decrypt(alg, cryptoKey, ciphertext, iv, tag, aad)
}
}

Expand Down
Loading

0 comments on commit 03ca310

Please sign in to comment.