Unverified Commit 00944b1b authored by Hong Minhee's avatar Hong Minhee
Browse files

`importPkcs1()` function

parent 1d000223
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@
    "phensley",
    "Pico",
    "Pixelfed",
    "PKCS",
    "popd",
    "poppanator",
    "proto",
+7 −0
Original line number Diff line number Diff line
@@ -8,6 +8,13 @@ Version 1.5.0

To be released.

 -  Fedify now accepts PEM-PKCS#1 besides PEM-SPKI for RSA public keys.
    [[#209]]

     -  Added `importPkcs1()` function.

[#209]: https://github.com/fedify-dev/fedify/issues/209


Version 1.4.1
-------------
+20 −3
Original line number Diff line number Diff line
@@ -5,11 +5,12 @@ import {
  exportMultibaseKey,
  exportSpki,
  importMultibaseKey,
  importPkcs1,
  importSpki,
} from "./key.ts";

// cSpell: disable
const rsaPem = "-----BEGIN PUBLIC KEY-----\n" +
const rsaSpki = "-----BEGIN PUBLIC KEY-----\n" +
  "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxsRuvCkgJtflBTl4OVsm\n" +
  "nt/J1mQfZasfJtN33dcZ3d1lJroxmgmMu69zjGEAwkNbMQaWNLqC4eogkJaeJ4RR\n" +
  "5MHYXkL9nNilVoTkjX5BVit3puzs7XJ7WQnKQgQMI+ezn24GHsZ/v1JIo77lerX5\n" +
@@ -20,6 +21,17 @@ const rsaPem = "-----BEGIN PUBLIC KEY-----\n" +
  "-----END PUBLIC KEY-----\n";
// cSpell: enable

// cSpell: disable
const rsaPkcs1 = "-----BEGIN RSA PUBLIC KEY-----\n" +
  "MIIBCgKCAQEAxsRuvCkgJtflBTl4OVsmnt/J1mQfZasfJtN33dcZ3d1lJroxmgmM\n" +
  "u69zjGEAwkNbMQaWNLqC4eogkJaeJ4RR5MHYXkL9nNilVoTkjX5BVit3puzs7XJ7\n" +
  "WQnKQgQMI+ezn24GHsZ/v1JIo77lerX5k4HNwTNVt+yaZVQWaOMR3+6FwziQR6kd\n" +
  "0VuG9/a9dgAnz2cEoORRC1i4W7IZaB1sZnh1WbHbevlGd72HSXll5rocPIHn8gq6\n" +
  "xpBgpHwRphlRsgn4KHaJ6brXDIJjrnQhIe/YUBOGj/ImSEXhRwlFerKsoAVnZ0Hw\n" +
  "bfa46qk44TAt8CyoPMWmpK6pt0ng4pQ2uwIDAQAB\n" +
  "-----END RSA PUBLIC KEY-----\n";
// cSpell: enable

const rsaJwk = {
  alg: "RS256",
  // cSpell: disable
@@ -67,7 +79,7 @@ const ed25519Multibase = "z6MksHj1MJnidCtDiyYW9ugNFftoX9fLK4bornTxmMZ6X7vq";
// cSpell: enable

test("importSpki()", async () => {
  const rsaKey = await importSpki(rsaPem);
  const rsaKey = await importSpki(rsaSpki);
  assertEquals(await exportJwk(rsaKey), rsaJwk);

  const ed25519Key = await importSpki(ed25519Pem);
@@ -77,13 +89,18 @@ test("importSpki()", async () => {
test("exportSpki()", async () => {
  const rsaKey = await importJwk(rsaJwk, "public");
  const rsaSpki = await exportSpki(rsaKey);
  assertEquals(rsaSpki, rsaPem);
  assertEquals(rsaSpki, rsaSpki);

  const ed25519Key = await importJwk(ed25519Jwk, "public");
  const ed25519Spki = await exportSpki(ed25519Key);
  assertEquals(ed25519Spki, ed25519Pem);
});

test("importPkcs1()", async () => {
  const rsaKey = await importPkcs1(rsaPkcs1);
  assertEquals(await exportJwk(rsaKey), rsaJwk);
});

test("importMultibase()", async () => {
  const rsaKey = await importMultibaseKey(rsaMultibase);
  assertEquals(await exportJwk(rsaKey), rsaJwk);
+16 −1
Original line number Diff line number Diff line
import { createPublicKey } from "node:crypto";
import { concat } from "@std/bytes/concat";
import { decodeBase64, encodeBase64 } from "@std/encoding/base64";
import { decodeBase64Url } from "@std/encoding/base64url";
@@ -6,6 +5,7 @@ import { decodeHex } from "@std/encoding/hex";
import { Integer, Sequence } from "asn1js";
import { decode, encode } from "multibase";
import { addPrefix, getCodeFromData, rmPrefix } from "multicodec";
import { createPublicKey } from "node:crypto";
import { PublicKeyInfo } from "pkijs";
import { validateCryptoKey } from "../sig/key.ts";

@@ -65,6 +65,19 @@ export async function exportSpki(key: CryptoKey): Promise<string> {
  return `-----BEGIN PUBLIC KEY-----\n${pem}\n-----END PUBLIC KEY-----\n`;
}

/**
 * Imports a PEM-PKCS#1 formatted public key.
 * @param pem The PEM-PKCS#1 formatted public key.
 * @returns The imported public key.
 * @throws {TypeError} If the key is invalid or unsupported.
 * @since 1.5.0
 */
export function importPkcs1(pem: string): Promise<CryptoKey> {
  const key = createPublicKey({ key: pem, format: "pem", type: "pkcs1" });
  const spki = key.export({ type: "spki", format: "pem" }) as string;
  return importSpki(spki);
}

/**
 * Imports a [Multibase]-encoded public key.
 *
@@ -153,3 +166,5 @@ export async function exportMultibaseKey(key: CryptoKey): Promise<string> {
  const encoded = encode("base58btc", prefixed);
  return new TextDecoder().decode(encoded);
}

// cSpell: ignore multicodec pkijs