Cleaning mpi.js; TODO: store MPI.data as Uint8Array instead of BN
Also improved asynchronousity in packet tests
This commit is contained in:
parent
d40e8fe428
commit
3b912d2fae
|
@ -95,8 +95,7 @@ export default {
|
|||
* @return {String} message, an octet string
|
||||
*/
|
||||
decode: function(EM) {
|
||||
// FIXME
|
||||
// leading zeros truncated by jsbn
|
||||
// leading zeros truncated by bn.js
|
||||
if (EM.charCodeAt(0) !== 0) {
|
||||
EM = String.fromCharCode(0) + EM;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,8 @@ export default {
|
|||
|
||||
/**
|
||||
* Generate a new random private key B bits long with public exponent E
|
||||
* @param {Integer} B RSA bit length
|
||||
* @param {String} E RSA public exponent in hex
|
||||
*/
|
||||
generate: async function(B, E) {
|
||||
let key;
|
||||
|
|
|
@ -42,7 +42,7 @@ import util from '../util';
|
|||
*/
|
||||
export default function MPI(data) {
|
||||
/** An implementation dependent integer */
|
||||
if (data instanceof BN) {
|
||||
if (BN.isBN(data)) {
|
||||
this.fromBN(data);
|
||||
} else if (util.isUint8Array(data)) {
|
||||
this.fromUint8Array(data);
|
||||
|
@ -54,35 +54,27 @@ export default function MPI(data) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Parsing function for a mpi ({@link https://tools.ietf.org/html/rfc4880#section3.2|RFC 4880 3.2}).
|
||||
* @param {Uint8Array} input Payload of mpi data
|
||||
* @param {String} endian Endianness of the payload; 'be' for big-endian or 'le' for little-endian
|
||||
* @return {Integer} Length of data read
|
||||
* Parsing function for a MPI ({@link https://tools.ietf.org/html/rfc4880#section-3.2|RFC 4880 3.2}).
|
||||
* @param {Uint8Array} input Payload of MPI data
|
||||
* @param {String} endian Endianness of the data; 'be' for big-endian or 'le' for little-endian
|
||||
* @return {Integer} Length of data read
|
||||
*/
|
||||
MPI.prototype.read = function (bytes, endian='be') {
|
||||
if (util.isString(bytes)) {
|
||||
bytes = util.str2Uint8Array(bytes);
|
||||
} else {
|
||||
bytes = util.copyUint8Array(bytes);
|
||||
}
|
||||
|
||||
const bits = (bytes[0] << 8) | bytes[1];
|
||||
|
||||
// Additional rules:
|
||||
//
|
||||
// The size of an MPI is ((MPI.length + 7) / 8) + 2 octets.
|
||||
//
|
||||
// The length field of an MPI describes the length starting from its
|
||||
// most significant non-zero bit. Thus, the MPI [00 02 01] is not
|
||||
// formed correctly. It should be [00 01 01].
|
||||
|
||||
// TODO: Verification of this size method! This size calculation as
|
||||
// specified above is not applicable in JavaScript
|
||||
const bytelen = Math.ceil(bits / 8);
|
||||
let payload = bytes.subarray(2, 2 + bytelen);
|
||||
const payload = bytes.subarray(2, 2 + bytelen);
|
||||
|
||||
if (endian === 'le') {
|
||||
payload = Uint8Array.from(payload).reverse();
|
||||
payload.reverse();
|
||||
}
|
||||
const raw = util.Uint8Array2str(payload);
|
||||
this.fromBytes(raw);
|
||||
|
||||
this.fromUint8Array(payload);
|
||||
|
||||
return 2 + bytelen;
|
||||
};
|
||||
|
@ -118,9 +110,6 @@ MPI.prototype.fromString = function (str) {
|
|||
this.data = new BN(util.str2Uint8Array(str));
|
||||
};
|
||||
|
||||
// TODO remove this
|
||||
MPI.prototype.fromBytes = MPI.prototype.fromString;
|
||||
|
||||
MPI.prototype.toBN = function () {
|
||||
return this.data.clone();
|
||||
};
|
||||
|
|
|
@ -378,10 +378,10 @@ describe('API functional testing', function() {
|
|||
|
||||
it('Asymmetric using RSA with eme_pkcs1 padding', function () {
|
||||
const symmKey = util.Uint8Array2str(crypto.generateSessionKey('aes256'));
|
||||
const RSAUnencryptedData = new openpgp.MPI();
|
||||
RSAUnencryptedData.fromBytes(crypto.pkcs1.eme.encode(symmKey, RSApubMPIs[0].byteLength()));
|
||||
const RSAUnencryptedData = crypto.pkcs1.eme.encode(symmKey, RSApubMPIs[0].byteLength())
|
||||
const RSAUnencryptedMPI = new openpgp.MPI(RSAUnencryptedData);
|
||||
return crypto.publicKeyEncrypt(
|
||||
1, RSApubMPIs, RSAUnencryptedData
|
||||
1, RSApubMPIs, RSAUnencryptedMPI
|
||||
).then(RSAEncryptedData => {
|
||||
|
||||
return crypto.publicKeyDecrypt(
|
||||
|
@ -398,11 +398,11 @@ describe('API functional testing', function() {
|
|||
|
||||
it('Asymmetric using Elgamal with eme_pkcs1 padding', function () {
|
||||
const symmKey = util.Uint8Array2str(crypto.generateSessionKey('aes256'));
|
||||
const ElgamalUnencryptedData = new openpgp.MPI();
|
||||
ElgamalUnencryptedData.fromBytes(crypto.pkcs1.eme.encode(symmKey, ElgamalpubMPIs[0].byteLength()));
|
||||
const ElgamalUnencryptedData = crypto.pkcs1.eme.encode(symmKey, ElgamalpubMPIs[0].byteLength());
|
||||
const ElgamalUnencryptedMPI = new openpgp.MPI(ElgamalUnencryptedData);
|
||||
|
||||
return crypto.publicKeyEncrypt(
|
||||
16, ElgamalpubMPIs, ElgamalUnencryptedData
|
||||
16, ElgamalpubMPIs, ElgamalUnencryptedMPI
|
||||
).then(ElgamalEncryptedData => {
|
||||
|
||||
return crypto.publicKeyDecrypt(
|
||||
|
|
|
@ -5,13 +5,6 @@ chai.use(require('chai-as-promised'));
|
|||
|
||||
const expect = chai.expect;
|
||||
|
||||
const bin2bi = function (bytes) {
|
||||
const mpi = new openpgp.MPI();
|
||||
bytes = openpgp.util.bin2str(bytes);
|
||||
mpi.fromBytes(bytes);
|
||||
return mpi.toUint8Array(); // FIXME
|
||||
};
|
||||
|
||||
describe('Elliptic Curve Cryptography', function () {
|
||||
const elliptic_curves = openpgp.crypto.publicKey.elliptic;
|
||||
const key_data = {
|
||||
|
@ -219,9 +212,9 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
return ecdsa.verify(
|
||||
oid,
|
||||
hash,
|
||||
{r: bin2bi(r), s: bin2bi(s)},
|
||||
{r: new Uint8Array(r), s: new Uint8Array(s)},
|
||||
message,
|
||||
bin2bi(pub)
|
||||
new Uint8Array(pub)
|
||||
);
|
||||
};
|
||||
const secp256k1_dummy_value = new Uint8Array([
|
||||
|
@ -297,8 +290,8 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
it('Sign and verify message', function () {
|
||||
const curve = elliptic_curves.get('p521');
|
||||
return curve.genKeyPair().then(keyPair => {
|
||||
const keyPublic = bin2bi(keyPair.getPublic());
|
||||
const keyPrivate = bin2bi(keyPair.getPrivate());
|
||||
const keyPublic = new Uint8Array(keyPair.getPublic());
|
||||
const keyPrivate = new Uint8Array(keyPair.getPrivate());
|
||||
const oid = curve.oid;
|
||||
const message = p384_message;
|
||||
return elliptic_curves.ecdsa.sign(oid, 10, message, keyPrivate).then(signature => {
|
||||
|
@ -321,9 +314,9 @@ describe('Elliptic Curve Cryptography', function () {
|
|||
curve.oid,
|
||||
cipher,
|
||||
hash,
|
||||
bin2bi(ephemeral),
|
||||
new Uint8Array(ephemeral),
|
||||
data,
|
||||
bin2bi(priv),
|
||||
new Uint8Array(priv),
|
||||
fingerprint
|
||||
);
|
||||
});
|
||||
|
|
|
@ -204,7 +204,7 @@ describe("Packet", function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('Secret key packet (reading, unencrypted)', function(done) {
|
||||
it('Secret key packet (reading, unencrypted)', function() {
|
||||
const armored_key =
|
||||
'-----BEGIN PGP PRIVATE KEY BLOCK-----\n' +
|
||||
'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
|
||||
|
@ -239,17 +239,14 @@ describe("Packet", function() {
|
|||
enc.sessionKeyAlgorithm = 'aes256';
|
||||
enc.publicKeyId.bytes = '12345678';
|
||||
|
||||
enc.encrypt(key).then(() => {
|
||||
|
||||
enc.decrypt(key).then(() => {
|
||||
|
||||
return enc.encrypt(key).then(() => {
|
||||
return enc.decrypt(key).then(() => {
|
||||
expect(stringify(enc.sessionKey)).to.equal(stringify(secret));
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Public key encrypted packet (reading, GPG)', function(done) {
|
||||
it('Public key encrypted packet (reading, GPG)', function() {
|
||||
const armored_key =
|
||||
'-----BEGIN PGP PRIVATE KEY BLOCK-----\n' +
|
||||
'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
|
||||
|
@ -304,17 +301,16 @@ describe("Packet", function() {
|
|||
const msg = new openpgp.packet.List();
|
||||
msg.read(openpgp.armor.decode(armored_msg).data);
|
||||
|
||||
msg[0].decrypt(key).then(() => {
|
||||
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
||||
return msg[0].decrypt(key).then(() => {
|
||||
return msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
||||
|
||||
const text = stringify(msg[1].packets[0].packets[0].data);
|
||||
|
||||
expect(text).to.equal('Hello world!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Sym encrypted session key reading/writing', function(done) {
|
||||
it('Sym. encrypted session key reading/writing', function(done) {
|
||||
const passphrase = 'hello';
|
||||
const algo = 'aes256';
|
||||
|
||||
|
@ -346,7 +342,7 @@ describe("Packet", function() {
|
|||
done();
|
||||
});
|
||||
|
||||
it('Secret key encryption/decryption test', function(done) {
|
||||
it('Secret key encryption/decryption test', function() {
|
||||
const armored_msg =
|
||||
'-----BEGIN PGP MESSAGE-----\n' +
|
||||
'Version: GnuPG v2.0.19 (GNU/Linux)\n' +
|
||||
|
@ -367,13 +363,12 @@ describe("Packet", function() {
|
|||
const msg = new openpgp.packet.List();
|
||||
msg.read(openpgp.armor.decode(armored_msg).data);
|
||||
|
||||
msg[0].decrypt(key).then(() => {
|
||||
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
||||
return msg[0].decrypt(key).then(() => {
|
||||
return msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
|
||||
|
||||
const text = stringify(msg[1].packets[0].packets[0].data);
|
||||
|
||||
expect(text).to.equal('Hello world!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user