@antigane/encryption
Version:
encryption with Lattice-based Cryptography
140 lines (138 loc) • 4.29 kB
JavaScript
"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
});