2016-11-29 17:54:41 +01:00
|
|
|
'use strict'
|
|
|
|
|
2019-07-17 11:17:18 +01:00
|
|
|
const webcrypto = require('../webcrypto')
|
2019-01-08 18:37:03 +00:00
|
|
|
const randomBytes = require('../random-bytes')
|
2016-11-29 17:54:41 +01:00
|
|
|
|
|
|
|
exports.utils = require('./rsa-utils')
|
|
|
|
|
2019-07-10 17:15:26 +01:00
|
|
|
exports.generateKey = async function (bits) {
|
2019-07-17 11:17:18 +01:00
|
|
|
const pair = await webcrypto.get().subtle.generateKey(
|
2016-11-29 17:54:41 +01:00
|
|
|
{
|
|
|
|
name: 'RSASSA-PKCS1-v1_5',
|
|
|
|
modulusLength: bits,
|
|
|
|
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
|
2019-01-03 08:13:07 -08:00
|
|
|
hash: { name: 'SHA-256' }
|
2016-11-29 17:54:41 +01:00
|
|
|
},
|
|
|
|
true,
|
|
|
|
['sign', 'verify']
|
|
|
|
)
|
2019-07-10 17:15:26 +01:00
|
|
|
|
|
|
|
const keys = await exportKey(pair)
|
|
|
|
|
|
|
|
return {
|
|
|
|
privateKey: keys[0],
|
|
|
|
publicKey: keys[1]
|
|
|
|
}
|
2016-11-29 17:54:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Takes a jwk key
|
2019-07-10 17:15:26 +01:00
|
|
|
exports.unmarshalPrivateKey = async function (key) {
|
2019-07-17 11:17:18 +01:00
|
|
|
const privateKey = await webcrypto.get().subtle.importKey(
|
2016-11-29 17:54:41 +01:00
|
|
|
'jwk',
|
|
|
|
key,
|
|
|
|
{
|
|
|
|
name: 'RSASSA-PKCS1-v1_5',
|
2019-01-03 08:13:07 -08:00
|
|
|
hash: { name: 'SHA-256' }
|
2016-11-29 17:54:41 +01:00
|
|
|
},
|
|
|
|
true,
|
|
|
|
['sign']
|
|
|
|
)
|
|
|
|
|
2019-07-10 17:15:26 +01:00
|
|
|
const pair = [
|
2016-11-29 17:54:41 +01:00
|
|
|
privateKey,
|
2019-07-10 17:15:26 +01:00
|
|
|
await derivePublicFromPrivate(key)
|
|
|
|
]
|
|
|
|
|
|
|
|
const keys = await exportKey({
|
|
|
|
privateKey: pair[0],
|
|
|
|
publicKey: pair[1]
|
|
|
|
})
|
|
|
|
|
|
|
|
return {
|
2016-11-29 17:54:41 +01:00
|
|
|
privateKey: keys[0],
|
|
|
|
publicKey: keys[1]
|
2019-07-10 17:15:26 +01:00
|
|
|
}
|
2016-11-29 17:54:41 +01:00
|
|
|
}
|
|
|
|
|
2019-01-08 18:37:03 +00:00
|
|
|
exports.getRandomValues = randomBytes
|
2016-11-29 17:54:41 +01:00
|
|
|
|
2019-07-10 17:15:26 +01:00
|
|
|
exports.hashAndSign = async function (key, msg) {
|
2019-07-17 11:17:18 +01:00
|
|
|
const privateKey = await webcrypto.get().subtle.importKey(
|
2016-11-29 17:54:41 +01:00
|
|
|
'jwk',
|
|
|
|
key,
|
|
|
|
{
|
|
|
|
name: 'RSASSA-PKCS1-v1_5',
|
2019-01-03 08:13:07 -08:00
|
|
|
hash: { name: 'SHA-256' }
|
2016-11-29 17:54:41 +01:00
|
|
|
},
|
|
|
|
false,
|
|
|
|
['sign']
|
2019-07-10 17:15:26 +01:00
|
|
|
)
|
|
|
|
|
2019-07-17 11:17:18 +01:00
|
|
|
const sig = await webcrypto.get().subtle.sign(
|
2019-07-10 17:15:26 +01:00
|
|
|
{ name: 'RSASSA-PKCS1-v1_5' },
|
|
|
|
privateKey,
|
|
|
|
Uint8Array.from(msg)
|
|
|
|
)
|
|
|
|
|
|
|
|
return Buffer.from(sig)
|
2016-11-29 17:54:41 +01:00
|
|
|
}
|
|
|
|
|
2019-07-10 17:15:26 +01:00
|
|
|
exports.hashAndVerify = async function (key, sig, msg) {
|
2019-07-17 11:17:18 +01:00
|
|
|
const publicKey = await webcrypto.get().subtle.importKey(
|
2016-11-29 17:54:41 +01:00
|
|
|
'jwk',
|
|
|
|
key,
|
|
|
|
{
|
|
|
|
name: 'RSASSA-PKCS1-v1_5',
|
2019-01-03 08:13:07 -08:00
|
|
|
hash: { name: 'SHA-256' }
|
2016-11-29 17:54:41 +01:00
|
|
|
},
|
|
|
|
false,
|
|
|
|
['verify']
|
2019-07-10 17:15:26 +01:00
|
|
|
)
|
|
|
|
|
2019-07-17 11:17:18 +01:00
|
|
|
return webcrypto.get().subtle.verify(
|
2019-07-10 17:15:26 +01:00
|
|
|
{ name: 'RSASSA-PKCS1-v1_5' },
|
|
|
|
publicKey,
|
|
|
|
sig,
|
|
|
|
msg
|
|
|
|
)
|
2016-11-29 17:54:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function exportKey (pair) {
|
|
|
|
return Promise.all([
|
2019-07-17 11:17:18 +01:00
|
|
|
webcrypto.get().subtle.exportKey('jwk', pair.privateKey),
|
|
|
|
webcrypto.get().subtle.exportKey('jwk', pair.publicKey)
|
2016-11-29 17:54:41 +01:00
|
|
|
])
|
|
|
|
}
|
|
|
|
|
|
|
|
function derivePublicFromPrivate (jwKey) {
|
2019-07-17 11:17:18 +01:00
|
|
|
return webcrypto.get().subtle.importKey(
|
2016-11-29 17:54:41 +01:00
|
|
|
'jwk',
|
|
|
|
{
|
|
|
|
kty: jwKey.kty,
|
|
|
|
n: jwKey.n,
|
2017-12-20 21:11:47 +13:00
|
|
|
e: jwKey.e
|
2016-11-29 17:54:41 +01:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: 'RSASSA-PKCS1-v1_5',
|
2019-01-03 08:13:07 -08:00
|
|
|
hash: { name: 'SHA-256' }
|
2016-11-29 17:54:41 +01:00
|
|
|
},
|
|
|
|
true,
|
|
|
|
['verify']
|
|
|
|
)
|
|
|
|
}
|
2019-07-12 18:53:56 +02:00
|
|
|
|
|
|
|
exports.encrypt = async function (key, msg) {
|
|
|
|
key = Object.assign({}, key)
|
|
|
|
key.key_ops = ['encrypt']
|
|
|
|
|
|
|
|
return webcrypto.subtle.importKey(
|
|
|
|
'jwk',
|
|
|
|
key,
|
|
|
|
{
|
|
|
|
name: 'RSA-OAEP',
|
|
|
|
hash: { name: 'SHA-256' }
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
['encrypt']
|
|
|
|
).then((publicKey) => {
|
|
|
|
return webcrypto.subtle.encrypt(
|
|
|
|
{ name: 'RSA-OEAP' },
|
|
|
|
publicKey,
|
|
|
|
Uint8Array.from(msg)
|
|
|
|
)
|
|
|
|
}).then((enc) => Buffer.from(enc))
|
|
|
|
}
|
|
|
|
|
|
|
|
exports.decrypt = async function (key, msg) {
|
|
|
|
key = Object.assign({}, key)
|
|
|
|
key.key_ops = ['decrypt']
|
|
|
|
|
|
|
|
return webcrypto.subtle.importKey(
|
|
|
|
'jwk',
|
|
|
|
key,
|
|
|
|
{
|
|
|
|
name: 'RSA-OAEP',
|
|
|
|
hash: { name: 'SHA-256' }
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
['decrypt']
|
|
|
|
).then((privateKey) => {
|
|
|
|
return webcrypto.subtle.decrypt(
|
|
|
|
{ name: 'RSA-OAEP' },
|
|
|
|
privateKey,
|
|
|
|
Uint8Array.from(msg)
|
|
|
|
)
|
|
|
|
}).then((dec) => Buffer.from(dec))
|
|
|
|
}
|