summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills/_crypto/crypto_browserify/public_encrypt')
-rw-r--r--ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mgf.js22
-rw-r--r--ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mod.js15
-rw-r--r--ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/private_decrypt.js111
-rw-r--r--ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/public_encrypt.js104
-rw-r--r--ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/with_public.js15
-rw-r--r--ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/xor.js11
6 files changed, 278 insertions, 0 deletions
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mgf.js b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mgf.js
new file mode 100644
index 000000000..5bb41f896
--- /dev/null
+++ b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mgf.js
@@ -0,0 +1,22 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright 2017 Calvin Metcalf. All rights reserved. MIT license.
+
+import { createHash } from "internal:deno_node/polyfills/internal/crypto/hash.ts";
+import { Buffer } from "internal:deno_node/polyfills/buffer.ts";
+
+export default function (seed, len) {
+ let t = Buffer.alloc(0);
+ let i = 0;
+ let c;
+ while (t.length < len) {
+ c = i2ops(i++);
+ t = Buffer.concat([t, createHash("sha1").update(seed).update(c).digest()]);
+ }
+ return t.slice(0, len);
+}
+
+function i2ops(c) {
+ const out = Buffer.allocUnsafe(4);
+ out.writeUInt32BE(c, 0);
+ return out;
+}
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mod.js b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mod.js
new file mode 100644
index 000000000..a91197aef
--- /dev/null
+++ b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/mod.js
@@ -0,0 +1,15 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright 2017 Calvin Metcalf. All rights reserved. MIT license.
+
+import { publicEncrypt } from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/public_encrypt.js";
+import { privateDecrypt } from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/private_decrypt.js";
+
+export { privateDecrypt, publicEncrypt };
+
+export function privateEncrypt(key, buf) {
+ return publicEncrypt(key, buf, true);
+}
+
+export function publicDecrypt(key, buf) {
+ return privateDecrypt(key, buf, true);
+}
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/private_decrypt.js b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/private_decrypt.js
new file mode 100644
index 000000000..9b485b3db
--- /dev/null
+++ b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/private_decrypt.js
@@ -0,0 +1,111 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright 2017 Calvin Metcalf. All rights reserved. MIT license.
+
+import parseKeys from "internal:deno_node/polyfills/_crypto/crypto_browserify/parse_asn1/mod.js";
+import { createHash } from "internal:deno_node/polyfills/internal/crypto/hash.ts";
+import mgf from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/mgf.js";
+import { xor } from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/xor.js";
+import { BN } from "internal:deno_node/polyfills/_crypto/crypto_browserify/bn.js/bn.js";
+import { withPublic } from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/with_public.js";
+import crt from "internal:deno_node/polyfills/_crypto/crypto_browserify/browserify_rsa.js";
+import { Buffer } from "internal:deno_node/polyfills/buffer.ts";
+
+export function privateDecrypt(privateKey, enc, reverse) {
+ let padding;
+ if (privateKey.padding) {
+ padding = privateKey.padding;
+ } else if (reverse) {
+ padding = 1;
+ } else {
+ padding = 4;
+ }
+
+ const key = parseKeys(privateKey);
+ const k = key.modulus.byteLength();
+ if (enc.length > k || new BN(enc).cmp(key.modulus) >= 0) {
+ throw new Error("decryption error");
+ }
+ let msg;
+ if (reverse) {
+ msg = withPublic(new BN(enc), key);
+ } else {
+ msg = crt(enc, key);
+ }
+ const zBuffer = Buffer.alloc(k - msg.length);
+ msg = Buffer.concat([zBuffer, msg], k);
+ if (padding === 4) {
+ return oaep(key, msg);
+ } else if (padding === 1) {
+ return pkcs1(key, msg, reverse);
+ } else if (padding === 3) {
+ return msg;
+ } else {
+ throw new Error("unknown padding");
+ }
+}
+
+function oaep(key, msg) {
+ const k = key.modulus.byteLength();
+ const iHash = createHash("sha1").update(Buffer.alloc(0)).digest();
+ const hLen = iHash.length;
+ if (msg[0] !== 0) {
+ throw new Error("decryption error");
+ }
+ const maskedSeed = msg.slice(1, hLen + 1);
+ const maskedDb = msg.slice(hLen + 1);
+ const seed = xor(maskedSeed, mgf(maskedDb, hLen));
+ const db = xor(maskedDb, mgf(seed, k - hLen - 1));
+ if (compare(iHash, db.slice(0, hLen))) {
+ throw new Error("decryption error");
+ }
+ let i = hLen;
+ while (db[i] === 0) {
+ i++;
+ }
+ if (db[i++] !== 1) {
+ throw new Error("decryption error");
+ }
+ return db.slice(i);
+}
+
+function pkcs1(_key, msg, reverse) {
+ const p1 = msg.slice(0, 2);
+ let i = 2;
+ let status = 0;
+ while (msg[i++] !== 0) {
+ if (i >= msg.length) {
+ status++;
+ break;
+ }
+ }
+ const ps = msg.slice(2, i - 1);
+
+ if (
+ (p1.toString("hex") !== "0002" && !reverse) ||
+ (p1.toString("hex") !== "0001" && reverse)
+ ) {
+ status++;
+ }
+ if (ps.length < 8) {
+ status++;
+ }
+ if (status) {
+ throw new Error("decryption error");
+ }
+ return msg.slice(i);
+}
+function compare(a, b) {
+ a = Buffer.from(a);
+ b = Buffer.from(b);
+ let dif = 0;
+ let len = a.length;
+ if (a.length !== b.length) {
+ dif++;
+ len = Math.min(a.length, b.length);
+ }
+ let i = -1;
+ while (++i < len) {
+ dif += a[i] ^ b[i];
+ }
+ return dif;
+}
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/public_encrypt.js b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/public_encrypt.js
new file mode 100644
index 000000000..9642128ba
--- /dev/null
+++ b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/public_encrypt.js
@@ -0,0 +1,104 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright 2017 Calvin Metcalf. All rights reserved. MIT license.
+
+import parseKeys from "internal:deno_node/polyfills/_crypto/crypto_browserify/parse_asn1/mod.js";
+import { randomBytes } from "internal:deno_node/polyfills/_crypto/crypto_browserify/randombytes.ts";
+import { createHash } from "internal:deno_node/polyfills/internal/crypto/hash.ts";
+import mgf from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/mgf.js";
+import { xor } from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/xor.js";
+import { BN } from "internal:deno_node/polyfills/_crypto/crypto_browserify/bn.js/bn.js";
+import { withPublic } from "internal:deno_node/polyfills/_crypto/crypto_browserify/public_encrypt/with_public.js";
+import crt from "internal:deno_node/polyfills/_crypto/crypto_browserify/browserify_rsa.js";
+import { Buffer } from "internal:deno_node/polyfills/buffer.ts";
+
+export function publicEncrypt(publicKey, msg, reverse) {
+ let padding;
+ if (publicKey.padding) {
+ padding = publicKey.padding;
+ } else if (reverse) {
+ padding = 1;
+ } else {
+ padding = 4;
+ }
+ const key = parseKeys(publicKey);
+ let paddedMsg;
+ if (padding === 4) {
+ paddedMsg = oaep(key, msg);
+ } else if (padding === 1) {
+ paddedMsg = pkcs1(key, msg, reverse);
+ } else if (padding === 3) {
+ paddedMsg = new BN(msg);
+ if (paddedMsg.cmp(key.modulus) >= 0) {
+ throw new Error("data too long for modulus");
+ }
+ } else {
+ throw new Error("unknown padding");
+ }
+ if (reverse) {
+ return crt(paddedMsg, key);
+ } else {
+ return withPublic(paddedMsg, key);
+ }
+}
+
+function oaep(key, msg) {
+ const k = key.modulus.byteLength();
+ const mLen = msg.length;
+ const iHash = createHash("sha1").update(Buffer.alloc(0)).digest();
+ const hLen = iHash.length;
+ const hLen2 = 2 * hLen;
+ if (mLen > k - hLen2 - 2) {
+ throw new Error("message too long");
+ }
+ const ps = Buffer.alloc(k - mLen - hLen2 - 2);
+ const dblen = k - hLen - 1;
+ const seed = randomBytes(hLen);
+ const maskedDb = xor(
+ Buffer.concat([iHash, ps, Buffer.alloc(1, 1), msg], dblen),
+ mgf(seed, dblen),
+ );
+ const maskedSeed = xor(seed, mgf(maskedDb, hLen));
+ return new BN(Buffer.concat([Buffer.alloc(1), maskedSeed, maskedDb], k));
+}
+function pkcs1(key, msg, reverse) {
+ const mLen = msg.length;
+ const k = key.modulus.byteLength();
+ if (mLen > k - 11) {
+ throw new Error("message too long");
+ }
+ let ps;
+ if (reverse) {
+ ps = Buffer.alloc(k - mLen - 3, 0xff);
+ } else {
+ ps = nonZero(k - mLen - 3);
+ }
+ return new BN(
+ Buffer.concat([
+ Buffer.from([
+ 0,
+ reverse ? 1 : 2,
+ ]),
+ ps,
+ Buffer.alloc(1),
+ msg,
+ ], k),
+ );
+}
+function nonZero(len) {
+ const out = Buffer.allocUnsafe(len);
+ let i = 0;
+ let cache = randomBytes(len * 2);
+ let cur = 0;
+ let num;
+ while (i < len) {
+ if (cur === cache.length) {
+ cache = randomBytes(len * 2);
+ cur = 0;
+ }
+ num = cache[cur++];
+ if (num) {
+ out[i++] = num;
+ }
+ }
+ return out;
+}
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/with_public.js b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/with_public.js
new file mode 100644
index 000000000..5e94c7bc9
--- /dev/null
+++ b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/with_public.js
@@ -0,0 +1,15 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright 2017 Calvin Metcalf. All rights reserved. MIT license.
+
+import { BN } from "internal:deno_node/polyfills/_crypto/crypto_browserify/bn.js/bn.js";
+import { Buffer } from "internal:deno_node/polyfills/buffer.ts";
+
+export function withPublic(paddedMsg, key) {
+ return Buffer.from(
+ paddedMsg
+ .toRed(BN.mont(key.modulus))
+ .redPow(new BN(key.publicExponent))
+ .fromRed()
+ .toArray(),
+ );
+}
diff --git a/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/xor.js b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/xor.js
new file mode 100644
index 000000000..25c4b8a40
--- /dev/null
+++ b/ext/node/polyfills/_crypto/crypto_browserify/public_encrypt/xor.js
@@ -0,0 +1,11 @@
+// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
+// Copyright 2017 Calvin Metcalf. All rights reserved. MIT license.
+
+export function xor(a, b) {
+ const len = a.length;
+ let i = -1;
+ while (++i < len) {
+ a[i] ^= b[i];
+ }
+ return a;
+}