@0xpass/passport
Advanced tools
Comparing version 2.1.4 to 2.1.5
# @0xpass/passport | ||
## 2.1.5 | ||
### Patch Changes | ||
- a7b02b7: Replace Web Crypto API with `node-forge` | ||
## 2.1.4 | ||
@@ -4,0 +10,0 @@ |
@@ -5,14 +5,7 @@ import { Network } from "./types"; | ||
}; | ||
export declare const generateKeyPair: () => Promise<{ | ||
publicKey: string; | ||
privateKey: string; | ||
}>; | ||
export declare const generateAesKey: () => Promise<any>; | ||
export declare const importKey: (keyFormat: any, encryptionKey: any, algo: any, keyUsages: any, extractable?: boolean) => Promise<any>; | ||
export declare const encrypt: (algo: any, key: any, data: any) => Promise<any>; | ||
export declare const decrypt: (algo: any, key: any, data: any) => Promise<any>; | ||
export declare const aesEncrypt: (plainText: string, encryptionKey: BufferSource, keyFormat?: "raw", keyLength?: number) => Promise<string>; | ||
export declare const aesDecrypt: (cipherText: string, encryptionKey: BufferSource, keyFormat?: "raw", keyLength?: number) => Promise<string>; | ||
export declare const rsaEncrypt: (plainText: string, encryptionKey: BufferSource, keyFormat?: "spki", hashName?: "SHA-256") => Promise<string>; | ||
export declare const generateAesKey: () => Promise<ArrayBufferLike>; | ||
export declare function aesEncrypt(plainText: string, encryptionKey: ArrayBuffer): Promise<string>; | ||
export declare function aesDecrypt(encryptedText: string, encryptionKey: ArrayBuffer): Promise<string>; | ||
export declare const rsaEncrypt: (plainText: string, encryptionKey: BufferSource) => Promise<string>; | ||
export declare const pemToBuffer: (pem: string) => ArrayBufferLike; | ||
//# sourceMappingURL=crypto.d.ts.map |
import axios from 'axios'; | ||
import forge from 'node-forge'; | ||
import pkg from 'js-sha3'; | ||
@@ -21,12 +22,2 @@ import elliptic from 'elliptic'; | ||
let cryptoObj; | ||
if (typeof window !== "undefined") { | ||
cryptoObj = window.crypto; | ||
} | ||
else { | ||
(async () => { | ||
const cryptoModule = await import('crypto'); | ||
cryptoObj = cryptoModule.webcrypto; | ||
})(); | ||
} | ||
const ENCLAVE_PUBLIC_KEYS = { | ||
@@ -40,30 +31,41 @@ // TODO: update the public key for mainnet | ||
const generateAesKey = async () => { | ||
const cryptoKey = await cryptoObj.subtle.generateKey({ | ||
name: "AES-GCM", | ||
length: 256, | ||
}, true, ["encrypt", "decrypt"]); | ||
return await cryptoObj.subtle.exportKey("raw", cryptoKey); | ||
}; | ||
const importKey = async (keyFormat, encryptionKey, algo, keyUsages, extractable = false) => { | ||
return cryptoObj.subtle.importKey(keyFormat, encryptionKey, algo, extractable, keyUsages); | ||
}; | ||
const encrypt = async (algo, key, data) => { | ||
try { | ||
return await cryptoObj.subtle.encrypt(algo, key, data); | ||
const key = forge.random.getBytesSync(32); | ||
const byteArray = new Uint8Array(key.length); | ||
for (let i = 0; i < key.length; i++) { | ||
byteArray[i] = key.charCodeAt(i); | ||
} | ||
catch (error) { | ||
console.error("Encryption error:", error); | ||
throw error; | ||
} | ||
return byteArray.buffer; | ||
}; | ||
const decrypt = async (algo, key, data) => { | ||
try { | ||
return await cryptoObj.subtle.decrypt(algo, key, data); | ||
async function aesEncrypt(plainText, encryptionKey) { | ||
const key = forge.util.binary.raw.encode(new Uint8Array(encryptionKey)); | ||
const iv = forge.random.getBytesSync(12); | ||
const cipher = forge.cipher.createCipher("AES-GCM", key); | ||
cipher.start({ iv: iv }); | ||
cipher.update(forge.util.createBuffer(plainText, "utf8")); | ||
cipher.finish(); | ||
const encrypted = cipher.output.getBytes(); | ||
const tag = cipher.mode.tag.getBytes(); | ||
const result = forge.util.encode64(iv + encrypted + tag); | ||
return result; | ||
} | ||
async function aesDecrypt(encryptedText, encryptionKey) { | ||
const input = forge.util.decode64(encryptedText); | ||
const iv = input.slice(0, 12); | ||
const tag = input.slice(-16); | ||
const encrypted = input.slice(12, -16); | ||
const key = forge.util.binary.raw.encode(new Uint8Array(encryptionKey)); | ||
const decipher = forge.cipher.createDecipher("AES-GCM", key); | ||
const ivBuffer = forge.util.createBuffer(iv, "raw"); | ||
const tagBuffer = forge.util.createBuffer(tag, "raw"); | ||
decipher.start({ iv: ivBuffer, tag: tagBuffer }); | ||
decipher.update(forge.util.createBuffer(encrypted, "raw")); | ||
const pass = decipher.finish(); | ||
if (pass) { | ||
return decipher.output.toString(); | ||
} | ||
catch (error) { | ||
console.error("Decryption error:", error); | ||
throw error; | ||
else { | ||
throw new Error("Decryption failed"); | ||
} | ||
}; | ||
const aesEncrypt = async (plainText, encryptionKey, keyFormat = "raw", keyLength = 256) => { | ||
} | ||
const rsaEncrypt = async (plainText, encryptionKey) => { | ||
if (!encryptionKey) { | ||
@@ -74,60 +76,32 @@ throw Error("Encryption key not initialized"); | ||
const data = encoder.encode(plainText); | ||
let cryptoKey; | ||
let encrypted; | ||
try { | ||
cryptoKey = await importKey(keyFormat, encryptionKey, { name: "AES-GCM", length: keyLength }, [ | ||
"encrypt", | ||
]); | ||
const iv = cryptoObj.getRandomValues(new Uint8Array(12)); // Initialization vector | ||
encrypted = await encrypt({ name: "AES-GCM", iv }, cryptoKey, data); | ||
const combined = new Uint8Array(iv.length + encrypted.byteLength); | ||
combined.set(iv, 0); | ||
combined.set(new Uint8Array(encrypted), iv.length); | ||
return btoa(String.fromCharCode.apply(null, combined)); | ||
const pemKey = bufferSourceToPem(encryptionKey); | ||
const publicKey = forge.pki.publicKeyFromPem(pemKey); | ||
encrypted = publicKey.encrypt(forge.util.binary.raw.encode(data), "RSA-OAEP", { | ||
md: forge.md.sha256.create(), | ||
mgf1: { | ||
md: forge.md.sha256.create(), | ||
}, | ||
}); | ||
return forge.util.encode64(encrypted); | ||
} | ||
catch (error) { | ||
console.error("AES-GCM Encryption error:", error); | ||
console.error("RSA-OAEP Encryption error:", error); | ||
throw error; | ||
} | ||
}; | ||
const aesDecrypt = async (cipherText, encryptionKey, keyFormat = "raw", keyLength = 256) => { | ||
if (!encryptionKey) { | ||
throw Error("Encryption key not initialized"); | ||
function bufferSourceToPem(bufferSource) { | ||
let bytes; | ||
if (bufferSource instanceof ArrayBuffer) { | ||
bytes = new Uint8Array(bufferSource); | ||
} | ||
let cryptoKey; | ||
let decryptedData; | ||
try { | ||
const combined = Uint8Array.from(atob(cipherText), (c) => c.charCodeAt(0)); | ||
const iv = combined.slice(0, 12); | ||
const encryptedData = combined.slice(12); | ||
cryptoKey = await importKey(keyFormat, encryptionKey, { name: "AES-GCM", length: keyLength }, [ | ||
"decrypt", | ||
]); | ||
decryptedData = await decrypt({ name: "AES-GCM", iv }, cryptoKey, encryptedData); | ||
const decoder = new TextDecoder(); | ||
return decoder.decode(new Uint8Array(decryptedData)); | ||
else { | ||
bytes = new Uint8Array(bufferSource.buffer, bufferSource.byteOffset, bufferSource.byteLength); | ||
} | ||
catch (error) { | ||
console.error("AES-GCM Decryption error:", error); | ||
throw error; | ||
} | ||
}; | ||
const rsaEncrypt = async (plainText, encryptionKey, keyFormat = "spki", hashName = "SHA-256") => { | ||
if (!encryptionKey) { | ||
throw Error("Encryption key not initialized"); | ||
} | ||
const encoder = new TextEncoder(); | ||
const data = encoder.encode(plainText); | ||
let cryptoKey; | ||
let encrypted; | ||
try { | ||
cryptoKey = await importKey(keyFormat, encryptionKey, { name: "RSA-OAEP", hash: { name: hashName } }, ["encrypt"]); | ||
encrypted = await encrypt({ name: "RSA-OAEP" }, cryptoKey, data); | ||
return btoa(String.fromCharCode.apply(null, new Uint8Array(encrypted))); | ||
} | ||
catch (error) { | ||
console.error("RSA-OAEP Encryption error:", error); | ||
throw error; | ||
} | ||
}; | ||
const binaryString = String.fromCharCode(...bytes); | ||
const base64 = forge.util.encode64(binaryString); | ||
const pem = `-----BEGIN PUBLIC KEY-----\n${base64}\n-----END PUBLIC KEY-----\n`; | ||
return pem; | ||
} | ||
const pemToBuffer = (pem) => { | ||
@@ -134,0 +108,0 @@ const pemHeader = "-----BEGIN PUBLIC KEY-----\n"; |
{ | ||
"name": "@0xpass/passport", | ||
"version": "2.1.4", | ||
"version": "2.1.5", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
import { Network } from "./types"; | ||
import forge from "node-forge"; | ||
let cryptoObj; | ||
if (typeof window !== "undefined") { | ||
cryptoObj = window.crypto; | ||
} else { | ||
(async () => { | ||
const cryptoModule = await import("crypto"); | ||
cryptoObj = cryptoModule.webcrypto; | ||
})(); | ||
} | ||
export const ENCLAVE_PUBLIC_KEYS: { [key in Network]: string } = { | ||
@@ -26,136 +16,57 @@ // TODO: update the public key for mainnet | ||
export const generateKeyPair = async () => { | ||
const keyPair = await cryptoObj.subtle.generateKey( | ||
{ | ||
name: "ECDSA", | ||
namedCurve: "P-256", | ||
}, | ||
true, | ||
["sign", "verify"] | ||
); | ||
const publicKey = await cryptoObj.subtle.exportKey("spki", keyPair.publicKey); | ||
const privateKey = await cryptoObj.subtle.exportKey("pkcs8", keyPair.privateKey); | ||
const publicKeyPem = arrayBufferToPem(publicKey); | ||
const privateKeyPem = arrayBufferToPem(privateKey); | ||
return { publicKey: publicKeyPem, privateKey: privateKeyPem }; | ||
}; | ||
const arrayBufferToPem = (buffer: ArrayBuffer) => { | ||
let binary = ""; | ||
const bytes = new Uint8Array(buffer); | ||
for (let i = 0; i < bytes.byteLength; i++) { | ||
binary += String.fromCharCode(bytes[i]); | ||
} | ||
return window.btoa(binary); | ||
}; | ||
export const generateAesKey = async () => { | ||
const cryptoKey = await cryptoObj.subtle.generateKey( | ||
{ | ||
name: "AES-GCM", | ||
length: 256, | ||
}, | ||
true, | ||
["encrypt", "decrypt"] | ||
); | ||
return await cryptoObj.subtle.exportKey("raw", cryptoKey); | ||
}; | ||
const key = forge.random.getBytesSync(32); | ||
export const importKey = async (keyFormat, encryptionKey, algo, keyUsages, extractable = false) => { | ||
return cryptoObj.subtle.importKey(keyFormat, encryptionKey, algo, extractable, keyUsages); | ||
return cryptoObj.subtle.importKey(keyFormat, encryptionKey, algo, extractable, keyUsages); | ||
}; | ||
export const encrypt = async (algo, key, data) => { | ||
try { | ||
return await cryptoObj.subtle.encrypt(algo, key, data); | ||
} catch (error) { | ||
console.error("Encryption error:", error); | ||
throw error; | ||
const byteArray = new Uint8Array(key.length); | ||
for (let i = 0; i < key.length; i++) { | ||
byteArray[i] = key.charCodeAt(i); | ||
} | ||
}; | ||
export const decrypt = async (algo, key, data) => { | ||
try { | ||
return await cryptoObj.subtle.decrypt(algo, key, data); | ||
} catch (error) { | ||
console.error("Decryption error:", error); | ||
throw error; | ||
} | ||
return byteArray.buffer; | ||
}; | ||
export const aesEncrypt = async ( | ||
plainText: string, | ||
encryptionKey: BufferSource, | ||
keyFormat: "raw" = "raw", | ||
keyLength: number = 256 | ||
) => { | ||
if (!encryptionKey) { | ||
throw Error("Encryption key not initialized"); | ||
} | ||
export async function aesEncrypt(plainText: string, encryptionKey: ArrayBuffer): Promise<string> { | ||
const key = forge.util.binary.raw.encode(new Uint8Array(encryptionKey)); | ||
const iv = forge.random.getBytesSync(12); | ||
const cipher = forge.cipher.createCipher("AES-GCM", key); | ||
const encoder = new TextEncoder(); | ||
const data = encoder.encode(plainText); | ||
let cryptoKey: CryptoKey; | ||
let encrypted: ArrayBuffer; | ||
cipher.start({ iv: iv }); | ||
cipher.update(forge.util.createBuffer(plainText, "utf8")); | ||
cipher.finish(); | ||
try { | ||
cryptoKey = await importKey(keyFormat, encryptionKey, { name: "AES-GCM", length: keyLength }, [ | ||
"encrypt", | ||
]); | ||
const encrypted = cipher.output.getBytes(); | ||
const tag = cipher.mode.tag.getBytes(); | ||
const iv = cryptoObj.getRandomValues(new Uint8Array(12)); // Initialization vector | ||
encrypted = await encrypt({ name: "AES-GCM", iv }, cryptoKey, data); | ||
const result = forge.util.encode64(iv + encrypted + tag); | ||
return result; | ||
} | ||
const combined = new Uint8Array(iv.length + encrypted.byteLength); | ||
combined.set(iv, 0); | ||
combined.set(new Uint8Array(encrypted), iv.length); | ||
export async function aesDecrypt( | ||
encryptedText: string, | ||
encryptionKey: ArrayBuffer | ||
): Promise<string> { | ||
const input = forge.util.decode64(encryptedText); | ||
return btoa(String.fromCharCode.apply(null, combined)); | ||
} catch (error) { | ||
console.error("AES-GCM Encryption error:", error); | ||
throw error; | ||
} | ||
}; | ||
const iv = input.slice(0, 12); | ||
const tag = input.slice(-16); | ||
const encrypted = input.slice(12, -16); | ||
export const aesDecrypt = async ( | ||
cipherText: string, | ||
encryptionKey: BufferSource, | ||
keyFormat: "raw" = "raw", | ||
keyLength: number = 256 | ||
) => { | ||
if (!encryptionKey) { | ||
throw Error("Encryption key not initialized"); | ||
} | ||
let cryptoKey: CryptoKey; | ||
let decryptedData: ArrayBuffer; | ||
const key = forge.util.binary.raw.encode(new Uint8Array(encryptionKey)); | ||
const decipher = forge.cipher.createDecipher("AES-GCM", key); | ||
try { | ||
const combined = Uint8Array.from(atob(cipherText), (c) => c.charCodeAt(0)); | ||
const iv = combined.slice(0, 12); | ||
const encryptedData = combined.slice(12); | ||
const ivBuffer = forge.util.createBuffer(iv, "raw"); | ||
const tagBuffer = forge.util.createBuffer(tag, "raw"); | ||
cryptoKey = await importKey(keyFormat, encryptionKey, { name: "AES-GCM", length: keyLength }, [ | ||
"decrypt", | ||
]); | ||
decipher.start({ iv: ivBuffer, tag: tagBuffer }); | ||
decipher.update(forge.util.createBuffer(encrypted, "raw")); | ||
const pass = decipher.finish(); | ||
decryptedData = await decrypt({ name: "AES-GCM", iv }, cryptoKey, encryptedData); | ||
const decoder = new TextDecoder(); | ||
return decoder.decode(new Uint8Array(decryptedData)); | ||
} catch (error) { | ||
console.error("AES-GCM Decryption error:", error); | ||
throw error; | ||
if (pass) { | ||
return decipher.output.toString(); | ||
} else { | ||
throw new Error("Decryption failed"); | ||
} | ||
}; | ||
} | ||
export const rsaEncrypt = async ( | ||
plainText: string, | ||
encryptionKey: BufferSource, | ||
keyFormat: "spki" = "spki", | ||
hashName: "SHA-256" = "SHA-256" | ||
) => { | ||
export const rsaEncrypt = async (plainText: string, encryptionKey: BufferSource) => { | ||
if (!encryptionKey) { | ||
@@ -168,14 +79,15 @@ throw Error("Encryption key not initialized"); | ||
let cryptoKey: CryptoKey; | ||
let encrypted: ArrayBuffer; | ||
let encrypted: string; | ||
try { | ||
cryptoKey = await importKey( | ||
keyFormat, | ||
encryptionKey, | ||
{ name: "RSA-OAEP", hash: { name: hashName } }, | ||
["encrypt"] | ||
); | ||
encrypted = await encrypt({ name: "RSA-OAEP" }, cryptoKey, data); | ||
return btoa(String.fromCharCode.apply(null, new Uint8Array(encrypted))); | ||
const pemKey = bufferSourceToPem(encryptionKey); | ||
const publicKey = forge.pki.publicKeyFromPem(pemKey); | ||
encrypted = publicKey.encrypt(forge.util.binary.raw.encode(data), "RSA-OAEP", { | ||
md: forge.md.sha256.create(), | ||
mgf1: { | ||
md: forge.md.sha256.create(), | ||
}, | ||
}); | ||
return forge.util.encode64(encrypted); | ||
} catch (error) { | ||
@@ -187,2 +99,15 @@ console.error("RSA-OAEP Encryption error:", error); | ||
function bufferSourceToPem(bufferSource: BufferSource): string { | ||
let bytes: Uint8Array; | ||
if (bufferSource instanceof ArrayBuffer) { | ||
bytes = new Uint8Array(bufferSource); | ||
} else { | ||
bytes = new Uint8Array(bufferSource.buffer, bufferSource.byteOffset, bufferSource.byteLength); | ||
} | ||
const binaryString = String.fromCharCode(...bytes); | ||
const base64 = forge.util.encode64(binaryString); | ||
const pem = `-----BEGIN PUBLIC KEY-----\n${base64}\n-----END PUBLIC KEY-----\n`; | ||
return pem; | ||
} | ||
export const pemToBuffer = (pem: string) => { | ||
@@ -189,0 +114,0 @@ const pemHeader = "-----BEGIN PUBLIC KEY-----\n"; |
import { aesDecrypt, aesEncrypt } from "../crypto"; | ||
import { AES_KEY_ARRAY } from "./environment"; | ||
import { TextEncoder, TextDecoder } from "util"; | ||
global.TextEncoder = TextEncoder; | ||
global.TextDecoder = TextDecoder; | ||
@@ -7,0 +4,0 @@ describe("encryption and decryption", () => { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
92012
1946