swc/crates/swc_bundler/tests/.cache/deno/584d22e957080d2df6b83c75e3ee64a7682b71ae.ts
2021-11-09 20:42:49 +09:00

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";
}