New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

five-bells-shared

Package Overview
Dependencies
Maintainers
1
Versions
76
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

five-bells-shared - npm Package Compare versions

Comparing version 12.2.0 to 12.2.1

test/data/signKeyRSAPrv.pem

2

package.json
{
"name": "five-bells-shared",
"version": "12.2.0",
"version": "12.2.1",
"description": "Shared components for Five Bells projects.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -47,1 +47,31 @@ # Five Bells Shared [![Circle CI](https://circleci.com/gh/interledger/five-bells-shared/tree/master.svg?style=svg&circle-token=df06f3b2d8bce028f8b2410d8b993285c3da5c9b)](https://circleci.com/gh/interledger/five-bells-shared/tree/master)

```
## JSON signing
JSONSigning module provides API for adding signature block, and verifying it, in a JSON object. The format follows JSON Cleartext Signature (JCS) specification.
### Usage
```
JSONSigning.sign (json, cryptoType, privateKey, publicKey)
json : JSON object. Must not have "signature" block at the top level.
cryptoType : "PS256" for RSA PSS, or "ES256" for ECDSA
privateKey : Private key.
For RSA, it can be a PEM format string, or jsrsasign RSA key object.
For ECDSA, it has to be jsrsasign ECDSA key object.
publicKey : Public key.
This is not needed for
For ECDSA, it has to be jsrsasign ECDSA key object.
Returns copy of JSON object with "signature" block added. It does not modify the original JSON object.
JSONSigning.verify (json, cryptoType, publicKey)
json : JSON object. Must have "signature" block at the top level.
cryptoType : "PS256" for RSA PSS, or "ES256" for ECDSA
publicKey : Public key.
For RSA, it can be a PEM format string, or jsrsasign RSA key object.
For ECDSA, it has to be jsrsasign ECDSA key object.
Returns true (signature is valid) or false (otherwise)
```

@@ -25,3 +25,18 @@ {

}
},
"expectedRSASignedNotification": {
"id": "6821484d-6ca7-4157-b15b-388c49637111",
"subscription_id": "c6345f6e-d3c9-440b-8aa0-f0077c0c40f4",
"transfer_id": "ba32d964-f143-4b67-b470-d258025288d4",
"retry_count": 1,
"retry_at": 1457645427712,
"signature": {
"algorithm": "PS256",
"publicKey": {
"type": "RSA",
"e": "NjU1Mzc=",
"n": "Njc1NTkwOTcxMTE2NTEwMTIyODY4MzE0NjkwMzkxODI3NTAyMjQ4MzA1NzQ3NzA0NTkxNDg3MzA4MzI4MzQ3ODEzODgyNTgwMTIzMDU1NzE4OTM1MjAyMTY2Njk0OTIwODcxMDkzMzcwNjA2MDc5NTU3Mzg2ODg1MjI3MTY0MTE2NTkwMDYxNTkzMDU0NTQyMDgyMzU0Nzc5NjczMzExODExMzMwNzkwNjI0NTMxNjIxMjg2OTg0MTE3NDgwNzM3MzUwNzUwNjM4Mzg0MjYzNDMwMjczNDQ0OTIwNDgyODY5MDc2MTgzNDEwOTc1NTU2NDM4MzYxNTg4MTIyNzIxNzU0NzU2ODcwNDAyMTI3OTcxNzIxMTc2MjkxMTE2MzEwNzIxMzEyOTExMTgwNTMyNDE5ODE4NzM0NjYwNTE3MDc0MDIxNDE4Nzc3Mjc5NjcwNDkyNjc1NDA5NzU1NTk2MzUxOTAwOTAwMTA5NDMyMzAzNzg2NjExMTA3NTExNjk1NDU2MzUwNzI5NDQ5NTE4NzkxNTQ1NTAxMjkzNDcwNzExNzI3MzExNDgwMDY3Njk2MDQ3MDgwNDAwMzE5Njk2MzYxNjk3NTY0MTg2NzIxNDI3NDMwNDIyMDk3MzExNjgxNjQxNDkyNjM2Nzk1ODQxNDE5MTY5MjM1NzM1MTUzNDA2MDc1MDk1OTk3NTc2MDA4NDE3NTEyMjgzMjY5MTI3NDU1OTU4OTM3MTk5MDI1MDMxNTM4NTIyMzE5MTg5MTMyOTM3NDgyNzg2NzE3MzAxMDM0MjkyMDM2NTEzMzQ2NDU2OTE4MzcwOTk1NzQyMDM5NzAwOTkyNDM3NzY5OTM1NDQ2OTc1OTIxNDE1NjQyMTU2NzIxMzkzMTAwMjQyMDkxMTk1NTIyMjQ5ODc3NTk3NzY2MjE3NzE2MDc4MzgxNzY1MjYxMDIyNjY4NjEwNzE0NTY1MTk5ODkzODcxMTU0NDQ5NTQzMzk4NjQzNTA0Njc3NjIwNjEwOTY5ODkwNzE2MDk0MTM5NjcxOTQ1MjY2ODEzNzY1MTkyOTc4Mjc0NjcwMTk2Njc5NDM5MTM4MjgxMTk5MTc5Nzg5NjIzMzU5ODk0MTExOTEwOTAxNTYyMTg1NjE1ODcxMzQ5NjQzOTA5MjcwMDg3ODM0MzUxNTg5NTA3MjgxOTc5NzE4MzQxMzkxNzc0NjE0NzI1NzI3MjQ0ODQ0MDM0NTUyNzg2ODQxNzM3MDQ5NDc0ODU4NTY3OTAxOTY4NTcyMjcxMTY2NDk5OTgzNjI0MjkyODcwMjM5ODY0Njk4ODU0ODY3ODAyMzk5NTUxNTE3MDcyOTI0MDk1OTUzMjY4MzEzNzk4Nzg5MDEyODUzNjc4OTU5NjE1MTg1NTUxNzQwMTU0MzYxODc3OTM3NjkxMzg4MzU0MDc1Nzk0ODA4OTQxOTEwNzkxMDA3Njc2MzQzNTcyODUwNjY4NTM3MjU2NjU5MDU1Mzk2ODE5ODc0OTk0NDA2NzMzNzc0NTEwMjE0MzYyMDYxNjc0MDc4OTI2NTEzODYwOTczMjEzNTY2OTQ1MDYwNjk5MjEyNTg5Njk2Njg2NjA4NjMwODYxOTA3OTQ2NTUyNzQzNzM5OTUyMDkzNTQxMzUxNjcx"
}
}
}
}

@@ -19,6 +19,12 @@ 'use strict'

// Keys were generated by:
// openssl genrsa -out signKeyRSAPrv.pem 4096
// openssl rsa -in signKeyRSAPrv.pem -outform PEM -pubout -out signKeyRSAPub.pem
const prvRSAPEM = fs.readFileSync('test/data/signKeyRSAPrv.pem', 'utf8')
const pubRSAPEM = fs.readFileSync('test/data/signKeyRSAPub.pem', 'utf8')
describe('jsonSigningTests', function () {
describe('jsonSigning', function () {
it('should sign JSON object successfully', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, prvKey, pubKey)
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.ES256, prvKey, pubKey)
// Do not check signature.value, because this value changes every time it signs

@@ -32,4 +38,4 @@ delete signedJSON.signature.value

it('should sign and verify JSON object successfully', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, prvKey, pubKey)
const result = jsonSigning.verify(signedJSON, pubKey)
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.ES256, prvKey, pubKey)
const result = jsonSigning.verify(signedJSON, jsonSigning.types.ES256, pubKey)
expect(result).to.be.true

@@ -41,6 +47,6 @@ })

it('should catch invalid JSON signature', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, prvKey, pubKey)
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.ES256, prvKey, pubKey)
// Modify signature value to make verification fail
signedJSON.signature.value += 'X'
const result = jsonSigning.verify(signedJSON, pubKey)
const result = jsonSigning.verify(signedJSON, jsonSigning.types.ES256, pubKey)
expect(result).to.be.false

@@ -52,10 +58,47 @@ })

it('should catch invalid public key in signed JSON', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, prvKey, pubKey)
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.ES256, prvKey, pubKey)
// Modify public key in signature to make verification throw error
signedJSON.signature.publicKey.y += 'X'
expect(function () {
jsonSigning.verify(signedJSON, pubKey)
jsonSigning.verify(signedJSON, jsonSigning.types.ES256, pubKey)
}).to.throw(ServerError)
})
})
describe('jsonRSASigning', function () {
it('should sign JSON object with RSA successfully', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.PS256, prvRSAPEM)
// Do not check signature.value, because this value changes every time it signs
delete signedJSON.signature.value
expect(signedJSON).to.deep.equal(signData.expectedRSASignedNotification)
})
})
describe('jsonRSASignAndVerify', function () {
it('should sign and verify JSON object with RSA successfully', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.PS256, prvRSAPEM)
const result = jsonSigning.verify(signedJSON, jsonSigning.types.PS256, pubRSAPEM)
expect(result).to.be.true
})
})
describe('jsonRSAInvalidSignature', function () {
it('should catch invalid JSON signature with RSA', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.PS256, prvRSAPEM)
signedJSON.signature.value += 'X'
const result = jsonSigning.verify(signedJSON, jsonSigning.types.PS256, pubRSAPEM)
expect(result).to.be.false
})
})
describe('jsonRSAInvalidPublicKey', function () {
it('should catch invalid RSA public key in signed JSON', function () {
const signedJSON = jsonSigning.sign(signData.sampleNotification, jsonSigning.types.PS256, prvRSAPEM)
// Modify public key in signature to make verification throw error
signedJSON.signature.publicKey.n += 'X'
expect(function () {
jsonSigning.verify(signedJSON, jsonSigning.types.PS256, pubRSAPEM)
}).to.throw(ServerError)
})
})
})

@@ -8,6 +8,30 @@ // JSON Cleartext Signing

// Constants for crypto algorithm types (ECDSA and RSA)
const ES256 = 'ES256'
const PS256 = 'PS256'
module.exports.types = {
ES256,
PS256
}
// If given key is PEM formatted string, convert it to key object
// If it's already key object, just use it
function parseKey (key) {
if (typeof key === 'string') {
return rsasign.KEYUTIL.getKey(key)
} else {
return key
}
}
// Sign JSON object, using ECDSA P-256 private key and public key.
// Insert 'signature' block in the JSON object.
// Warning: there must not be an existing 'signature' block.
module.exports.sign = function (json, prvKey, pubKey) {
module.exports.sign = function (json, cryptoType, prvKey, pubKey) {
if (cryptoType === ES256) return signECDSA(json, prvKey, pubKey)
else if (cryptoType === PS256) return signRSA(json, prvKey)
else throw new ServerError('Unsupported crypto algorithm: ' + cryptoType)
}
function signECDSA (json, prvKey, pubKey) {
if (!prvKey) throw new ServerError('Problem reading private key for JSON signing')

@@ -45,4 +69,37 @@ if (!pubKey) throw new ServerError('Problem reading public key for JSON signing')

// Sign JSON object using RSA
function signRSA (json, prvKey) {
if (!prvKey) throw new ServerError('Problem reading private key for JSON signing')
const prvKeyObj = parseKey(prvKey)
const strJWS = KJUR.jws.JWS.sign(PS256, // eslint-disable-line no-undef
JSON.stringify({alg: PS256}),
JSON.stringify(json),
prvKeyObj)
const jwsArray = strJWS.split('.')
// TODO: To make e and n exactly compliant with JCS spec, E and N must be represented as
// "Base64URL-encoded positive integer with arbitrary precision."
// jsrsasign stores public key components "e" as Number, and "n" as BigInteger
const pubkeyE = new Buffer(prvKeyObj.e.toString()).toString('base64')
const pubkeyN = new Buffer(prvKeyObj.n.toString()).toString('base64')
const signedJSON = _.cloneDeep(json)
signedJSON.signature = {
'algorithm': PS256,
'publicKey': {
'type': 'RSA',
'e': pubkeyE,
'n': pubkeyN
},
'value': jwsArray[2]
}
return signedJSON
}
// Verify 'signature' block on the input JSON object has the correct signature value.
module.exports.verify = function (json, pubKey) {
module.exports.verify = function (json, cryptoType, pubKey) {
if (cryptoType === ES256) return verifyECDSA(json, pubKey)
else if (cryptoType === PS256) return verifyRSA(json, pubKey)
else throw new ServerError('Unsupported crypto algorithm: ' + cryptoType)
}
function verifyECDSA (json, pubKey) {
if (!json || !json.signature || !json.signature.value) {

@@ -54,3 +111,3 @@ throw new ServerError('Invalid input for JSON verification')

let strPayload = new Buffer(JSON.stringify(jsonWithoutSignature)).toString('base64')
// chop training '=='
// chop trailing '=='
if (_.endsWith(strPayload, '==')) {

@@ -78,1 +135,25 @@ strPayload = strPayload.slice(0, strPayload.length - 2)

}
function verifyRSA (json, pubKey) {
if (!json || !json.signature || !json.signature.value) {
throw new ServerError('Invalid input for JSON verification')
}
if (!pubKey) throw new ServerError('Problem reading public key for JSON signing')
const pubKeyObj = parseKey(pubKey)
const jsonWithoutSignature = _.omit(json, 'signature')
let strPayload = new Buffer(JSON.stringify(jsonWithoutSignature)).toString('base64')
// chop trailing '=='
if (_.endsWith(strPayload, '==')) {
strPayload = strPayload.slice(0, strPayload.length - 2)
}
// Check pub key parameters
const pubkeyE = new Buffer(pubKeyObj.e.toString()).toString('base64')
const pubkeyN = new Buffer(pubKeyObj.n.toString()).toString('base64')
if (json.signature.publicKey.e !== pubkeyE || json.signature.publicKey.n !== pubkeyN) {
throw new ServerError('Public key mismatch in JSON signature verification')
}
const jws = 'eyJhbGciOiJQUzI1NiJ9\.' + // Base64 encoded {"alg":"PS256"}
strPayload + '\.' + json.signature.value
return KJUR.jws.JWS.verify(jws, pubKeyObj, [PS256]) // eslint-disable-line no-undef
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc