First upload version 0.0.1
This commit is contained in:
8
node_modules/universal-github-app-jwt/lib/crypto-native.js
generated
vendored
Normal file
8
node_modules/universal-github-app-jwt/lib/crypto-native.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
const { subtle } = globalThis.crypto;
|
||||
|
||||
// no-op, unfortunately there is no way to transform from PKCS8 or OpenSSH to PKCS1 with WebCrypto
|
||||
function convertPrivateKey(privateKey) {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
export { subtle, convertPrivateKey };
|
||||
15
node_modules/universal-github-app-jwt/lib/crypto-node.js
generated
vendored
Normal file
15
node_modules/universal-github-app-jwt/lib/crypto-node.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// this can be removed once we only support Node 20+
|
||||
export { subtle } from "node:crypto";
|
||||
import { createPrivateKey } from "node:crypto";
|
||||
|
||||
import { isPkcs1 } from "./utils.js";
|
||||
|
||||
// no-op, unfortunately there is no way to transform from PKCS8 or OpenSSH to PKCS1 with WebCrypto
|
||||
export function convertPrivateKey(privateKey) {
|
||||
if (!isPkcs1(privateKey)) return privateKey;
|
||||
|
||||
return createPrivateKey(privateKey).export({
|
||||
type: "pkcs8",
|
||||
format: "pem",
|
||||
});
|
||||
}
|
||||
66
node_modules/universal-github-app-jwt/lib/get-token.js
generated
vendored
Normal file
66
node_modules/universal-github-app-jwt/lib/get-token.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// we don't @ts-check here because it chokes crypto which is a global API in modern JS runtime environments
|
||||
|
||||
import {
|
||||
isPkcs1,
|
||||
isOpenSsh,
|
||||
getEncodedMessage,
|
||||
getDERfromPEM,
|
||||
string2ArrayBuffer,
|
||||
base64encode,
|
||||
} from "./utils.js";
|
||||
|
||||
import { subtle, convertPrivateKey } from "#crypto";
|
||||
|
||||
/**
|
||||
* @param {import('../internals').GetTokenOptions} options
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export async function getToken({ privateKey, payload }) {
|
||||
const convertedPrivateKey = convertPrivateKey(privateKey);
|
||||
|
||||
// WebCrypto only supports PKCS#8, unfortunately
|
||||
/* c8 ignore start */
|
||||
if (isPkcs1(convertedPrivateKey)) {
|
||||
throw new Error(
|
||||
"[universal-github-app-jwt] Private Key is in PKCS#1 format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats"
|
||||
);
|
||||
}
|
||||
/* c8 ignore stop */
|
||||
|
||||
// WebCrypto does not support OpenSSH, unfortunately
|
||||
if (isOpenSsh(convertedPrivateKey)) {
|
||||
throw new Error(
|
||||
"[universal-github-app-jwt] Private Key is in OpenSSH format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats"
|
||||
);
|
||||
}
|
||||
|
||||
const algorithm = {
|
||||
name: "RSASSA-PKCS1-v1_5",
|
||||
hash: { name: "SHA-256" },
|
||||
};
|
||||
|
||||
/** @type {import('../internals').Header} */
|
||||
const header = { alg: "RS256", typ: "JWT" };
|
||||
|
||||
const privateKeyDER = getDERfromPEM(convertedPrivateKey);
|
||||
const importedKey = await subtle.importKey(
|
||||
"pkcs8",
|
||||
privateKeyDER,
|
||||
algorithm,
|
||||
false,
|
||||
["sign"]
|
||||
);
|
||||
|
||||
const encodedMessage = getEncodedMessage(header, payload);
|
||||
const encodedMessageArrBuf = string2ArrayBuffer(encodedMessage);
|
||||
|
||||
const signatureArrBuf = await subtle.sign(
|
||||
algorithm.name,
|
||||
importedKey,
|
||||
encodedMessageArrBuf
|
||||
);
|
||||
|
||||
const encodedSignature = base64encode(signatureArrBuf);
|
||||
|
||||
return `${encodedMessage}.${encodedSignature}`;
|
||||
}
|
||||
85
node_modules/universal-github-app-jwt/lib/utils.js
generated
vendored
Normal file
85
node_modules/universal-github-app-jwt/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// we don't @ts-check here because it chokes on atob and btoa which are available in all modern JS runtime environments
|
||||
|
||||
/**
|
||||
* @param {string} privateKey
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPkcs1(privateKey) {
|
||||
return privateKey.includes("-----BEGIN RSA PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} privateKey
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isOpenSsh(privateKey) {
|
||||
return privateKey.includes("-----BEGIN OPENSSH PRIVATE KEY-----");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
export function string2ArrayBuffer(str) {
|
||||
const buf = new ArrayBuffer(str.length);
|
||||
const bufView = new Uint8Array(buf);
|
||||
for (let i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} pem
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
export function getDERfromPEM(pem) {
|
||||
const pemB64 = pem
|
||||
.trim()
|
||||
.split("\n")
|
||||
.slice(1, -1) // Remove the --- BEGIN / END PRIVATE KEY ---
|
||||
.join("");
|
||||
|
||||
const decoded = atob(pemB64);
|
||||
return string2ArrayBuffer(decoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('../internals').Header} header
|
||||
* @param {import('../internals').Payload} payload
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getEncodedMessage(header, payload) {
|
||||
return `${base64encodeJSON(header)}.${base64encodeJSON(payload)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} buffer
|
||||
* @returns {string}
|
||||
*/
|
||||
export function base64encode(buffer) {
|
||||
var binary = "";
|
||||
var bytes = new Uint8Array(buffer);
|
||||
var len = bytes.byteLength;
|
||||
for (var i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
|
||||
return fromBase64(btoa(binary));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} base64
|
||||
* @returns {string}
|
||||
*/
|
||||
function fromBase64(base64) {
|
||||
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string,unknown>} obj
|
||||
* @returns {string}
|
||||
*/
|
||||
function base64encodeJSON(obj) {
|
||||
return fromBase64(btoa(JSON.stringify(obj)));
|
||||
}
|
||||
Reference in New Issue
Block a user