mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 05:32:09 +03:00
125 lines
3.7 KiB
TypeScript
125 lines
3.7 KiB
TypeScript
// Loaded from https://deno.land/x/god_crypto@v1.4.3/src/rsa/export_key.ts
|
|
|
|
|
|
import type { RSAKeyParams } from "./common.ts";
|
|
import { bignum_to_byte } from "../helper.ts";
|
|
import { encode } from "./../../src/utility/encode.ts";
|
|
|
|
function ber_size_bytes(size: number): number[] {
|
|
// The BER Length
|
|
// The second component in the TLV structure of a BER element is the length.
|
|
// This specifies the size in bytes of the encoded value. For the most part,
|
|
// this uses a straightforward binary encoding of the integer value
|
|
// (for example, if the encoded value is five bytes long, then it is encoded as
|
|
// 00000101 binary, or 0x05 hex), but if the value is longer than 127 bytes then
|
|
// it is necessary to use multiple bytes to encode the length. In that case, the
|
|
// first byte has the leftmost bit set to one and the remaining seven bits are
|
|
// used to specify the number of bytes required to encode the full length. For example,
|
|
// if there are 500 bytes in the length (hex 0x01F4), then the encoded length will actually
|
|
// consist of three bytes: 82 01 F4.
|
|
//
|
|
// Note that there is an alternate form for encoding the length called the indefinite form.
|
|
// In this mechanism, only a part of the length is given at a time, similar to the chunked encoding
|
|
// that is available in HTTP 1.1. However, this form is not used in LDAP, as specified in RFC 2251
|
|
// section 5.1.
|
|
// https://docs.oracle.com/cd/E19476-01/821-0510/def-basic-encoding-rules.html
|
|
|
|
if (size <= 127) return [size];
|
|
|
|
const bytes = [];
|
|
while (size > 0) {
|
|
bytes.push(size & 0xff);
|
|
size = size >> 8;
|
|
}
|
|
|
|
bytes.reverse();
|
|
return [0x80 + bytes.length, ...bytes];
|
|
}
|
|
|
|
function add_line_break(base64_str: string): string {
|
|
const lines = [];
|
|
for (let i = 0; i < base64_str.length; i += 64) {
|
|
lines.push(base64_str.substr(i, 64));
|
|
}
|
|
|
|
return lines.join("\n");
|
|
}
|
|
|
|
function ber_generate_integer_list(order: number[][]) {
|
|
let content: number[] = [];
|
|
|
|
for (const item of order) {
|
|
if ((item[0] & 0x80) > 0) {
|
|
content = content.concat(
|
|
[0x02, ...ber_size_bytes(item.length + 1), 0x0, ...item],
|
|
);
|
|
} else {
|
|
content = content.concat(
|
|
[0x02, ...ber_size_bytes(item.length), ...item],
|
|
);
|
|
}
|
|
}
|
|
|
|
return content;
|
|
}
|
|
|
|
export function rsa_export_pkcs8_public(key: RSAKeyParams) {
|
|
const n = bignum_to_byte(key.n);
|
|
const e = bignum_to_byte(key.e || 0n);
|
|
|
|
// deno-fmt-ignore
|
|
const other = [0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00];
|
|
|
|
// Key sequence
|
|
const content = ber_generate_integer_list([n, e]);
|
|
const keySequence = [
|
|
0x30,
|
|
...ber_size_bytes(content.length),
|
|
...content,
|
|
];
|
|
|
|
// Bitstring
|
|
const bitString = [
|
|
0x03,
|
|
...ber_size_bytes(keySequence.length + 1),
|
|
0x00,
|
|
...keySequence,
|
|
];
|
|
|
|
const ber = [
|
|
0x30,
|
|
...ber_size_bytes(other.length + bitString.length),
|
|
...other,
|
|
...bitString,
|
|
];
|
|
|
|
return "-----BEGIN PUBLIC KEY-----\n" +
|
|
add_line_break(encode.binary(ber).base64()) +
|
|
"\n-----END PUBLIC KEY-----\n";
|
|
}
|
|
|
|
export function rsa_export_pkcs8_private(key: RSAKeyParams) {
|
|
const n = bignum_to_byte(key.n);
|
|
const e = bignum_to_byte(key.e || 0n);
|
|
const d = bignum_to_byte(key.d || 0n);
|
|
const q = bignum_to_byte(key.q || 0n);
|
|
const p = bignum_to_byte(key.p || 0n);
|
|
const dp = bignum_to_byte(key.dp || 0n);
|
|
const dq = bignum_to_byte(key.dq || 0n);
|
|
const qi = bignum_to_byte(key.qi || 0n);
|
|
|
|
const content = ber_generate_integer_list([n, e, d, p, q, dp, dq, qi]);
|
|
|
|
const ber = encode.binary([
|
|
0x30,
|
|
...ber_size_bytes(content.length + 3),
|
|
0x02,
|
|
0x01,
|
|
0x00,
|
|
...content,
|
|
]).base64();
|
|
|
|
return "-----BEGIN RSA PRIVATE KEY-----\n" + add_line_break(ber) +
|
|
"\n-----END RSA PRIVATE KEY-----\n";
|
|
}
|