This commit is contained in:
Patrick Roumanoff 2018-02-13 17:41:00 +01:00
parent 4846fadc83
commit 63133c72e8
6 changed files with 115 additions and 142 deletions

View file

@ -1,23 +1,11 @@
{ {
"env": { "extends": ["airbnb-base", "prettier"],
"browser": true, "rules": {
"commonjs": true, "quotes": ["warn", "double"],
"es6": true, "no-param-reassign": ["error", { "props": false }]
"node": true },
}, "env": {
"parserOptions": { "browser": true,
"ecmaFeatures": { "node": true
"jsx": true }
}, }
"sourceType": "module"
},
"rules": {
"no-const-assign": "warn",
"no-this-before-super": "warn",
"no-undef": "warn",
"no-unreachable": "warn",
"no-unused-vars": "warn",
"constructor-super": "warn",
"valid-typeof": "warn"
}
}

View file

@ -1,30 +1,31 @@
//adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-08#appendix-C // adapted from https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-08#appendix-C
function base64urlEncode(arg) { function base64urlEncode(arg) {
var s = window.btoa(arg); // Regular base64 encoder const step1 = window.btoa(arg); // Regular base64 encoder
s = s.split("=")[0]; // Remove any trailing '='s const step2 = step1.split("=")[0]; // Remove any trailing '='s
s = s.replace(/\+/g, "-"); // 62nd char of encoding const step3 = step2.replace(/\+/g, "-"); // 62nd char of encoding
s = s.replace(/\//g, "_"); // 63rd char of encoding const step4 = step3.replace(/\//g, "_"); // 63rd char of encoding
return s; return step4;
} }
function base64urlDecode(s) { function base64urlDecode(s) {
s = s.replace(/-/g, "+"); // 62nd char of encoding const step1 = s.replace(/-/g, "+"); // 62nd char of encoding
s = s.replace(/_/g, "/"); // 63rd char of encoding const step2 = step1.replace(/_/g, "/"); // 63rd char of encoding
switch (s.length % 4) { // Pad with trailing '='s let step3 = step2;
switch (step2.length % 4) { // Pad with trailing '='s
case 0: // No pad chars in this case case 0: // No pad chars in this case
break; break;
case 2: // Two pad chars case 2: // Two pad chars
s += "=="; step3 += "==";
break; break;
case 3: // One pad char case 3: // One pad char
s += "="; step3 += "=";
break; break;
default: default:
throw "Illegal base64url string!"; throw new Error("Illegal base64url string!");
} }
return window.atob(s); // Regular base64 decoder return window.atob(step3); // Regular base64 decoder
} }
module = window.module || {}; const module = window.module || {};
module.exports = { base64urlDecode, base64urlEncode }; module.exports = { base64urlDecode, base64urlEncode };

View file

@ -3,6 +3,7 @@
<head> <head>
<title>js-keygen</title> <title>js-keygen</title>
<scrip>module = {};</scrip>
<script src="base64url.js"></script> <script src="base64url.js"></script>
<script src="ssh-util.js"></script> <script src="ssh-util.js"></script>
<script src="js-keygen-ui.js"></script> <script src="js-keygen-ui.js"></script>

View file

@ -1,26 +1,25 @@
var extractable = true; /* global encodePrivateKey, encodePublicKey */
var encodePrivateKey, encodePublicKey; const extractable = true;
function wrap(text, len) { function wrap(text, len) {
var length = len || 72, const length = len || 72;
i, let result = "";
result = ""; for (let i = 0; i < text.length; i += length) {
for (i = 0; i < text.length; i += length) { result += text.slice(i, i + length);
result += text.slice(i, i + length) + "\n"; result += "\n";
} }
return result; return result;
} }
function rsaPrivateKey(key) { function rsaPrivateKey(key) {
return "-----BEGIN RSA PRIVATE KEY-----\n" + key + "-----END RSA PRIVATE KEY-----"; return `-----BEGIN RSA PRIVATE KEY-----\n${key}-----END RSA PRIVATE KEY-----`;
} }
function arrayBufferToBase64(buffer) { function arrayBufferToBase64(buffer) {
var binary = "", let binary = "";
i; const bytes = new Uint8Array(buffer);
var bytes = new Uint8Array(buffer); const len = bytes.byteLength;
var len = bytes.byteLength; for (let i = 0; i < len; i += 1) {
for (i = 0; i < len; i += 1) {
binary += String.fromCharCode(bytes[i]); binary += String.fromCharCode(bytes[i]);
} }
return window.btoa(binary); return window.btoa(binary);
@ -31,24 +30,23 @@ function generateKeyPair(alg, size, name) {
.generateKey( .generateKey(
{ {
name: "RSASSA-PKCS1-v1_5", name: "RSASSA-PKCS1-v1_5",
modulusLength: 2048, //can be 1024, 2048, or 4096 modulusLength: 2048, // can be 1024, 2048, or 4096
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: { name: "SHA-1" }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512" hash: { name: "SHA-1" }, // can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
}, },
extractable, extractable,
["sign", "verify"] ["sign", "verify"]
) )
.then(key => { .then(key => {
var privateKey = window.crypto.subtle const privateKey = window.crypto.subtle
.exportKey("jwk", key.privateKey) .exportKey("jwk", key.privateKey)
.then(encodePrivateKey) .then(encodePrivateKey)
.then(wrap) .then(wrap)
.then(rsaPrivateKey); .then(rsaPrivateKey);
var publicKey = window.crypto.subtle.exportKey("jwk", key.publicKey).then(jwk => encodePublicKey(jwk, name)); const publicKey = window.crypto.subtle.exportKey("jwk", key.publicKey).then(jwk => encodePublicKey(jwk, name));
return Promise.all([privateKey, publicKey]); return Promise.all([privateKey, publicKey]);
}); });
} }
module = window.module || {};
module.exportKey = { arrayBufferToBase64, generateKeyPair }; module.exportKey = { arrayBufferToBase64, generateKeyPair };

View file

@ -1,4 +1,5 @@
var base64urlDecode; /* eslint no-bitwise: 0 */
/* global base64urlDecode */
function arrayToString(a) { function arrayToString(a) {
return String.fromCharCode.apply(null, a); return String.fromCharCode.apply(null, a);
@ -21,25 +22,24 @@ function arrayToPem(a) {
} }
function arrayToLen(a) { function arrayToLen(a) {
var result = 0, let result = 0;
i; for (let i = 0; i < a.length; i += 1) {
for (i = 0; i < a.length; i += 1) {
result = result * 256 + a[i]; result = result * 256 + a[i];
} }
return result; return result;
} }
function integerToOctet(n) { function integerToOctet(n) {
var result = []; const result = [];
for (true; n > 0; n = n >> 8) { for (let i = n; i > 0; i >>= 8) {
result.push(n & 0xff); result.push(i & 0xff);
} }
return result.reverse(); return result.reverse();
} }
function lenToArray(n) { function lenToArray(n) {
var oct = integerToOctet(n), const oct = integerToOctet(n);
i; let i;
for (i = oct.length; i < 4; i += 1) { for (i = oct.length; i < 4; i += 1) {
oct.unshift(0); oct.unshift(0);
} }
@ -47,22 +47,22 @@ function lenToArray(n) {
} }
function decodePublicKey(s) { function decodePublicKey(s) {
var split = s.split(" "); const split = s.split(" ");
var prefix = split[0]; const prefix = split[0];
if (prefix !== "ssh-rsa") { if (prefix !== "ssh-rsa") {
throw "Unknown prefix:" + prefix; throw new Error(`Unknown prefix: ${prefix}`);
} }
var buffer = pemToArray(split[1]); const buffer = pemToArray(split[1]);
var nameLen = arrayToLen(buffer.splice(0, 4)); const nameLen = arrayToLen(buffer.splice(0, 4));
var type = arrayToString(buffer.splice(0, nameLen)); const type = arrayToString(buffer.splice(0, nameLen));
if (type !== "ssh-rsa") { if (type !== "ssh-rsa") {
throw "Unknown key type:" + type; throw new Error(`Unknown key type: ${type}`);
} }
var exponentLen = arrayToLen(buffer.splice(0, 4)); const exponentLen = arrayToLen(buffer.splice(0, 4));
var exponent = buffer.splice(0, exponentLen); const exponent = buffer.splice(0, exponentLen);
var keyLen = arrayToLen(buffer.splice(0, 4)); const keyLen = arrayToLen(buffer.splice(0, 4));
var key = buffer.splice(0, keyLen); const key = buffer.splice(0, keyLen);
return { type: type, exponent: exponent, key: key, name: split[2] }; return { type, exponent, key, name: split[2] };
} }
function checkHighestBit(v) { function checkHighestBit(v) {
@ -83,18 +83,18 @@ function jwkToInternal(jwk) {
} }
function encodePublicKey(jwk, name) { function encodePublicKey(jwk, name) {
var k = jwkToInternal(jwk); const k = jwkToInternal(jwk);
k.name = name; k.name = name;
var keyLenA = lenToArray(k.key.length); const keyLenA = lenToArray(k.key.length);
var exponentLenA = lenToArray(k.exponent.length); const exponentLenA = lenToArray(k.exponent.length);
var typeLenA = lenToArray(k.type.length); const typeLenA = lenToArray(k.type.length);
var array = [].concat(typeLenA, stringToArray(k.type), exponentLenA, k.exponent, keyLenA, k.key); const array = [].concat(typeLenA, stringToArray(k.type), exponentLenA, k.exponent, keyLenA, k.key);
var encoding = arrayToPem(array); const encoding = arrayToPem(array);
return k.type + " " + encoding + " " + k.name; return `${k.type} ${encoding} ${k.name}`;
} }
function asnEncodeLen(n) { function asnEncodeLen(n) {
var result = []; let result = [];
if (n >> 7) { if (n >> 7) {
result = integerToOctet(n); result = integerToOctet(n);
result.unshift(0x80 + result.length); result.unshift(0x80 + result.length);
@ -105,18 +105,17 @@ function asnEncodeLen(n) {
} }
function encodePrivateKey(jwk) { function encodePrivateKey(jwk) {
var order = ["n", "e", "d", "p", "q", "dp", "dq", "qi"]; const order = ["n", "e", "d", "p", "q", "dp", "dq", "qi"];
var list = order.map(prop => { const list = order.map(prop => {
var v = checkHighestBit(stringToArray(base64urlDecode(jwk[prop]))); const v = checkHighestBit(stringToArray(base64urlDecode(jwk[prop])));
var len = asnEncodeLen(v.length); const len = asnEncodeLen(v.length);
return [0x02].concat(len, v); // int tag is 0x02 return [0x02].concat(len, v); // int tag is 0x02
}); });
var seq = [0x02, 0x01, 0x00]; // extra seq for SSH let seq = [0x02, 0x01, 0x00]; // extra seq for SSH
seq = seq.concat.apply(seq, list); seq = seq.concat(...list);
var len = asnEncodeLen(seq.length); const len = asnEncodeLen(seq.length);
var a = [0x30].concat(len, seq); // seq is 0x30 const a = [0x30].concat(len, seq); // seq is 0x30
return arrayToPem(a); return arrayToPem(a);
} }
module = window.module || {};
module.exports = { base64urlToArray, decodePublicKey, encodePublicKey, encodePrivateKey }; module.exports = { base64urlToArray, decodePublicKey, encodePublicKey, encodePrivateKey };

View file

@ -1,9 +1,11 @@
var public_ssh = [ /* global QUnit,arrayToString,pemToArray,arrayToPem,encodePrivateKey,lenToArray,arrayToLen,asnEncodeLen,decodePublicKey,decodePublicKey,encodePublicKey,stringToArray,base64urlDecode,checkHighestBit,integerToOctet */
const publicSsh = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwi36YMW0eDS3NXSAM/Gcs0txeLOcZE0LQmGPYmHX09Fm1FC9AdzvDWQIfwVylqNy8G6X8+pE0TMuWav4rQjtWRls3j43LdrXkfaTZV2PNJH0ki2zaCND3cz46hBR1bSwi3O4LoN0ZHXoC4ZXoMBXKtYEOg+9jS+pE3vu2QSPruiRROTOYYvrjWx0Bwi8DJc90TmNVeqvPjewPAm4qaTdmh96jIgJQq+vAdhDHu90i31Kl3JUF94x6pzFmg8ZyXOv0Py2GtK9c5To3C33FXI8yTm/sf2Bp7fwd3MEGNcdVNqa7Tt0z2u5Jcmsws93SZuj4iVjbR6xqme9EmIa3BTB7 name", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwi36YMW0eDS3NXSAM/Gcs0txeLOcZE0LQmGPYmHX09Fm1FC9AdzvDWQIfwVylqNy8G6X8+pE0TMuWav4rQjtWRls3j43LdrXkfaTZV2PNJH0ki2zaCND3cz46hBR1bSwi3O4LoN0ZHXoC4ZXoMBXKtYEOg+9jS+pE3vu2QSPruiRROTOYYvrjWx0Bwi8DJc90TmNVeqvPjewPAm4qaTdmh96jIgJQq+vAdhDHu90i31Kl3JUF94x6pzFmg8ZyXOv0Py2GtK9c5To3C33FXI8yTm/sf2Bp7fwd3MEGNcdVNqa7Tt0z2u5Jcmsws93SZuj4iVjbR6xqme9EmIa3BTB7 name",
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuew50MaphQgiuM6H7zxMspNojI2Ujf77MuWlAjmw1JxcTkfE7JKzV+9fqmESJNtnZSr3+I2dxQhJ72jttrz+2dFt9ol91muTPWzKrA8XXIBH2o7sEJ+QB8/q7S03d+Zgw6tlo+qdXLOWcKqL5MJhYwzTFEdGTSMF00cBFadcpDq1xFPygGTHRa7m3pK723nGz7TMGWmtBK2bHx+Zlp7geLK/7hl+NRG1lTyIbtdkP2T4Y81Z0bhz9kNHroUei3MFD6HvN93qMJWl3/LZZzTb++1BedNeybGKqbtsB3xp0v3c6bQy49wR3RwrAwL03AKbCwTawAufSeoXyRI+rtgZ/ name", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuew50MaphQgiuM6H7zxMspNojI2Ujf77MuWlAjmw1JxcTkfE7JKzV+9fqmESJNtnZSr3+I2dxQhJ72jttrz+2dFt9ol91muTPWzKrA8XXIBH2o7sEJ+QB8/q7S03d+Zgw6tlo+qdXLOWcKqL5MJhYwzTFEdGTSMF00cBFadcpDq1xFPygGTHRa7m3pK723nGz7TMGWmtBK2bHx+Zlp7geLK/7hl+NRG1lTyIbtdkP2T4Y81Z0bhz9kNHroUei3MFD6HvN93qMJWl3/LZZzTb++1BedNeybGKqbtsB3xp0v3c6bQy49wR3RwrAwL03AKbCwTawAufSeoXyRI+rtgZ/ name",
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpNNtjZeldPuJ5ZgcjO4i6eSJb6kiuf1sULOoWaW9acwSxAfqrmN6Hn7VGg3GK3kSKJUmBKMsF2u+ECajVBec+OTMlbL7oZrYNl2neUYsI7O0G/8lpozZjADYu8CaMqVSAeTa3ORga9Ht/qgCpqXIyEcTsFSbZ45hhaZF0fXQ0GHDCkV/ylBduQHxheCe1SPBSWIO2BwqSlGx/Q76lkL/BnGdcx7xVi3h2yNbEGxqzFuPK75VADZfWria4x09rTqvu41GWIyqzFcbB7BxNImVNh6WVk/qKTcXbfWwH8ck9Cd5bX9g36QaImZ6tW8i/bl3o75bGgP2hSWpsNx8CMVn9 name", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpNNtjZeldPuJ5ZgcjO4i6eSJb6kiuf1sULOoWaW9acwSxAfqrmN6Hn7VGg3GK3kSKJUmBKMsF2u+ECajVBec+OTMlbL7oZrYNl2neUYsI7O0G/8lpozZjADYu8CaMqVSAeTa3ORga9Ht/qgCpqXIyEcTsFSbZ45hhaZF0fXQ0GHDCkV/ylBduQHxheCe1SPBSWIO2BwqSlGx/Q76lkL/BnGdcx7xVi3h2yNbEGxqzFuPK75VADZfWria4x09rTqvu41GWIyqzFcbB7BxNImVNh6WVk/qKTcXbfWwH8ck9Cd5bX9g36QaImZ6tW8i/bl3o75bGgP2hSWpsNx8CMVn9 name",
]; ];
var public_ssh_decoded = [ const publicSshDecoded = [
{ {
type: "ssh-rsa", type: "ssh-rsa",
exponent: [1, 0, 1], exponent: [1, 0, 1],
@ -270,7 +272,7 @@ var public_ssh_decoded = [
}, },
]; ];
var jwk_public = { const jwkPublic = {
alg: "RS1", alg: "RS1",
e: "AQAB", e: "AQAB",
ext: true, ext: true,
@ -280,7 +282,7 @@ var jwk_public = {
"3PWJ6uDsFPgQo67of3IYw0Svyq95SNh9GS-2gorv68GxWIYYeAShaG_UtTf8mvf6u-VIUr54Re2FoLc78ICR3nRhFH5D1_fNaP9hkMAHBqaJ8ATiq4d7-PfeXTCi0yY0qfWkGjuPtOC3IK7WmnEkiA5qUVpy0oHFPiqoAyNynWJRDFJka00JEpM1QFyF1Tz3PEGp0XlFnClY48iJG9UqXlDgaysnG3ro2sDm8ftva0IjX1Sp7Z9FyWQci-yOYfST00wKHQd7z5-Eo3cTd5M0BhcVXeR0gprdK1TTDLZLznFJQ36HYwrUFEXvTyme6vkZfNPRb0z8KPq5Gs7dujE_cw", "3PWJ6uDsFPgQo67of3IYw0Svyq95SNh9GS-2gorv68GxWIYYeAShaG_UtTf8mvf6u-VIUr54Re2FoLc78ICR3nRhFH5D1_fNaP9hkMAHBqaJ8ATiq4d7-PfeXTCi0yY0qfWkGjuPtOC3IK7WmnEkiA5qUVpy0oHFPiqoAyNynWJRDFJka00JEpM1QFyF1Tz3PEGp0XlFnClY48iJG9UqXlDgaysnG3ro2sDm8ftva0IjX1Sp7Z9FyWQci-yOYfST00wKHQd7z5-Eo3cTd5M0BhcVXeR0gprdK1TTDLZLznFJQ36HYwrUFEXvTyme6vkZfNPRb0z8KPq5Gs7dujE_cw",
}; };
var jwk_private = { const jwkPrivate = {
kty: "RSA", kty: "RSA",
kid: "juliet@capulet.lit", kid: "juliet@capulet.lit",
use: "enc", use: "enc",
@ -301,76 +303,60 @@ var jwk_private = {
"lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqqabu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0oYu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8", "lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqqabu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0oYu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8",
}; };
var tags = { QUnit.test("array to PEM", assert => {
SEQUENCE: 0x30, const a = [1, 2, 3];
INTEGER: 0x02, const p = arrayToPem(a);
BIT_STRING: 0x03, const a2 = pemToArray(p);
OCTET_STRING: 0x04,
NULL: 0x05,
OBJECT_IDENTIFIER: 0x06,
SET: 0x11,
PrintableString: 0x13,
T61String: 0x14,
IA5String: 0x16,
UTCTime: 0x17,
};
QUnit.test("array to PEM", function(assert) {
var a = [1, 2, 3];
var p = arrayToPem(a);
var a2 = pemToArray(p);
assert.deepEqual(a2, a, "can you count?"); assert.deepEqual(a2, a, "can you count?");
}); });
QUnit.test("array to String", function(assert) { QUnit.test("array to String", assert => {
var a = "ssh-rsa".split("").map(function(c) { const a = "ssh-rsa".split("").map(c => c.charCodeAt());
return c.charCodeAt();
});
assert.equal(arrayToString(pemToArray(arrayToPem(a))), "ssh-rsa"); assert.equal(arrayToString(pemToArray(arrayToPem(a))), "ssh-rsa");
}); });
QUnit.test("lenToArray", function(assert) { QUnit.test("lenToArray", assert => {
var a = 66051; const a = 66051;
assert.deepEqual(lenToArray(a), [0, 1, 2, 3]); assert.deepEqual(lenToArray(a), [0, 1, 2, 3]);
}); });
QUnit.test("arrayToLen", function(assert) { QUnit.test("arrayToLen", assert => {
var a = [0, 1, 2, 3]; const a = [0, 1, 2, 3];
assert.deepEqual(arrayToLen(a), 66051); assert.deepEqual(arrayToLen(a), 66051);
}); });
public_ssh.forEach(function(public, index) { publicSsh.forEach((pub, index) => {
QUnit.test("decoding ssh public key " + index, function(assert) { QUnit.test(`decoding ssh public key ${index}`, assert => {
var key = decodePublicKey(public); const key = decodePublicKey(pub);
assert.equal(key.type, "ssh-rsa", "type"); assert.equal(key.type, "ssh-rsa", "type");
assert.equal(key.name, "name", "name"); assert.equal(key.name, "name", "name");
if (index === 0) { if (index === 0) {
assert.deepEqual(key.key, public_ssh_decoded[0].key, "key"); assert.deepEqual(key.key, publicSshDecoded[0].key, "key");
} }
}); });
}); });
QUnit.test("Encoding ssh public key", function(assert) { QUnit.test("Encoding ssh public key", assert => {
var result = encodePublicKey(jwk_public, "name"); const result = encodePublicKey(jwkPublic, "name");
assert.equal( assert.equal(
result, result,
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc9Ynq4OwU+BCjruh/chjDRK/Kr3lI2H0ZL7aCiu/rwbFYhhh4BKFob9S1N/ya9/q75UhSvnhF7YWgtzvwgJHedGEUfkPX981o/2GQwAcGponwBOKrh3v4995dMKLTJjSp9aQaO4+04LcgrtaacSSIDmpRWnLSgcU+KqgDI3KdYlEMUmRrTQkSkzVAXIXVPPc8QanReUWcKVjjyIkb1SpeUOBrKycbeujawObx+29rQiNfVKntn0XJZByL7I5h9JPTTAodB3vPn4SjdxN3kzQGFxVd5HSCmt0rVNMMtkvOcUlDfodjCtQURe9PKZ7q+Rl809FvTPwo+rkazt26MT9z name" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc9Ynq4OwU+BCjruh/chjDRK/Kr3lI2H0ZL7aCiu/rwbFYhhh4BKFob9S1N/ya9/q75UhSvnhF7YWgtzvwgJHedGEUfkPX981o/2GQwAcGponwBOKrh3v4995dMKLTJjSp9aQaO4+04LcgrtaacSSIDmpRWnLSgcU+KqgDI3KdYlEMUmRrTQkSkzVAXIXVPPc8QanReUWcKVjjyIkb1SpeUOBrKycbeujawObx+29rQiNfVKntn0XJZByL7I5h9JPTTAodB3vPn4SjdxN3kzQGFxVd5HSCmt0rVNMMtkvOcUlDfodjCtQURe9PKZ7q+Rl809FvTPwo+rkazt26MT9z name"
); );
}); });
QUnit.test("base64url", function(assert) { QUnit.test("base64url", assert => {
var result = stringToArray(base64urlDecode(jwk_public.n)); const result = stringToArray(base64urlDecode(jwkPublic.n));
assert.equal(result.length, 256); assert.equal(result.length, 256);
}); });
QUnit.test("high bit", function(assert) { QUnit.test("high bit", assert => {
assert.deepEqual(checkHighestBit([0x80]), [0x00, 0x80]); assert.deepEqual(checkHighestBit([0x80]), [0x00, 0x80]);
assert.deepEqual(checkHighestBit([0x0f]), [0x0f]); assert.deepEqual(checkHighestBit([0x0f]), [0x0f]);
}); });
QUnit.test("jwk", function(assert) { QUnit.test("jwk", assert => {
var sshkey = encodePublicKey(jwk_public, "name"); const sshkey = encodePublicKey(jwkPublic, "name");
assert.deepEqual(stringToArray(base64urlDecode(jwk_public.e)), [1, 0, 1]); assert.deepEqual(stringToArray(base64urlDecode(jwkPublic.e)), [1, 0, 1]);
assert.equal( assert.equal(
sshkey, sshkey,
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc9Ynq4OwU+BCjruh/chjDRK/Kr3lI2H0ZL7aCiu/rwbFYhhh4BKFob9S1N/ya9/q75UhSvnhF7YWgtzvwgJHedGEUfkPX981o/2GQwAcGponwBOKrh3v4995dMKLTJjSp9aQaO4+04LcgrtaacSSIDmpRWnLSgcU+KqgDI3KdYlEMUmRrTQkSkzVAXIXVPPc8QanReUWcKVjjyIkb1SpeUOBrKycbeujawObx+29rQiNfVKntn0XJZByL7I5h9JPTTAodB3vPn4SjdxN3kzQGFxVd5HSCmt0rVNMMtkvOcUlDfodjCtQURe9PKZ7q+Rl809FvTPwo+rkazt26MT9z name" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc9Ynq4OwU+BCjruh/chjDRK/Kr3lI2H0ZL7aCiu/rwbFYhhh4BKFob9S1N/ya9/q75UhSvnhF7YWgtzvwgJHedGEUfkPX981o/2GQwAcGponwBOKrh3v4995dMKLTJjSp9aQaO4+04LcgrtaacSSIDmpRWnLSgcU+KqgDI3KdYlEMUmRrTQkSkzVAXIXVPPc8QanReUWcKVjjyIkb1SpeUOBrKycbeujawObx+29rQiNfVKntn0XJZByL7I5h9JPTTAodB3vPn4SjdxN3kzQGFxVd5HSCmt0rVNMMtkvOcUlDfodjCtQURe9PKZ7q+Rl809FvTPwo+rkazt26MT9z name"
@ -382,9 +368,9 @@ QUnit.test("jwk", function(assert) {
{ len: 0x104, octet: [0x01, 0x04] }, { len: 0x104, octet: [0x01, 0x04] },
{ len: 0xff32, octet: [0xff, 0x32] }, { len: 0xff32, octet: [0xff, 0x32] },
{ len: 0x1000000, octet: [1, 0, 0, 0] }, { len: 0x1000000, octet: [1, 0, 0, 0] },
{ len: 0x7fffffff, octet: [0x7f, 0xff, 0xff, 0xff] }, //biggest one { len: 0x7fffffff, octet: [0x7f, 0xff, 0xff, 0xff] }, // biggest one
].forEach(function(t) { ].forEach(t => {
QUnit.test("Integer to Octet:" + t.len, function(assert) { QUnit.test(`Integer to Octet: ${t.len}`, assert => {
assert.deepEqual(integerToOctet(t.len), t.octet, t.len); assert.deepEqual(integerToOctet(t.len), t.octet, t.len);
}); });
}); });
@ -395,14 +381,14 @@ QUnit.test("jwk", function(assert) {
{ len: 0x134, asn: [0x80 + 2, 0x01, 0x34] }, { len: 0x134, asn: [0x80 + 2, 0x01, 0x34] },
{ len: 0x12345, asn: [0x80 + 3, 0x01, 0x23, 0x45] }, { len: 0x12345, asn: [0x80 + 3, 0x01, 0x23, 0x45] },
{ len: 0x123456, asn: [0x80 + 3, 0x12, 0x34, 0x56] }, { len: 0x123456, asn: [0x80 + 3, 0x12, 0x34, 0x56] },
].forEach(function(t) { ].forEach(t => {
QUnit.test("ASN.1 Len Writing:" + t.len, function(assert) { QUnit.test(`ASN.1 Len Writing: ${t.len}`, assert => {
assert.deepEqual(asnEncodeLen(t.len), t.asn, t.len); assert.deepEqual(asnEncodeLen(t.len), t.asn, t.len);
}); });
}); });
QUnit.test("encodePrivateKey", function(assert) { QUnit.test("encodePrivateKey", assert => {
var encoded = encodePrivateKey(jwk_private); encodePrivateKey(jwkPrivate);
console.log(encoded); // console.log(encoded);
assert.ok(true); assert.ok(true);
}); });