UNPKG

@antigane/encryption

Version:

encryption with Lattice-based Cryptography

140 lines (138 loc) 4.29 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { AntiganeEncryption: () => AntiganeEncryption, createEncryptionService: () => createEncryptionService }); module.exports = __toCommonJS(index_exports); var AntiganeEncryption = class { m; n; q; A; s; e; constructor(m, n, q = 2053) { this.m = m; this.n = n; this.q = q; this.A = []; this.s = []; this.e = []; } mod(x, q) { let result = x % q; return result >= 0 ? result : result + q; } getSecureRandom(max) { const array = new Uint32Array(1); crypto.getRandomValues(array); return this.mod(array[0], max); } defineA() { this.A = Array(this.n).fill(0).map( () => Array(this.m).fill(0).map(() => this.getSecureRandom(this.q)) ); } defineE() { this.e = Array(this.m).fill(0).map(() => this.mod(this.getSecureRandom(10), this.q)); } async generateHash(message) { const encoder = new TextEncoder(); const data = encoder.encode(message); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map((byte) => this.mod(byte, this.q)); } async sVector(password) { const hashValues = await this.generateHash(password); this.s = hashValues.slice(0, this.n); while (this.s.length < this.n) { this.s.push(this.s[this.s.length % hashValues.length]); } } calculateB() { let tempAS = Array(this.A.length).fill(null).map(() => Array(this.A[0].length).fill(0)); for (let i = 0; i < this.A.length; i++) { for (let j = 0; j < this.A[0].length; j++) { tempAS[i][j] = this.mod(this.s[i] * this.A[i][j], this.q); } } let result = Array(this.m).fill(0); for (let i = 0; i < this.m; i++) { for (let j = 0; j < this.n; j++) { result[i] = this.mod(result[i] + tempAS[j][i], this.q); } } return result.map((val, idx) => this.mod(val + this.e[idx], this.q)); } async encrypt(msg, password, encryptParams) { await this.sVector(password); if (encryptParams) { this.A = encryptParams.A; this.e = encryptParams.E; } else { this.defineA(); this.defineE(); } const ascii = Array.from(msg).map( (char) => this.mod(char.charCodeAt(0), this.q) ); const b = this.calculateB(); const cyphertext = ascii.map( (val, idx) => this.mod(val + b[idx % b.length], this.q) ); return { data: this.arrayToBase64(cyphertext), params: { A: this.A, E: this.e, q: this.q } }; } async decrypt(encryptedData, password) { await this.sVector(password); this.A = encryptedData.params.A; this.e = encryptedData.params.E; this.q = encryptedData.params.q; const fromBase64 = this.base64ToArray(encryptedData.data); const b = this.calculateB(); const decrypted = fromBase64.map( (val, idx) => this.mod(val - b[idx % b.length], this.q) ); return String.fromCharCode(...decrypted); } arrayToBase64(arr) { return Buffer.from(JSON.stringify(arr)).toString("base64"); } base64ToArray(base64) { return JSON.parse(Buffer.from(base64, "base64").toString()); } }; var createEncryptionService = (m = 128, n = 64, q = 2053) => { return new AntiganeEncryption(m, n, q); }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { AntiganeEncryption, createEncryptionService });