mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
234 lines
5.2 KiB
JavaScript
234 lines
5.2 KiB
JavaScript
var asn = require('asn1.js')
|
|
var factor = require('./factor')
|
|
var one = new asn.bignum(1)
|
|
|
|
function urlize(base64) {
|
|
return base64.replace(/\+/g, '-')
|
|
.replace(/\//g, '_')
|
|
.replace(/=/g, '')
|
|
}
|
|
|
|
function hex2b64url(str) {
|
|
return urlize(Buffer.from(str, 'hex').toString('base64'))
|
|
}
|
|
|
|
function fromPEM(data) {
|
|
var text = data.toString().split(/(\r\n|\r|\n)+/g);
|
|
text = text.filter(function(line) {
|
|
return line.trim().length !== 0;
|
|
});
|
|
text = text.slice(1, -1).join('');
|
|
return Buffer.from(text.replace(/[^\w\d\+\/=]+/g, ''), 'base64');
|
|
}
|
|
|
|
var RSAPublicKey = asn.define('RSAPublicKey', function () {
|
|
this.seq().obj(
|
|
this.key('n').int(),
|
|
this.key('e').int()
|
|
)
|
|
})
|
|
|
|
var AlgorithmIdentifier = asn.define('AlgorithmIdentifier', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').objid(),
|
|
this.key('parameters').optional().any()
|
|
)
|
|
})
|
|
|
|
var PublicKeyInfo = asn.define('PublicKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('publicKey').bitstr()
|
|
)
|
|
})
|
|
|
|
var Version = asn.define('Version', function () {
|
|
this.int({
|
|
0: 'two-prime',
|
|
1: 'multi'
|
|
})
|
|
})
|
|
|
|
var OtherPrimeInfos = asn.define('OtherPrimeInfos', function () {
|
|
this.seq().obj(
|
|
this.key('ri').int(),
|
|
this.key('di').int(),
|
|
this.key('ti').int()
|
|
)
|
|
})
|
|
|
|
var RSAPrivateKey = asn.define('RSAPrivateKey', function () {
|
|
this.seq().obj(
|
|
this.key('version').use(Version),
|
|
this.key('n').int(),
|
|
this.key('e').int(),
|
|
this.key('d').int(),
|
|
this.key('p').int(),
|
|
this.key('q').int(),
|
|
this.key('dp').int(),
|
|
this.key('dq').int(),
|
|
this.key('qi').int(),
|
|
this.key('other').optional().use(OtherPrimeInfos)
|
|
)
|
|
})
|
|
|
|
var PrivateKeyInfo = asn.define('PrivateKeyInfo', function () {
|
|
this.seq().obj(
|
|
this.key('version').use(Version),
|
|
this.key('algorithm').use(AlgorithmIdentifier),
|
|
this.key('privateKey').bitstr()
|
|
)
|
|
})
|
|
|
|
const RSA_OID = '1.2.840.113549.1.1.1'
|
|
|
|
function addExtras(obj, extras) {
|
|
extras = extras || {}
|
|
Object.keys(extras).forEach(
|
|
function (key) {
|
|
obj[key] = extras[key]
|
|
}
|
|
)
|
|
return obj
|
|
}
|
|
|
|
function pad(hex) {
|
|
return (hex.length % 2 === 1) ? '0' + hex : hex
|
|
}
|
|
|
|
function decodeRsaPublic(buffer, extras) {
|
|
var key = RSAPublicKey.decode(buffer, 'der')
|
|
var e = pad(key.e.toString(16))
|
|
var jwk = {
|
|
kty: 'RSA',
|
|
n: bn2base64url(key.n),
|
|
e: hex2b64url(e)
|
|
}
|
|
return addExtras(jwk, extras)
|
|
}
|
|
|
|
function decodeRsaPrivate(buffer, extras) {
|
|
var key = RSAPrivateKey.decode(buffer, 'der')
|
|
var e = pad(key.e.toString(16))
|
|
var jwk = {
|
|
kty: 'RSA',
|
|
n: bn2base64url(key.n),
|
|
e: hex2b64url(e),
|
|
d: bn2base64url(key.d),
|
|
p: bn2base64url(key.p),
|
|
q: bn2base64url(key.q),
|
|
dp: bn2base64url(key.dp),
|
|
dq: bn2base64url(key.dq),
|
|
qi: bn2base64url(key.qi)
|
|
}
|
|
return addExtras(jwk, extras)
|
|
}
|
|
|
|
function decodePublic(buffer, extras) {
|
|
var info = PublicKeyInfo.decode(buffer, 'der')
|
|
return decodeRsaPublic(info.publicKey.data, extras)
|
|
}
|
|
|
|
function decodePrivate(buffer, extras) {
|
|
var info = PrivateKeyInfo.decode(buffer, 'der')
|
|
return decodeRsaPrivate(info.privateKey.data, extras)
|
|
}
|
|
|
|
function getDecoder(header) {
|
|
var match = /^-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----$/.exec(header)
|
|
if (!match) { return null }
|
|
var isRSA = !!(match[1])
|
|
var isPrivate = (match[2] === 'PRIVATE')
|
|
if (isPrivate) {
|
|
return isRSA ? decodeRsaPrivate : decodePrivate
|
|
}
|
|
else {
|
|
return isRSA ? decodeRsaPublic : decodePublic
|
|
}
|
|
}
|
|
|
|
function pem2jwk(pem, extras) {
|
|
var text = pem.toString().split(/(\r\n|\r|\n)+/g)
|
|
text = text.filter(function(line) {
|
|
return line.trim().length !== 0
|
|
});
|
|
var decoder = getDecoder(text[0])
|
|
|
|
text = text.slice(1, -1).join('')
|
|
return decoder(Buffer.from(text.replace(/[^\w\d\+\/=]+/g, ''), 'base64'), extras)
|
|
}
|
|
|
|
function recomputePrimes(jwk) {
|
|
var pq = factor(jwk.e, jwk.d, jwk.n)
|
|
var p = pq.p
|
|
var q = pq.q
|
|
var dp = jwk.d.mod(p.sub(one))
|
|
var dq = jwk.d.mod(q.sub(one))
|
|
var qi = q.invm(p)
|
|
return {
|
|
n: jwk.n,
|
|
e: jwk.e,
|
|
d: jwk.d,
|
|
p: p,
|
|
q: q,
|
|
dp: dp,
|
|
dq: dq,
|
|
qi: qi
|
|
}
|
|
}
|
|
|
|
function parse(jwk) {
|
|
return {
|
|
n: string2bn(jwk.n),
|
|
e: string2bn(jwk.e),
|
|
d: jwk.d && string2bn(jwk.d),
|
|
p: jwk.p && string2bn(jwk.p),
|
|
q: jwk.q && string2bn(jwk.q),
|
|
dp: jwk.dp && string2bn(jwk.dp),
|
|
dq: jwk.dq && string2bn(jwk.dq),
|
|
qi: jwk.qi && string2bn(jwk.qi)
|
|
}
|
|
}
|
|
|
|
function jwk2pem(json) {
|
|
var jwk = parse(json)
|
|
var isPrivate = !!(jwk.d)
|
|
var t = isPrivate ? 'PRIVATE' : 'PUBLIC'
|
|
var header = '-----BEGIN RSA ' + t + ' KEY-----\n'
|
|
var footer = '\n-----END RSA ' + t + ' KEY-----\n'
|
|
var data = null
|
|
if (isPrivate) {
|
|
if (!jwk.p) {
|
|
jwk = recomputePrimes(jwk)
|
|
}
|
|
jwk.version = 'two-prime'
|
|
data = RSAPrivateKey.encode(jwk, 'der')
|
|
}
|
|
else {
|
|
data = RSAPublicKey.encode(jwk, 'der')
|
|
}
|
|
var body = data.toString('base64').match(/.{1,64}/g).join('\n')
|
|
return header + body + footer
|
|
}
|
|
|
|
function bn2base64url(bn) {
|
|
return hex2b64url(pad(bn.toString(16)))
|
|
}
|
|
|
|
function base64url2bn(str) {
|
|
return new asn.bignum(Buffer.from(str, 'base64'))
|
|
}
|
|
|
|
function string2bn(str) {
|
|
if (/^[0-9]+$/.test(str)) {
|
|
return new asn.bignum(str, 10)
|
|
}
|
|
return base64url2bn(str)
|
|
}
|
|
|
|
module.exports = {
|
|
pem2jwk: pem2jwk,
|
|
jwk2pem: jwk2pem,
|
|
BN: asn.bignum
|
|
}
|