Bugfix in Native ECC in Node
This commit is contained in:
parent
5fac00eddb
commit
5e857e131e
10
Gruntfile.js
10
Gruntfile.js
|
@ -49,11 +49,12 @@ module.exports = function(grunt) {
|
|||
standalone: 'openpgp'
|
||||
},
|
||||
// Don't bundle these packages with openpgp.js
|
||||
external: ['crypto', 'zlib', 'node-localstorage', 'node-fetch', 'asn1.js', 'jwk-to-pem'],
|
||||
external: ['crypto', 'zlib', 'node-localstorage', 'node-fetch', 'asn1.js'],
|
||||
transform: [
|
||||
["babelify", {
|
||||
global: true,
|
||||
only: /^(?:.*\/node_modules\/asmcrypto\.js\/|(?!.*\/node_modules\/)).*$/, // Only babelify asmcrypto in node_modules
|
||||
// Only babelify asmcrypto in node_modules
|
||||
only: /^(?:.*\/node_modules\/asmcrypto\.js\/|(?!.*\/node_modules\/)).*$/,
|
||||
plugins: ["transform-async-to-generator",
|
||||
"syntax-async-functions",
|
||||
"transform-regenerator",
|
||||
|
@ -75,11 +76,12 @@ module.exports = function(grunt) {
|
|||
debug: true,
|
||||
standalone: 'openpgp'
|
||||
},
|
||||
external: ['crypto', 'zlib', 'node-localstorage', 'node-fetch', 'asn1.js', 'jwk-to-pem'],
|
||||
external: ['crypto', 'zlib', 'node-localstorage', 'node-fetch', 'asn1.js'],
|
||||
transform: [
|
||||
["babelify", {
|
||||
global: true,
|
||||
only: /^(?:.*\/node_modules\/asmcrypto\.js\/|(?!.*\/node_modules\/)).*$/, // Only babelify asmcrypto in node_modules
|
||||
// Only babelify asmcrypto in node_modules
|
||||
only: /^(?:.*\/node_modules\/asmcrypto\.js\/|(?!.*\/node_modules\/)).*$/,
|
||||
plugins: ["transform-async-to-generator",
|
||||
"syntax-async-functions",
|
||||
"transform-regenerator",
|
||||
|
|
|
@ -79,7 +79,6 @@
|
|||
"compressjs": "github:openpgpjs/compressjs",
|
||||
"elliptic": "github:openpgpjs/elliptic",
|
||||
"hash.js": "^1.1.3",
|
||||
"jwk-to-pem": "^1.2.6",
|
||||
"node-fetch": "^1.7.3",
|
||||
"node-localstorage": "~1.3.0",
|
||||
"pako": "^1.0.6",
|
||||
|
|
|
@ -56,7 +56,7 @@ if (nodeCrypto) {
|
|||
|
||||
const curves = {
|
||||
p256: {
|
||||
oid: util.Uint8Array_to_str([0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07]),
|
||||
oid: [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07],
|
||||
keyType: enums.publicKey.ecdsa,
|
||||
hash: enums.hash.sha256,
|
||||
cipher: enums.symmetric.aes128,
|
||||
|
@ -65,7 +65,7 @@ const curves = {
|
|||
payloadSize: 32
|
||||
},
|
||||
p384: {
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x81, 0x04, 0x00, 0x22]),
|
||||
oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22],
|
||||
keyType: enums.publicKey.ecdsa,
|
||||
hash: enums.hash.sha384,
|
||||
cipher: enums.symmetric.aes192,
|
||||
|
@ -74,7 +74,7 @@ const curves = {
|
|||
payloadSize: 48
|
||||
},
|
||||
p521: {
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x81, 0x04, 0x00, 0x23]),
|
||||
oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x23],
|
||||
keyType: enums.publicKey.ecdsa,
|
||||
hash: enums.hash.sha512,
|
||||
cipher: enums.symmetric.aes256,
|
||||
|
@ -83,80 +83,83 @@ const curves = {
|
|||
payloadSize: 66
|
||||
},
|
||||
secp256k1: {
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x81, 0x04, 0x00, 0x0A]),
|
||||
oid: [0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x0A],
|
||||
keyType: enums.publicKey.ecdsa,
|
||||
hash: enums.hash.sha256,
|
||||
cipher: enums.symmetric.aes128,
|
||||
node: false // FIXME when we replace jwk-to-pem or it supports this curve
|
||||
node: nodeCurves.secp256k1
|
||||
},
|
||||
ed25519: {
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01]),
|
||||
oid: [0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01],
|
||||
keyType: enums.publicKey.eddsa,
|
||||
hash: enums.hash.sha512,
|
||||
payloadSize: 32
|
||||
},
|
||||
curve25519: {
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01]),
|
||||
oid: [0x06, 0x08, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01],
|
||||
keyType: enums.publicKey.ecdsa,
|
||||
hash: enums.hash.sha256,
|
||||
cipher: enums.symmetric.aes128
|
||||
},
|
||||
brainpoolP256r1: { // TODO 1.3.36.3.3.2.8.1.1.7
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07])
|
||||
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07]
|
||||
},
|
||||
brainpoolP384r1: { // TODO 1.3.36.3.3.2.8.1.1.11
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B])
|
||||
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B]
|
||||
},
|
||||
brainpoolP512r1: { // TODO 1.3.36.3.3.2.8.1.1.13
|
||||
oid: util.Uint8Array_to_str([0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D])
|
||||
oid: [0x06, 0x07, 0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D]
|
||||
}
|
||||
};
|
||||
|
||||
export default function Curve(oid_or_name, params) {
|
||||
if (OID.prototype.isPrototypeOf(oid_or_name) &&
|
||||
enums.curve[oid_or_name.toHex()]) {
|
||||
this.name = oid_or_name.toHex(); // by curve OID
|
||||
} else if (enums.curve[oid_or_name]) {
|
||||
this.name = oid_or_name; // by curve name
|
||||
} else if (enums.curve[util.str_to_hex(oid_or_name)]) {
|
||||
this.name = util.str_to_hex(oid_or_name); // by oid string
|
||||
} else {
|
||||
try {
|
||||
if (util.isArray(oid_or_name) ||
|
||||
util.isUint8Array(oid_or_name)) {
|
||||
// by oid byte array
|
||||
oid_or_name = new OID(oid_or_name);
|
||||
}
|
||||
if (oid_or_name instanceof OID) {
|
||||
// by curve OID
|
||||
oid_or_name = oid_or_name.getName();
|
||||
}
|
||||
// by curve name or oid string
|
||||
this.name = enums.write(enums.curve, oid_or_name);
|
||||
} catch (err) {
|
||||
throw new Error('Not valid curve');
|
||||
}
|
||||
this.name = enums.write(enums.curve, this.name);
|
||||
this.oid = new OID(curves[this.name].oid);
|
||||
|
||||
params = params || curves[this.name];
|
||||
|
||||
this.keyType = params.keyType;
|
||||
switch (this.keyType) {
|
||||
case enums.publicKey.eddsa:
|
||||
this.curve = new EdDSA(this.name);
|
||||
break;
|
||||
case enums.publicKey.ecdsa:
|
||||
this.curve = new EC(this.name);
|
||||
break;
|
||||
case enums.publicKey.eddsa:
|
||||
this.curve = new EdDSA(this.name);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown elliptic key type;');
|
||||
}
|
||||
|
||||
this.oid = params.oid;
|
||||
this.hash = params.hash;
|
||||
this.cipher = params.cipher;
|
||||
this.node = params.node && curves[this.name].node;
|
||||
this.web = params.web && curves[this.name].web;
|
||||
this.payloadSize = curves[this.name].payloadSize;
|
||||
this.node = params.node && curves[this.name];
|
||||
this.web = params.web && curves[this.name];
|
||||
this.payloadSize = params.payloadSize;
|
||||
}
|
||||
|
||||
Curve.prototype.keyFromPrivate = function (priv) { // Not for ed25519
|
||||
return new KeyPair(this.curve, { priv: priv });
|
||||
return new KeyPair(this, { priv: priv });
|
||||
};
|
||||
|
||||
Curve.prototype.keyFromSecret = function (secret) { // Only for ed25519
|
||||
return new KeyPair(this.curve, { secret: secret });
|
||||
return new KeyPair(this, { secret: secret });
|
||||
};
|
||||
|
||||
Curve.prototype.keyFromPublic = function (pub) {
|
||||
return new KeyPair(this.curve, { pub: pub });
|
||||
return new KeyPair(this, { pub: pub });
|
||||
};
|
||||
|
||||
Curve.prototype.genKeyPair = async function () {
|
||||
|
@ -174,7 +177,9 @@ Curve.prototype.genKeyPair = async function () {
|
|||
|
||||
if (!keyPair || !keyPair.priv) {
|
||||
// elliptic fallback
|
||||
const r = await this.curve.genKeyPair({ entropy: util.Uint8Array_to_str(random.getRandomBytes(32)) });
|
||||
const r = await this.curve.genKeyPair({
|
||||
entropy: util.Uint8Array_to_str(random.getRandomBytes(32))
|
||||
});
|
||||
const compact = this.curve.curve.type === 'edwards' || this.curve.curve.type === 'mont';
|
||||
if (this.keyType === enums.publicKey.eddsa) {
|
||||
keyPair = { secret: r.getSecret() };
|
||||
|
@ -182,14 +187,14 @@ Curve.prototype.genKeyPair = async function () {
|
|||
keyPair = { pub: r.getPublic('array', compact), priv: r.getPrivate().toArray() };
|
||||
}
|
||||
}
|
||||
return new KeyPair(this.curve, keyPair);
|
||||
return new KeyPair(this, keyPair);
|
||||
};
|
||||
|
||||
async function generate(curve) {
|
||||
curve = new Curve(curve);
|
||||
const keyPair = await curve.genKeyPair();
|
||||
return {
|
||||
oid: curve.oid,
|
||||
oid: new OID(curve.oid.slice(2)),
|
||||
Q: new BN(keyPair.getPublic()),
|
||||
d: new BN(keyPair.getPrivate()),
|
||||
hash: curve.hash,
|
||||
|
@ -230,6 +235,7 @@ async function webGenKeyPair(name) {
|
|||
}
|
||||
|
||||
async function nodeGenKeyPair(name) {
|
||||
// Note: ECDSA and ECDH key generation is structurally equivalent
|
||||
const ecdh = nodeCrypto.createECDH(nodeCurves[name]);
|
||||
await ecdh.generateKeys();
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
|
||||
import BN from 'bn.js';
|
||||
import { webCurves, nodeCurves } from './curves';
|
||||
import { curves, webCurves, nodeCurves } from './curves';
|
||||
import hash from '../../hash';
|
||||
import util from '../../../util';
|
||||
import enums from '../../../enums';
|
||||
|
@ -37,19 +37,10 @@ import enums from '../../../enums';
|
|||
const webCrypto = util.getWebCrypto();
|
||||
const nodeCrypto = util.getNodeCrypto();
|
||||
|
||||
const jwkToPem = nodeCrypto ? require('jwk-to-pem') : undefined;
|
||||
const ECDSASignature = nodeCrypto ?
|
||||
require('asn1.js').define('ECDSASignature', function() {
|
||||
this.seq().obj(
|
||||
this.key('r').int(),
|
||||
this.key('s').int()
|
||||
);
|
||||
}) : undefined;
|
||||
|
||||
export default function KeyPair(curve, options) {
|
||||
this.curve = curve;
|
||||
this.keyType = curve.curve.type === 'edwards' ? enums.publicKey.eddsa : enums.publicKey.ecdsa;
|
||||
this.keyPair = this.curve.keyPair(options);
|
||||
this.keyPair = this.curve.curve.keyPair(options);
|
||||
}
|
||||
|
||||
KeyPair.prototype.sign = async function (message, hash_algo) {
|
||||
|
@ -90,12 +81,13 @@ KeyPair.prototype.derive = function (pub) {
|
|||
};
|
||||
|
||||
KeyPair.prototype.getPublic = function () {
|
||||
const compact = (this.curve.curve.type === 'edwards' || this.curve.curve.type === 'mont');
|
||||
const compact = this.curve.curve.curve.type === 'edwards' ||
|
||||
this.curve.curve.curve.type === 'mont';
|
||||
return this.keyPair.getPublic('array', compact);
|
||||
};
|
||||
|
||||
KeyPair.prototype.getPrivate = function () {
|
||||
if (this.keyType === enums.publicKey.eddsa) {
|
||||
if (this.curve.keyType === enums.publicKey.eddsa) {
|
||||
return this.keyPair.getSecret();
|
||||
}
|
||||
return this.keyPair.getPrivate().toArray();
|
||||
|
@ -110,15 +102,15 @@ KeyPair.prototype.getPrivate = function () {
|
|||
|
||||
|
||||
async function webSign(curve, hash_algo, message, keyPair) {
|
||||
const l = curve.payloadSize;
|
||||
const len = curve.payloadSize;
|
||||
const key = await webCrypto.importKey(
|
||||
"jwk",
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": webCurves[curve.name],
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray('be', l)), true),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray('be', l)), true),
|
||||
"d": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray('be', l)), true),
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray('be', len)), true),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray('be', len)), true),
|
||||
"d": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray('be', len)), true),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Private Key"
|
||||
},
|
||||
|
@ -141,23 +133,20 @@ async function webSign(curve, hash_algo, message, keyPair) {
|
|||
message
|
||||
));
|
||||
return {
|
||||
r: signature.slice(0, l),
|
||||
s: signature.slice(l, 2 * l)
|
||||
r: signature.slice(0, len),
|
||||
s: signature.slice(len, len << 1)
|
||||
};
|
||||
}
|
||||
|
||||
async function webVerify(curve, hash_algo, { r, s }, message, publicKey) {
|
||||
const l = curve.payloadSize;
|
||||
r = Array(l - r.length).fill(0).concat(r);
|
||||
s = Array(l - s.length).fill(0).concat(s);
|
||||
const signature = new Uint8Array(r.concat(s)).buffer;
|
||||
const len = curve.payloadSize;
|
||||
const key = await webCrypto.importKey(
|
||||
"jwk",
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": webCurves[curve.name],
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(publicKey.getX().toArray('be', l)), true),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(publicKey.getY().toArray('be', l)), true),
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(publicKey.getX().toArray('be', len)), true),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(publicKey.getY().toArray('be', len)), true),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Public Key"
|
||||
},
|
||||
|
@ -170,6 +159,10 @@ async function webVerify(curve, hash_algo, { r, s }, message, publicKey) {
|
|||
["verify"]
|
||||
);
|
||||
|
||||
r = [].concat(Array(len - r.length).fill(0), r);
|
||||
s = [].concat(Array(len - s.length).fill(0), s);
|
||||
const signature = new Uint8Array([].concat(r, s)).buffer;
|
||||
|
||||
return webCrypto.verify(
|
||||
{
|
||||
"name": 'ECDSA',
|
||||
|
@ -182,58 +175,88 @@ async function webVerify(curve, hash_algo, { r, s }, message, publicKey) {
|
|||
);
|
||||
}
|
||||
|
||||
|
||||
async function nodeSign(curve, hash_algo, message, keyPair) {
|
||||
console.log({
|
||||
"kty": "EC",
|
||||
"crv": webCurves[curve.name],
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray())),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray())),
|
||||
"d": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray())),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Private Key"
|
||||
});
|
||||
|
||||
const key = jwkToPem(
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": webCurves[curve.name],
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getX().toArray())),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPublic().getY().toArray())),
|
||||
"d": util.Uint8Array_to_b64(new Uint8Array(keyPair.getPrivate().toArray())),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Private Key"
|
||||
},
|
||||
{ private: true }
|
||||
);
|
||||
|
||||
const sign = nodeCrypto.createSign(enums.read(enums.hash, hash_algo));
|
||||
sign.write(message);
|
||||
sign.end();
|
||||
const signature = await ECDSASignature.decode(sign.sign(key), 'der');
|
||||
return {
|
||||
r: signature.r.toArray(),
|
||||
s: signature.s.toArray()
|
||||
};
|
||||
|
||||
const key = ECPrivateKey.encode({
|
||||
version: 1,
|
||||
parameters: curve.oid,
|
||||
privateKey: keyPair.getPrivate().toArray(),
|
||||
publicKey: { unused: 0, data: keyPair.getPublic().encode() }
|
||||
}, 'pem', {
|
||||
label: 'EC PRIVATE KEY'
|
||||
});
|
||||
|
||||
return ECDSASignature.decode(sign.sign(key), 'der');
|
||||
}
|
||||
|
||||
async function nodeVerify(curve, hash_algo, { r, s }, message, publicKey) {
|
||||
const signature = ECDSASignature.encode({ r: new BN(r), s: new BN(s) }, 'der');
|
||||
const key = jwkToPem(
|
||||
{
|
||||
"kty": "EC",
|
||||
"crv": webCurves[curve.name],
|
||||
"x": util.Uint8Array_to_b64(new Uint8Array(publicKey.getX().toArray())),
|
||||
"y": util.Uint8Array_to_b64(new Uint8Array(publicKey.getY().toArray())),
|
||||
"use": "sig",
|
||||
"kid": "ECDSA Public Key"
|
||||
},
|
||||
{ private: false }
|
||||
);
|
||||
|
||||
const verify = nodeCrypto.createVerify(enums.read(enums.hash, hash_algo));
|
||||
verify.write(message);
|
||||
verify.end();
|
||||
const result = await verify.verify(key, signature);
|
||||
return result;
|
||||
|
||||
const key = SubjectPublicKeyInfo.encode({
|
||||
algorithm: {
|
||||
algorithm: [1, 2, 840, 10045, 2, 1],
|
||||
parameters: curve.oid
|
||||
},
|
||||
subjectPublicKey: { unused: 0, data: publicKey.encode() }
|
||||
}, 'pem', {
|
||||
label: 'PUBLIC KEY'
|
||||
});
|
||||
|
||||
const signature = ECDSASignature.encode({
|
||||
r: new BN(r), s: new BN(s)
|
||||
}, 'der');
|
||||
|
||||
try {
|
||||
return verify.verify(key, signature);
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const asn1 = nodeCrypto ? require('asn1.js') : undefined;
|
||||
|
||||
const ECDSASignature = nodeCrypto ?
|
||||
asn1.define('ECDSASignature', function() {
|
||||
this.seq().obj(
|
||||
this.key('r').int(),
|
||||
this.key('s').int()
|
||||
);
|
||||
}) : undefined;
|
||||
|
||||
const ECParameters = nodeCrypto ?
|
||||
asn1.define('ECParameters', function() {
|
||||
this.choice({
|
||||
namedCurve: this.objid()
|
||||
});
|
||||
}) : undefined;
|
||||
|
||||
const ECPrivateKey = nodeCrypto ?
|
||||
asn1.define('ECPrivateKey', function() {
|
||||
this.seq().obj(
|
||||
this.key('version').int(),
|
||||
this.key('privateKey').octstr(),
|
||||
this.key('parameters').explicit(0).optional().any(),
|
||||
this.key('publicKey').explicit(1).optional().bitstr()
|
||||
);
|
||||
}) : undefined;
|
||||
|
||||
const AlgorithmIdentifier = nodeCrypto ?
|
||||
asn1.define('AlgorithmIdentifier', function() {
|
||||
this.seq().obj(
|
||||
this.key('algorithm').objid(),
|
||||
this.key('parameters').optional().any()
|
||||
);
|
||||
}) : undefined;
|
||||
|
||||
const SubjectPublicKeyInfo = nodeCrypto ?
|
||||
asn1.define('SubjectPublicKeyInfo', function() {
|
||||
this.seq().obj(
|
||||
this.key('algorithm').use(AlgorithmIdentifier),
|
||||
this.key('subjectPublicKey').bitstr()
|
||||
);
|
||||
}) : undefined;
|
||||
|
|
|
@ -41,7 +41,9 @@ import util from '../util';
|
|||
*/
|
||||
export default function MPI(data) {
|
||||
/** An implementation dependent integer */
|
||||
if (BN.isBN(data)) {
|
||||
if (data instanceof MPI) {
|
||||
this.data = data.data;
|
||||
} else if (BN.isBN(data)) {
|
||||
this.fromBN(data);
|
||||
} else if (util.isUint8Array(data)) {
|
||||
this.fromUint8Array(data);
|
||||
|
|
|
@ -18,8 +18,17 @@
|
|||
/**
|
||||
* Wrapper to an OID value
|
||||
*
|
||||
* An object identifier type from
|
||||
* {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}.
|
||||
* {@link https://tools.ietf.org/html/rfc6637#section-11|RFC6637, section 11}:
|
||||
* The sequence of octets in the third column is the result of applying
|
||||
* the Distinguished Encoding Rules (DER) to the ASN.1 Object Identifier
|
||||
* with subsequent truncation. The truncation removes the two fields of
|
||||
* encoded Object Identifier. The first omitted field is one octet
|
||||
* representing the Object Identifier tag, and the second omitted field
|
||||
* is the length of the Object Identifier body. For example, the
|
||||
* complete ASN.1 DER encoding for the NIST P-256 curve OID is "06 08 2A
|
||||
* 86 48 CE 3D 03 01 07", from which the first entry in the table above
|
||||
* is constructed by omitting the first two octets. Only the truncated
|
||||
* sequence of octets is the valid representation of a curve OID.
|
||||
* @requires util
|
||||
* @requires enums
|
||||
* @module type/oid
|
||||
|
@ -33,15 +42,16 @@ import enums from '../enums';
|
|||
*/
|
||||
function OID(oid) {
|
||||
if (oid instanceof OID) {
|
||||
oid = oid.oid;
|
||||
} else if (typeof oid === 'undefined') {
|
||||
oid = '';
|
||||
} else if (util.isArray(oid)) {
|
||||
oid = util.Uint8Array_to_str(oid);
|
||||
} else if (util.isUint8Array(oid)) {
|
||||
oid = util.Uint8Array_to_str(oid);
|
||||
this.oid = oid.oid;
|
||||
} else if (util.isArray(oid) ||
|
||||
util.isUint8Array(oid)) {
|
||||
if (oid[0] === 0x06) { // DER encoded oid byte array
|
||||
oid = oid.slice(2);
|
||||
}
|
||||
this.oid = util.Uint8Array_to_str(oid);
|
||||
} else {
|
||||
this.oid = '';
|
||||
}
|
||||
this.oid = oid;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
10
src/util.js
10
src/util.js
|
@ -18,10 +18,12 @@
|
|||
/**
|
||||
* This object contains utility functions
|
||||
* @requires config
|
||||
* @requires encoding/base64
|
||||
* @module util
|
||||
*/
|
||||
|
||||
import config from './config';
|
||||
import b64 from './encoding/base64';
|
||||
|
||||
export default {
|
||||
|
||||
|
@ -157,8 +159,8 @@ export default {
|
|||
* @return {Uint8Array} An array of 8-bit integers
|
||||
*/
|
||||
b64_to_Uint8Array: function (base64) {
|
||||
const str = atob(base64.replace(/\-/g, '+').replace(/_/g, '/'));
|
||||
return this.str_to_Uint8Array(str);
|
||||
// atob(base64.replace(/\-/g, '+').replace(/_/g, '/'));
|
||||
return b64.decode(base64.replace(/\-/g, '+').replace(/_/g, '/'));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -168,8 +170,8 @@ export default {
|
|||
* @return {String} Base-64 encoded string
|
||||
*/
|
||||
Uint8Array_to_b64: function (bytes, url) {
|
||||
const base64 = btoa(this.Uint8Array_to_str(bytes));
|
||||
return url ? base64.replace(/\+/g, '-').replace(/\//g, '_') : base64;
|
||||
// btoa(this.Uint8Array_to_str(bytes)).replace(/\+/g, '-').replace(/\//g, '_');
|
||||
return b64.encode(bytes, url).replace('\n', '');
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -144,7 +144,7 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
it('Creating curve from oid', function (done) {
|
||||
const oids = ['2A8648CE3D030107', '2B81040022', '2B81040023', '2B8104000A'];
|
||||
oids.forEach(function (oid) {
|
||||
expect(new elliptic_curves.Curve(openpgp.util.hex_to_str(oid))).to.exist;
|
||||
expect(new elliptic_curves.Curve(oid)).to.exist;
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
@ -173,21 +173,25 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
it('Signature verification', function (done) {
|
||||
const curve = new elliptic_curves.Curve('p256');
|
||||
const key = curve.keyFromPublic(signature_data.pub);
|
||||
expect(key.verify(signature_data.message, signature_data.signature, 8)).to.eventually.be.true;
|
||||
done();
|
||||
expect(
|
||||
key.verify(signature_data.message, signature_data.signature, 8)
|
||||
).to.eventually.be.true.notify(done);
|
||||
});
|
||||
it('Invalid signature', function (done) {
|
||||
const curve = new elliptic_curves.Curve('p256');
|
||||
const key = curve.keyFromPublic(key_data.p256.pub);
|
||||
expect(key.verify(signature_data.message, signature_data.signature, 8)).to.eventually.be.false;
|
||||
done();
|
||||
expect(
|
||||
key.verify(signature_data.message, signature_data.signature, 8)
|
||||
).to.eventually.be.false.notify(done);
|
||||
});
|
||||
it('Signature generation', function () {
|
||||
const curve = new elliptic_curves.Curve('p256');
|
||||
let key = curve.keyFromPrivate(key_data.p256.priv);
|
||||
return key.sign(signature_data.message, 8).then(signature => {
|
||||
key = curve.keyFromPublic(key_data.p256.pub);
|
||||
expect(key.verify(signature_data.message, signature, 8)).to.eventually.be.true;
|
||||
expect(
|
||||
key.verify(signature_data.message, signature, 8)
|
||||
).to.eventually.be.true;
|
||||
});
|
||||
});
|
||||
it('Shared secret generation', function (done) {
|
||||
|
@ -312,7 +316,7 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
return Promise.resolve().then(() => {
|
||||
const curve = new elliptic_curves.Curve(oid);
|
||||
return elliptic_curves.ecdh.decrypt(
|
||||
curve.oid,
|
||||
new openpgp.OID(curve.oid),
|
||||
cipher,
|
||||
hash,
|
||||
new Uint8Array(ephemeral),
|
||||
|
|
|
@ -524,7 +524,7 @@ describe('X25519 Cryptography', function () {
|
|||
|
||||
/* TODO how does GPG2 accept this?
|
||||
it('Should handle little-endian parameters in EdDSA', function () {
|
||||
var pubKey = [
|
||||
const pubKey = [
|
||||
'-----BEGIN PGP PUBLIC KEY BLOCK-----',
|
||||
'Version: OpenPGP.js v3.0.0',
|
||||
'Comment: https://openpgpjs.org',
|
||||
|
@ -539,12 +539,12 @@ describe('X25519 Cryptography', function () {
|
|||
'Gbm1oe83ZB+0aSp5m34YkpHQNb80y8PGFy7nIexiAA==',
|
||||
'=xeG/',
|
||||
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
|
||||
var hi = openpgp.key.readArmored(pubKey).keys[0];
|
||||
const hi = openpgp.key.readArmored(pubKey).keys[0];
|
||||
return hi.verifyPrimaryUser().then(() => {
|
||||
var results = hi.getPrimaryUser();
|
||||
const results = hi.getPrimaryUser();
|
||||
expect(results).to.exist;
|
||||
expect(results.user).to.exist;
|
||||
var user = results.user;
|
||||
const user = results.user;
|
||||
expect(user.selfCertifications[0].verify(
|
||||
hi.primaryKey, {userid: user.userId, key: hi.primaryKey}
|
||||
)).to.eventually.be.true;
|
||||
|
|
Loading…
Reference in New Issue
Block a user