Skip to content

Commit

Permalink
Remove dependency on jose
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlia committed Mar 30, 2024
1 parent 86f836e commit 20aa825
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 15 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"redirections",
"rels",
"setext",
"spki",
"subproperty",
"superproperty",
"unfollow",
Expand Down
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Version 0.5.0

To be released.

- Removed dependency on *jose*.

- Added `exportSpki()` function.
- Added `importSpki()` function.


Version 0.4.0
-------------
Expand Down
8 changes: 3 additions & 5 deletions codegen/__snapshots__/class.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { Temporal } from \\"@js-temporal/polyfill\\";
import jsonld from \\"jsonld\\";
import { type LanguageTag, parseLanguageTag }
from \\"@phensley/language-tag\\";
import { exportSPKI, importSPKI } from \\"jose\\";
import { type DocumentLoader, fetchDocumentLoader }
from \\"../runtime/docloader.ts\\";
import { exportSpki, importSpki } from \\"../runtime/key.ts\\";
import { LanguageString } from \\"../runtime/langstr.ts\\";


Expand Down Expand Up @@ -178,7 +178,7 @@ get publicKey(): (CryptoKey | null) {
array = [];
for (const v of this.#_2fE2QMDdg6KFGqa4NEC3TmjApSAD) {
array.push(
{ \\"@value\\": await exportSPKI(v) }
{ \\"@value\\": await exportSpki(v) }
);
}
if (array.length > 0) values[\\"https://w3id.org/security#publicKeyPem\\"] = array;
Expand Down Expand Up @@ -263,9 +263,7 @@ get publicKey(): (CryptoKey | null) {

for (const v of values[\\"https://w3id.org/security#publicKeyPem\\"] ?? []) {
if (v == null) continue;
_2fE2QMDdg6KFGqa4NEC3TmjApSAD.push(await importSPKI<CryptoKey>(v[\\"@value\\"], \\"RS256\\", {
extractable: true
}))
_2fE2QMDdg6KFGqa4NEC3TmjApSAD.push(await importSpki(v[\\"@value\\"]))
}
instance.#_2fE2QMDdg6KFGqa4NEC3TmjApSAD = _2fE2QMDdg6KFGqa4NEC3TmjApSAD;

Expand Down
2 changes: 1 addition & 1 deletion codegen/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ export async function* generateClasses(
yield 'import jsonld from "jsonld";\n';
yield `import { type LanguageTag, parseLanguageTag }
from "@phensley/language-tag";\n`;
yield `import { exportSPKI, importSPKI } from "jose";\n`;
yield `import { type DocumentLoader, fetchDocumentLoader }
from "${runtimePath}/docloader.ts";\n`;
yield `import { exportSpki, importSpki } from "${runtimePath}/key.ts";\n`;
yield `import { LanguageString } from "${runtimePath}/langstr.ts";\n`;
yield "\n\n";
const sorted = sortTopologically(types);
Expand Down
7 changes: 2 additions & 5 deletions codegen/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,17 +199,14 @@ const scalarTypes: Record<string, ScalarType> = {
return `${v} instanceof CryptoKey`;
},
encoder(v) {
return `{ "@value": await exportSPKI(${v}) }`;
return `{ "@value": await exportSpki(${v}) }`;
},
dataCheck(v) {
return `typeof ${v} === "object" && "@value" in ${v}
&& typeof ${v}["@value"] === "string"`;
},
decoder(v) {
// TODO: support other than RSASSA-PKCS1-v1_5:
return `await importSPKI<CryptoKey>(${v}["@value"], "RS256", {
extractable: true
})`;
return `await importSpki(${v}["@value"])`;
},
},
"fedify:units": {
Expand Down
1 change: 0 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"@std/url": "jsr:@std/url@^0.220.1",
"@std/yaml": "jsr:@std/yaml@^0.220.1",
"fast-check": "npm:fast-check@^3.17.0",
"jose": "npm:jose@^5.2.3",
"jsonld": "npm:jsonld@^8.3.2",
"mock_fetch": "https://deno.land/x/[email protected]/mod.ts",
"uri-template-router": "npm:uri-template-router@^0.0.16",
Expand Down
1 change: 0 additions & 1 deletion examples/blog/import_map.g.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"@std/url": "jsr:@std/url@^0.220.1",
"@std/yaml": "jsr:@std/yaml@^0.220.1",
"fast-check": "npm:fast-check@^3.17.0",
"jose": "npm:jose@^5.2.3",
"jsonld": "npm:jsonld@^8.3.2",
"mock_fetch": "https://deno.land/x/[email protected]/mod.ts",
"uri-template-router": "npm:uri-template-router@^0.0.16",
Expand Down
43 changes: 43 additions & 0 deletions runtime/key.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { assertEquals } from "@std/assert";
import { exportJwk, importJwk } from "../httpsig/key.ts";
import { exportSpki, importSpki } from "./key.ts";

// cSpell: disable
const pem = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxsRuvCkgJtflBTl4OVsm\n" +
"nt/J1mQfZasfJtN33dcZ3d1lJroxmgmMu69zjGEAwkNbMQaWNLqC4eogkJaeJ4RR\n" +
"5MHYXkL9nNilVoTkjX5BVit3puzs7XJ7WQnKQgQMI+ezn24GHsZ/v1JIo77lerX5\n" +
"k4HNwTNVt+yaZVQWaOMR3+6FwziQR6kd0VuG9/a9dgAnz2cEoORRC1i4W7IZaB1s\n" +
"Znh1WbHbevlGd72HSXll5rocPIHn8gq6xpBgpHwRphlRsgn4KHaJ6brXDIJjrnQh\n" +
"Ie/YUBOGj/ImSEXhRwlFerKsoAVnZ0Hwbfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2\n" +
"uwIDAQAB\n" +
"-----END PUBLIC KEY-----\n";
// cSpell: enable

const jwk = {
alg: "RS256",
// cSpell: disable
e: "AQAB",
// cSpell: enable
ext: true,
key_ops: ["verify"],
kty: "RSA",
// cSpell: disable
n: "xsRuvCkgJtflBTl4OVsmnt_J1mQfZasfJtN33dcZ3d1lJroxmgmMu69zjGEAwkNbMQaWN" +
"LqC4eogkJaeJ4RR5MHYXkL9nNilVoTkjX5BVit3puzs7XJ7WQnKQgQMI-ezn24GHsZ_v1J" +
"Io77lerX5k4HNwTNVt-yaZVQWaOMR3-6FwziQR6kd0VuG9_a9dgAnz2cEoORRC1i4W7IZa" +
"B1sZnh1WbHbevlGd72HSXll5rocPIHn8gq6xpBgpHwRphlRsgn4KHaJ6brXDIJjrnQhIe_" +
"YUBOGj_ImSEXhRwlFerKsoAVnZ0Hwbfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2uw",
// cSpell: enable
};

Deno.test("importSpki()", async () => {
const key = await importSpki(pem);
assertEquals(await exportJwk(key), jwk);
});

Deno.test("exportSpki()", async () => {
const key = await importJwk(jwk, "public");
const spki = await exportSpki(key);
assertEquals(spki, pem);
});
31 changes: 31 additions & 0 deletions runtime/key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { decodeBase64, encodeBase64 } from "@std/encoding/base64";

/**
* Imports a PEM-SPKI formatted public key.
* @param pem The PEM-SPKI formatted public key.
* @returns The imported public key.
*/
export async function importSpki(pem: string): Promise<CryptoKey> {
pem = pem.replace(/(?:-----(?:BEGIN|END) PUBLIC KEY-----|\s)/g, "");
const spki = decodeBase64(pem);
// TODO: support other than RSASSA-PKCS1-v1_5:
return await crypto.subtle.importKey(
"spki",
spki,
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
true,
["verify"],
);
}

/**
* Exports a public key in PEM-SPKI format.
* @param key The public key to export.
* @returns The exported public key in PEM-SPKI format.
*/
export async function exportSpki(key: CryptoKey): Promise<string> {
const spki = await crypto.subtle.exportKey("spki", key);
let pem = encodeBase64(spki);
pem = (pem.match(/.{1,64}/g) || []).join("\n");
return `-----BEGIN PUBLIC KEY-----\n${pem}\n-----END PUBLIC KEY-----\n`;
}
1 change: 1 addition & 0 deletions runtime/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
* @module
*/
export * from "./docloader.ts";
export * from "./key.ts";
export * from "./langstr.ts";
10 changes: 8 additions & 2 deletions vocab/vocab.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ Deno.test("Person.fromJsonLd()", async () => {
"publicKey": {
"id": "https://todon.eu/users/hongminhee#main-key",
"owner": "https://todon.eu/users/hongminhee",
// cSpell: disable
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxsRuvCkgJtflBTl4OVsm\n" +
"nt/J1mQfZasfJtN33dcZ3d1lJroxmgmMu69zjGEAwkNbMQaWNLqC4eogkJaeJ4RR\n" +
Expand All @@ -275,6 +276,7 @@ Deno.test("Person.fromJsonLd()", async () => {
"Ie/YUBOGj/ImSEXhRwlFerKsoAVnZ0Hwbfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2\n" +
"uwIDAQAB\n" +
"-----END PUBLIC KEY-----\n",
// cSpell: enable
},
}, { documentLoader: mockDocumentLoader });
assertEquals(
Expand All @@ -296,7 +298,11 @@ Deno.test("Key.publicKey", async () => {
kty: "RSA",
alg: "RS256",
// cSpell: disable
n: "xsRuvCkgJtflBTl4OVsmnt_J1mQfZasfJtN33dcZ3d1lJroxmgmMu69zjGEAwkNbMQaWNLqC4eogkJaeJ4RR5MHYXkL9nNilVoTkjX5BVit3puzs7XJ7WQnKQgQMI-ezn24GHsZ_v1JIo77lerX5k4HNwTNVt-yaZVQWaOMR3-6FwziQR6kd0VuG9_a9dgAnz2cEoORRC1i4W7IZaB1sZnh1WbHbevlGd72HSXll5rocPIHn8gq6xpBgpHwRphlRsgn4KHaJ6brXDIJjrnQhIe_YUBOGj_ImSEXhRwlFerKsoAVnZ0Hwbfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2uw",
n: "xsRuvCkgJtflBTl4OVsmnt_J1mQfZasfJtN33dcZ3d1lJroxmgmMu69zjGEAwkNbMQaWN" +
"LqC4eogkJaeJ4RR5MHYXkL9nNilVoTkjX5BVit3puzs7XJ7WQnKQgQMI-ezn24GHsZ_v1J" +
"Io77lerX5k4HNwTNVt-yaZVQWaOMR3-6FwziQR6kd0VuG9_a9dgAnz2cEoORRC1i4W7IZa" +
"B1sZnh1WbHbevlGd72HSXll5rocPIHn8gq6xpBgpHwRphlRsgn4KHaJ6brXDIJjrnQhIe_" +
"YUBOGj_ImSEXhRwlFerKsoAVnZ0Hwbfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2uw",
e: "AQAB",
// cSpell: enable
key_ops: ["verify"],
Expand Down Expand Up @@ -324,7 +330,7 @@ Deno.test("Key.publicKey", async () => {
"Ie/YUBOGj/ImSEXhRwlFerKsoAVnZ0Hwbfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2\n" +
"uwIDAQAB\n" +
// cSpell: enable
"-----END PUBLIC KEY-----",
"-----END PUBLIC KEY-----\n",
type: "CryptographicKey",
});
const loadedKey = await CryptographicKey.fromJsonLd(jsonLd, {
Expand Down

0 comments on commit 20aa825

Please sign in to comment.