feat: add deno-github-mod.ts, update deno-sshsig-mod.ts
This commit is contained in:
38
libraries/deno-github-mod.ts
Normal file
38
libraries/deno-github-mod.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
getFetchAutoProxyInit,
|
||||||
|
} from "https://hatter.ink/script/fetch/library/deno-fetch-auto-proxy-mod.ts?202501191421";
|
||||||
|
|
||||||
|
export class SshKey {
|
||||||
|
algorithm: string;
|
||||||
|
material: string;
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
algorithm: string,
|
||||||
|
material: string,
|
||||||
|
description: string | undefined,
|
||||||
|
) {
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.material = material;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
static parseSshKey(key: string): SshKey {
|
||||||
|
const keyParts = key.split(/\s+/);
|
||||||
|
if (keyParts.length < 2 || keyParts.length > 3) {
|
||||||
|
throw `Bad SSH key format ${key}`;
|
||||||
|
}
|
||||||
|
return new SshKey(
|
||||||
|
keyParts[0],
|
||||||
|
keyParts[1],
|
||||||
|
(keyParts.length > 2) ? keyParts[2] : undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchKeys(username: string): Promise<Array<SshKey>> {
|
||||||
|
const url = `https://github.com/${username}.keys`;
|
||||||
|
const response = await fetch(url, getFetchAutoProxyInit());
|
||||||
|
const responseText = await response.text();
|
||||||
|
return responseText.trim().split("\n").map((k) => SshKey.parseSshKey(k));
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { crypto } from "jsr:@std/crypto";
|
import { crypto } from "jsr:@std/crypto";
|
||||||
import { decodeBase64 } from "jsr:@std/encoding/base64";
|
import { decodeBase64, encodeBase64 } from "jsr:@std/encoding/base64";
|
||||||
import { encodeBase64Url } from "jsr:@std/encoding/base64url";
|
import { encodeBase64Url } from "jsr:@std/encoding/base64url";
|
||||||
import { decodeHex, encodeHex } from "jsr:@std/encoding/hex";
|
import { decodeHex, encodeHex } from "jsr:@std/encoding/hex";
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ class BinaryReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SshSignature {
|
export class SshSignature {
|
||||||
publicKey: SshPublicKey;
|
publicKey: SshPublicKey;
|
||||||
namespace: string;
|
namespace: string;
|
||||||
hashAlgorithm: string;
|
hashAlgorithm: string;
|
||||||
@@ -257,7 +257,7 @@ class SshSignature {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SshSignatureValue {
|
export class SshSignatureValue {
|
||||||
signatureAlgorithm: string;
|
signatureAlgorithm: string;
|
||||||
ecSignatureR: Uint8Array;
|
ecSignatureR: Uint8Array;
|
||||||
ecSignatureS: Uint8Array;
|
ecSignatureS: Uint8Array;
|
||||||
@@ -330,16 +330,19 @@ class SshSignatureValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SshPublicKey {
|
export class SshPublicKey {
|
||||||
|
raw: Uint8Array;
|
||||||
signatureAlgorithm: string;
|
signatureAlgorithm: string;
|
||||||
algorithm: string;
|
algorithm: string;
|
||||||
publicKeyPoint: Uint8Array;
|
publicKeyPoint: Uint8Array;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
raw: Uint8Array,
|
||||||
signatureAlgorithm: string,
|
signatureAlgorithm: string,
|
||||||
algorithm: string,
|
algorithm: string,
|
||||||
publicKeyPoint: Uint8Array,
|
publicKeyPoint: Uint8Array,
|
||||||
) {
|
) {
|
||||||
|
this.raw = raw;
|
||||||
this.signatureAlgorithm = signatureAlgorithm;
|
this.signatureAlgorithm = signatureAlgorithm;
|
||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
this.publicKeyPoint = publicKeyPoint;
|
this.publicKeyPoint = publicKeyPoint;
|
||||||
@@ -354,12 +357,22 @@ class SshPublicKey {
|
|||||||
throw `Not supported signature algorithm ${signatureAlgorithm} or curve algorithm ${curveAlgorithm}`;
|
throw `Not supported signature algorithm ${signatureAlgorithm} or curve algorithm ${curveAlgorithm}`;
|
||||||
}
|
}
|
||||||
return new SshPublicKey(
|
return new SshPublicKey(
|
||||||
|
buffer,
|
||||||
signatureAlgorithm,
|
signatureAlgorithm,
|
||||||
curveAlgorithm,
|
curveAlgorithm,
|
||||||
publicKeyPoint,
|
publicKeyPoint,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toSshKeyFormat(description?: string | undefined): string {
|
||||||
|
const suffix = description ? ` ${description}` : "";
|
||||||
|
return `${this.signatureAlgorithm} ${this.asRawBase64()}${suffix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
asRawBase64(): string {
|
||||||
|
return encodeBase64(this.raw);
|
||||||
|
}
|
||||||
|
|
||||||
toDer(): Uint8Array {
|
toDer(): Uint8Array {
|
||||||
const writer = new BinaryWriter();
|
const writer = new BinaryWriter();
|
||||||
if (this.algorithm === "nistp256") {
|
if (this.algorithm === "nistp256") {
|
||||||
@@ -395,6 +408,7 @@ class SshPublicKey {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deno-lint-ignore no-explicit-any
|
||||||
toJwk(): any {
|
toJwk(): any {
|
||||||
if (this.publicKeyPoint[0] !== 0x04) {
|
if (this.publicKeyPoint[0] !== 0x04) {
|
||||||
throw `Invalid EC public key point: ${
|
throw `Invalid EC public key point: ${
|
||||||
@@ -509,6 +523,9 @@ WRxFFw==
|
|||||||
const data = new TextDecoder(ENCODING_UTF8).decode(
|
const data = new TextDecoder(ENCODING_UTF8).decode(
|
||||||
decodeBase64("aGVsbG8gaGF0dGVyIDIwMjUK"),
|
decodeBase64("aGVsbG8gaGF0dGVyIDIwMjUK"),
|
||||||
);
|
);
|
||||||
|
console.log(
|
||||||
|
sshSignature.publicKey.toSshKeyFormat(),
|
||||||
|
);
|
||||||
console.log(await sshSignature.verifyString(data));
|
console.log(await sshSignature.verifyString(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user