Comparing version 0.2.0 to 0.3.1
# jose ChangeLog | ||
## 2015-12-01, Version 0.3.0 | ||
### Notable Changes | ||
* **jwa**: | ||
- Added support for the Key Encryption Algorithms RSA1_5, dir, A128KWGCM, | ||
A192KWGCM and A256KWGCM, as specified in the JWA RFC | ||
- The signature algorithms now return and expect buffers instead of | ||
Base64Url-encoded strings | ||
### Known Issues | ||
None | ||
### Commits | ||
* [`dd9c2db`] Added documentation for jwa.unwrapKey | ||
* [`678e50f`] Added documentation for jwa.wrapKey | ||
* [`3b73781`] Added support for A*KWGCM and RSA1_5 algorithms | ||
* [`d26db82`] Direct Encryption can't have a wrong key | ||
* [`bf9ecba`] test the examples from the README | ||
* [`085c87a`] Start work on Key Encryption Algorithms | ||
* [`eb0aa3e`] Recommend usage of new | ||
* [`7084b3a`] Fix README for signatures | ||
* [`8836326`] Signature methods now expect and return buffers | ||
## 2015-09-22, Version 0.2.0 | ||
@@ -70,2 +96,2 @@ | ||
* [`25d6179`] Added Readme | ||
* [`fa00c25`] Initial commit | ||
* [`fa00c25`] Initial commit |
"use strict"; | ||
var signer = require("./signer"); | ||
var content = require("./content"); | ||
var key = require("./key"); | ||
@@ -8,9 +9,9 @@ module.exports = function jwa(alg) { | ||
var signing = alg.match(/^(HS|RS|ES|none)(256|384|512)?$/); | ||
var keyMgmt = alg.match(/[]/); | ||
var keyMgmt = alg.match(/^(RSA1_5|A|dir)(128|192|256)?(GCMKW)?$/); | ||
var contEnc = alg.match(/^A(128|192|256)(CBC|GCM)(-HS(256|384|512))?$/); | ||
if(signing) { | ||
match = signer(signing[1], signing[2]); | ||
} /*else if(keyMgmt) { | ||
}*/ else if(contEnc) { | ||
} else if(keyMgmt) { | ||
match = key(keyMgmt[1], keyMgmt[2], keyMgmt[3]); | ||
} else if(contEnc) { | ||
match = content(contEnc[2], contEnc[1], contEnc[4]); | ||
@@ -17,0 +18,0 @@ } |
@@ -33,12 +33,12 @@ "use strict"; | ||
function normalizeInput(input) { | ||
if(!Buffer.isBuffer(input) && "string" !== typeof input) { | ||
input = JSON.stringify(input); | ||
function verifyBuffer(buf, param) { | ||
if(!Buffer.isBuffer(buf)) { | ||
throw new Error(param + " must be a buffer"); | ||
} | ||
return input; | ||
} | ||
function createNoneSigner() { | ||
return function sign() { | ||
return ""; | ||
return function sign(input) { | ||
verifyBuffer(input, "input"); | ||
return new Buffer(0); | ||
} | ||
@@ -49,3 +49,5 @@ } | ||
return function verify(input, signature) { | ||
return signature === ""; | ||
verifyBuffer(input, "input"); | ||
verifyBuffer(signature, "signature"); | ||
return signature.length === 0; | ||
} | ||
@@ -56,6 +58,6 @@ } | ||
return function sign(input, secret) { | ||
input = normalizeInput(input); | ||
verifyBuffer(input, "input"); | ||
var hmac = crypto.createHmac("SHA" + bits, secret); | ||
hmac.update(input); | ||
return base64url.fromBase64(hmac.digest("base64")); | ||
return hmac.digest(); | ||
} | ||
@@ -67,5 +69,6 @@ } | ||
return function verify(input, signature, secret) { | ||
input = normalizeInput(input); | ||
verifyBuffer(input, "input"); | ||
verifyBuffer(signature, "signature"); | ||
var sig2 = signer(input, secret); | ||
return bufferEqual(Buffer(signature), Buffer(sig2)); | ||
return bufferEqual(signature, sig2); | ||
} | ||
@@ -76,6 +79,6 @@ } | ||
return function sign(input, key) { | ||
input = normalizeInput(input); | ||
verifyBuffer(input, "input"); | ||
var signer = crypto.createSign("RSA-SHA"+bits); | ||
signer.update(input); | ||
return base64url.fromBase64(signer.sign(key, "base64")); | ||
return signer.sign(key); | ||
} | ||
@@ -86,8 +89,8 @@ } | ||
return function verify(input, signature, key) { | ||
input = normalizeInput(input); | ||
signature = base64url.toBase64(signature); | ||
verifyBuffer(input, "input"); | ||
verifyBuffer(signature, "signature"); | ||
var verifier = crypto.createVerify("RSA-SHA"+bits); | ||
verifier.update(input); | ||
return verifier.verify(key, signature, "base64"); | ||
return verifier.verify(key, signature); | ||
} | ||
@@ -98,3 +101,4 @@ } | ||
return function sign(input, key) { | ||
input = normalizeInput(input); | ||
verifyBuffer(input); | ||
var signer = crypto.createSign("RSA-SHA"+bits); // openssl only signs with ec with sha2 when specifying rsa and using an ec key | ||
@@ -109,4 +113,3 @@ signer.update(input); | ||
var signature = Buffer.concat([derSig.r, derSig.s], derSig.r.length + derSig.s.length); | ||
return base64url.fromBase64(signature.toString("base64")); | ||
return Buffer.concat([derSig.r, derSig.s], derSig.r.length + derSig.s.length); | ||
} | ||
@@ -117,4 +120,5 @@ } | ||
return function verify(input, signature, key) { | ||
input = normalizeInput(input); | ||
signature = new Buffer(base64url.toBase64(signature), "base64"); | ||
verifyBuffer(input, "input"); | ||
verifyBuffer(signature, "signature"); | ||
var bytesLength = (ecdsaKeySize[bits]/8 | 0) + (ecdsaKeySize[bits]%8 !== 0 ? 1 : 0); | ||
@@ -121,0 +125,0 @@ if(signature.length !== bytesLength*2) { |
{ | ||
"name": "jose", | ||
"version": "0.2.0", | ||
"version": "0.3.1", | ||
"description": "JSON Object Signing and Encryption (JOSE) library (symmetric and asymmetric)", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -28,2 +28,10 @@ # jose | ||
"alg" Header Parameter | Key Encryption Algorithm | Additional paramters needed | ||
-----------------------|------------------------- | --------------------------- | ||
RSA1_5 | Key wrapping using RSAES-PKCS1-v1_5 | none | ||
dir | Direct use of key as CEK | none | ||
A128GCMKW | Key wrapping using AES-GCM with 128-bit key | iv, tag for unwrapping | ||
A192GCMKW | Key wrapping using AES-GCM with 192-bit key | iv, tag for unwrapping | ||
A256GCMKW | Key wrapping using AES-GCM with 256-bit key | iv, tag for unwrapping | ||
The following content encryption algorithms are supported: | ||
@@ -40,5 +48,2 @@ | ||
Currently no key encryption algorithms are | ||
supported. | ||
### jwa(algorithm) | ||
@@ -62,4 +67,3 @@ Creates a new `jwa` object with `sign` and `verify` or `encrypt` and `decrypt` methods, depending | ||
If `input` is neither a string nor a buffer, | ||
it will be stringified using `JSON.stringify`. | ||
`input` must be a buffer. | ||
@@ -70,3 +74,3 @@ When using a HMAC algorithm `secretOrPrivateKey` should be either a | ||
Returns the signature in [base64url](https://en.wikipedia.org/wiki/Base64#URL_applications) format. | ||
Returns the signature as buffer. | ||
@@ -76,5 +80,5 @@ #### Example: | ||
var jose = require('jose'); | ||
var hs256 = jose.jwa('HS256'); | ||
var signature = hs256.sign('input', 'secret'); | ||
console.log(signature); // Prints 'jYmF0Et6vTLLqjd5o9qgGeDSaaIq7BWvjnKW9wLMaMY' | ||
var hs256 = new jose.jwa('HS256'); | ||
var signature = hs256.sign(input, 'secret'); | ||
console.log(signature); // Prints Buffer <8C, ... | ||
``` | ||
@@ -89,7 +93,6 @@ | ||
If `input` is neither a string nor a buffer, | ||
it will be stringified using `JSON.stringify`. | ||
`input` must be a buffer. | ||
When using a HMAC algorithm `secretOrPublicKey` should be either a | ||
string or a buffer. Whenn using a digital signature algorithm, the | ||
string or a buffer. When using a digital signature algorithm, the | ||
value should be a PEM encoded *public* key. | ||
@@ -102,4 +105,4 @@ | ||
var jose = require('jose'); | ||
var hs256 = jose.jwa('HS256'); | ||
var isValid = hs256.verify('input', 'jYmF0Et6vTLLqjd5o9qgGeDSaaIq7BWvjnKW9wLMaMY', 'secret'); | ||
var hs256 = new jose.jwa('HS256'); | ||
var isValid = hs256.verify(input, signature, 'secret'); | ||
console.log(isValid); // Prints 'true' | ||
@@ -123,3 +126,3 @@ ``` | ||
var jose = require('jose'); | ||
var aes = jose.jwa('A256GCM'); | ||
var aes = new jose.jwa('A256GCM'); | ||
var enc = aes.encrypt('secret', aad, iv, key); | ||
@@ -140,7 +143,52 @@ console.log(enc.cipher); // Prints Buffer <5F, ... | ||
#### Example: | ||
```js | ||
var jose = require('jose'); | ||
var aes = jose.jwa('A256GCM'); | ||
var aes = new jose.jwa('A256GCM'); | ||
var plain = aes.encrypt(ciphertext, tag, aad, iv, key); | ||
console.log(plain); // Prints Buffer <F9, ... | ||
``` | ||
``` | ||
### jwa.wrapKey(keyToWrap, key[, options]) | ||
*This method is only available to algorithms for key encryption.* | ||
Wraps the `keyToWrap` with a key suitable to the used algorithm, | ||
as defined by RFC7518. `options` may have to be provided, | ||
depending on the algorithm used for wrapping. | ||
`keyToWrap` must be a `Buffer`. | ||
`key` must be of an type that the used algorithm accepts. | ||
`options`, if provided, must be an object. | ||
Returns an object containing `keydata`, which is a `Buffer`, | ||
and possibly further arguments that are needed to unwrap the key again | ||
(see supported algorithms table). | ||
#### Example: | ||
```js | ||
var jose = require('jose'); | ||
var rsa = new jose.jwa('RSA1_5'); | ||
var wrapped = rsa.wrapKey(keyToWrap, key); | ||
console.log(wrapped.keydata); // Prints Buffer <58, ... | ||
``` | ||
### jwa.unwrapKey(keyToUnwrap, key[, options]) | ||
*This method is only available to algorithms for key encryption.* | ||
Unwraps the `keyToUnwrap` with a key suitable to the used algorithm, | ||
as defined by RFC7518. `options` may have to be provided, | ||
depending on the algorithm used for unwrapping. | ||
`keyToUnwrap` must be a `Buffer`. | ||
`key` must be of an type that the used algorithm accepts. | ||
`options`, if provided, must be an object. | ||
Returns a `Buffer`, which is the unwrapped key. | ||
#### Example: | ||
```js | ||
var jose = require('jose'); | ||
var rsa = new jose.jwa('RSA1_5'); | ||
var unwrapped = rsa.unwrapKey(keytoUnwrap, key); | ||
console.log(unwrapped); // Prints Buffer <A7, ... | ||
``` |
@@ -13,15 +13,21 @@ "use strict"; | ||
it("should create an empty string as signature", function() { | ||
var signature = alg.sign("123456", "secret"); | ||
it("should create an empty buffer as signature", function() { | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, "secret"); | ||
expect(signature).to.not.be.null; | ||
expect(signature).to.equal(""); | ||
expect(Buffer.isBuffer(signature)).to.be.true; | ||
expect(signature).to.have.length(0); | ||
}); | ||
it("should verify an empty signature as valid", function() { | ||
expect(alg.verify("123456", "", "secret")).to.be.true; | ||
it("should verify an zero-length buffer signature as valid", function() { | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
expect(alg.verify(input, new Buffer(0), "secret")).to.be.true; | ||
}); | ||
it("shouldn't verify a non-empty signature as valid", function() { | ||
expect(alg.verify("123456", "1", "secret")).to.be.false; | ||
it("shouldn't verify a non-zero-length buffer signature as valid", function() { | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
expect(alg.verify(input, new Buffer(1), "secret")).to.be.false; | ||
}); | ||
@@ -36,20 +42,31 @@ }); | ||
it("should create a non-empty string as signature", function() { | ||
var signature = alg.sign("123456", "secret"); | ||
it("should create a non-empty buffer as signature", function() { | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, "secret"); | ||
expect(signature).to.not.be.null; | ||
expect(Buffer.isBuffer(signature)).to.be.true; | ||
}); | ||
it("should verify a signature which was created with the same input and secret", function() { | ||
var signature = alg.sign("123456", "secret"); | ||
expect(alg.verify("123456", signature, "secret")).to.be.true; | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, "secret"); | ||
expect(alg.verify(input, signature, "secret")).to.be.true; | ||
}); | ||
it("shouldnt verify a wrong signature", function() { | ||
var signature = alg.sign("1234567", "secret"); | ||
expect(alg.verify("123456", signature, "secret")).to.be.false; | ||
var input1 = new Buffer(6); | ||
input1.fill(0); | ||
var input2 = new Buffer(6); | ||
input2.fill(1); | ||
var signature = alg.sign(input1, "secret"); | ||
expect(alg.verify(input2, signature, "secret")).to.be.false; | ||
}); | ||
it("shouldnt verify with a wrong secret", function() { | ||
var signature = alg.sign("123456", "secret"); | ||
expect(alg.verify("123456", signature, "secret2")).to.be.false; | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, "secret"); | ||
expect(alg.verify(input, signature, "secret2")).to.be.false; | ||
}); | ||
@@ -71,20 +88,31 @@ }); | ||
it("should create a non-empty string as signature", function() { | ||
var signature = alg.sign("123456", privKey[0]); | ||
it("should create a non-empty buffer as signature", function() { | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, privKey[0]); | ||
expect(signature).to.not.be.null; | ||
expect(Buffer.isBuffer(signature)).to.be.true; | ||
}); | ||
it("should verify a signature which was created with the same input and secret", function() { | ||
var signature = alg.sign("123456", privKey[0]); | ||
expect(alg.verify("123456", signature, pubKey[0])).to.be.true; | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, privKey[0]); | ||
expect(alg.verify(input, signature, pubKey[0])).to.be.true; | ||
}); | ||
it("shouldnt verify a wrong signature", function() { | ||
var signature = alg.sign("1234567", privKey[0]); | ||
expect(alg.verify("123456", signature, pubKey[0])).to.be.false; | ||
var input1 = new Buffer(6); | ||
input1.fill(0); | ||
var input2 = new Buffer(6); | ||
input2.fill(1); | ||
var signature = alg.sign(input1, privKey[0]); | ||
expect(alg.verify(input2, signature, pubKey[0])).to.be.false; | ||
}); | ||
it("shouldnt verify with a wrong secret", function() { | ||
var signature = alg.sign("123456", privKey[0]); | ||
expect(alg.verify("123456", signature, pubKey[1])).to.be.false; | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, privKey[0]); | ||
expect(alg.verify(input, signature, pubKey[1])).to.be.false; | ||
}); | ||
@@ -106,20 +134,31 @@ }); | ||
it("should create a non-empty string as signature", function() { | ||
var signature = alg.sign("123456", privKey[0]); | ||
it("should create a non-empty buffer as signature", function() { | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, privKey[0]); | ||
expect(signature).to.not.be.null; | ||
expect(Buffer.isBuffer(signature)).to.be.true; | ||
}); | ||
it("should verify a signature which was created with the same input and secret", function() { | ||
var signature = alg.sign("123456", privKey[0]); | ||
expect(alg.verify("123456", signature, pubKey[0])).to.be.true; | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, privKey[0]); | ||
expect(alg.verify(input, signature, pubKey[0])).to.be.true; | ||
}); | ||
it("shouldnt verify a wrong signature", function() { | ||
var signature = alg.sign("1234567", privKey[0]); | ||
expect(alg.verify("123456", signature, pubKey[0])).to.be.false; | ||
var input1 = new Buffer(6); | ||
input1.fill(0); | ||
var input2 = new Buffer(6); | ||
input2.fill(1); | ||
var signature = alg.sign(input1, privKey[0]); | ||
expect(alg.verify(input2, signature, pubKey[0])).to.be.false; | ||
}); | ||
it("shouldnt verify with a wrong secret", function() { | ||
var signature = alg.sign("123456", privKey[0]); | ||
expect(alg.verify("123456", signature, pubKey[1])).to.be.false; | ||
var input = new Buffer(6); | ||
input.fill(0); | ||
var signature = alg.sign(input, privKey[0]); | ||
expect(alg.verify(input, signature, pubKey[1])).to.be.false; | ||
}); | ||
@@ -126,0 +165,0 @@ }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
40840
20
868
186
2