Skip to content

Commit

Permalink
Merge pull request #1 from dajiaji/first-release
Browse files Browse the repository at this point in the history
Initial implementation.
  • Loading branch information
dajiaji authored Sep 4, 2023
2 parents 4403483 + a3cde48 commit 5600547
Show file tree
Hide file tree
Showing 20 changed files with 3,691 additions and 1 deletion.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Changes

## Version 0.1.0

Released 2023-09-03

- First public preview release.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
# crystals-kyber-js
A CRYSTALS-KYBER implementation written in TypeScript for various JavaScript runtimes.

A CRYSTALS-KYBER implementation written in TypeScript for various JavaScript
runtimes.
13 changes: 13 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Security Policy

## Supported Versions

| Version | Supported |
| ------- | ------------------ |
| 0.1.x | :white_check_mark: |

## Reporting a Vulnerability

Please use maintainer's email: [email protected]

DO NOT REPORT SECURITY VULNERABILITIES VIA THE ISSUES OF THIS REPOSITORY.
31 changes: 31 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"imports": {
"testing/": "https://deno.land/[email protected]/testing/",
"dnt": "https://deno.land/x/[email protected]/mod.ts"
},
"fmt": {
"include": [
"README.md",
"deno.json",
"dnt.ts",
"mod.ts",
"src/",
"test/"
],
"exclude": [
"**/*/node_modules"
]
},
"lint": {
"include": ["mod.ts", "src/", "test/"],
"exclude": [
"**/*/node_modules"
]
},
"tasks": {
"test": "deno fmt && deno lint && deno test test -A --fail-fast --doc --coverage=coverage --parallel --allow-read",
"cov": "deno coverage ./coverage --lcov --exclude='test'",
"dnt": "deno run -A dnt.ts $(git describe --tags $(git rev-list --tags --max-count=1))",
"minify": "esbuild npm/esm/mod.js --bundle --format=esm --minify"
}
}
62 changes: 62 additions & 0 deletions dnt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { build, emptyDir } from "dnt";

await emptyDir("./npm");

await build({
entryPoints: ["./mod.ts"],
outDir: "./npm",
typeCheck: "both",
test: true,
declaration: true,
scriptModule: "umd",
importMap: "./deno.json",
compilerOptions: {
lib: ["es2022", "dom"],
},
shims: {
deno: "dev",
},
package: {
name: "crystals-kyber-js",
version: Deno.args[0],
description:
"A CRYSTALS-KYBER implementation written in TypeScript for various JavaScript runtimes",
repository: {
type: "git",
url: "git+https://github.com/dajiaji/crystals-kyber-js.git",
},
homepage: "https://github.com/dajiaji/crystals-kyber-js#readme",
license: "MIT",
module: "./esm/mod.js",
main: "./script/mod.js",
types: "./esm/mod.d.ts",
sideEffects: false,
exports: {
".": {
"import": "./esm/mod.js",
"require": "./script/mod.js",
},
"./package.json": "./package.json",
},
keywords: [
"crystals-kyber",
"kyber",
"kem",
"security",
"encryption",
"pqc",
"post-quantum",
],
engines: {
"node": ">=16.0.0",
},
author: "Ajitomi Daisuke",
bugs: {
url: "https://github.com/dajiaji/crystals-kyber-js/issues",
},
},
});

// post build steps
Deno.copyFileSync("LICENSE", "npm/LICENSE");
Deno.copyFileSync("README.md", "npm/README.md");
4 changes: 4 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { KyberError } from "./src/errors.ts";
export { Kyber512 } from "./src/kyber512.ts";
export { Kyber768 } from "./src/kyber768.ts";
export { Kyber1024 } from "./src/kyber1024.ts";
39 changes: 39 additions & 0 deletions src/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
* which was deveploped under the MIT licence below:
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
*/

export const N = 256;

export const Q = 3329;

export const Q_INV = 62209;

// deno-fmt-ignore
export const NTT_ZETAS = [
2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962,
2127, 1855, 1468, 573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017,
732, 608, 1787, 411, 3124, 1758, 1223, 652, 2777, 1015, 2036, 1491, 3047,
1785, 516, 3321, 3009, 2663, 1711, 2167, 126, 1469, 2476, 3239, 3058, 830,
107, 1908, 3082, 2378, 2931, 961, 1821, 2604, 448, 2264, 677, 2054, 2226,
430, 555, 843, 2078, 871, 1550, 105, 422, 587, 177, 3094, 3038, 2869, 1574,
1653, 3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349,
418, 329, 3173, 3254, 817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193,
1218, 1994, 2455, 220, 2142, 1670, 2144, 1799, 2051, 794, 1819, 2475, 2459,
478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628,
];

// deno-fmt-ignore
export const NTT_ZETAS_INV = [
1701, 1807, 1460, 2371, 2338, 2333, 308, 108, 2851, 870, 854, 1510, 2535,
1278, 1530, 1185, 1659, 1187, 3109, 874, 1335, 2111, 136, 1215, 2945, 1465,
1285, 2007, 2719, 2726, 2232, 2512, 75, 156, 3000, 2911, 2980, 872, 2685,
1590, 2210, 602, 1846, 777, 147, 2170, 2551, 246, 1676, 1755, 460, 291, 235,
3152, 2742, 2907, 3224, 1779, 2458, 1251, 2486, 2774, 2899, 1103, 1275, 2652,
1065, 2881, 725, 1508, 2368, 398, 951, 247, 1421, 3222, 2499, 271, 90, 853,
1860, 3203, 1162, 1618, 666, 320, 8, 2813, 1544, 282, 1838, 1293, 2314, 552,
2677, 2106, 1571, 205, 2918, 1542, 2721, 2597, 2312, 681, 130, 1602, 1871,
829, 2946, 3065, 1325, 2756, 1861, 1474, 1202, 2367, 3147, 1752, 2707, 171,
3127, 3042, 1907, 1836, 1517, 359, 758, 1441,
];
19 changes: 19 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* The base error class of kyber-ts.
*/
export class KyberError extends Error {
public constructor(e: unknown) {
let message: string;

if (e instanceof Error) {
message = e.message;
} else if (typeof e === "string") {
message = e;
} else {
message = "";
}
super(message);

this.name = this.constructor.name;
}
}
126 changes: 126 additions & 0 deletions src/kyber1024.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/**
* This implementation is based on https://github.com/antontutoveanu/crystals-kyber-javascript,
* which was deveploped under the MIT licence below:
* https://github.com/antontutoveanu/crystals-kyber-javascript/blob/main/LICENSE
*/
import { N, Q } from "./consts.ts";
import { KyberBase } from "./kyberBase.ts";
import { byte, int16, uint16, uint32 } from "./utils.ts";

export class Kyber1024 extends KyberBase {
protected _k = 4;
protected _du = 11;
protected _dv = 5;
protected _eta1 = 2;
protected _eta2 = 2;

constructor() {
super();
this._skSize = 12 * this._k * N / 8;
this._pkSize = this._skSize + 32;
this._compressedUSize = this._k * this._du * N / 8;
this._compressedVSize = this._dv * N / 8;
}

// compressU lossily compresses and serializes a vector of polynomials.
protected override _compressU(
r: Uint8Array,
u: Array<Array<number>>,
): Uint8Array {
const t = new Array<number>(8);
for (let rr = 0, i = 0; i < this._k; i++) {
for (let j = 0; j < N / 8; j++) {
for (let k = 0; k < 8; k++) {
t[k] = uint16(
(((uint32(u[i][8 * j + k]) << 11 >>> 0) + uint32(Q / 2)) /
uint32(Q)) & 0x7ff >>> 0,
);
}
r[rr++] = byte(t[0] >> 0);
r[rr++] = byte((t[0] >> 8) | (t[1] << 3));
r[rr++] = byte((t[1] >> 5) | (t[2] << 6));
r[rr++] = byte(t[2] >> 2);
r[rr++] = byte((t[2] >> 10) | (t[3] << 1));
r[rr++] = byte((t[3] >> 7) | (t[4] << 4));
r[rr++] = byte((t[4] >> 4) | (t[5] << 7));
r[rr++] = byte(t[5] >> 1);
r[rr++] = byte((t[5] >> 9) | (t[6] << 2));
r[rr++] = byte((t[6] >> 6) | (t[7] << 5));
r[rr++] = byte(t[7] >> 3);
}
}
return r;
}

// compressV lossily compresses and subsequently serializes a polynomial.
protected override _compressV(r: Uint8Array, v: Array<number>): Uint8Array {
const t = new Uint8Array(8);
for (let rr = 0, i = 0; i < N / 8; i++) {
for (let j = 0; j < 8; j++) {
t[j] = byte(
((uint32(v[8 * i + j]) << 5 >>> 0) + uint32(Q / 2)) / uint32(Q),
) & 31;
}
r[rr++] = byte((t[0] >> 0) | (t[1] << 5));
r[rr++] = byte((t[1] >> 3) | (t[2] << 2) | (t[3] << 7));
r[rr++] = byte((t[3] >> 1) | (t[4] << 4));
r[rr++] = byte((t[4] >> 4) | (t[5] << 1) | (t[6] << 6));
r[rr++] = byte((t[6] >> 2) | (t[7] << 3));
}
return r;
}

// decompressU de-serializes and decompresses a vector of polynomials and
// represents the approximate inverse of compress1. Since compression is lossy,
// the results of decompression will may not match the original vector of polynomials.
protected override _decompressU(a: Uint8Array): Array<Array<number>> {
const r = new Array<Array<number>>(this._k);
for (let i = 0; i < this._k; i++) {
r[i] = new Array<number>(384);
}
const t = new Array<number>(8);
for (let aa = 0, i = 0; i < this._k; i++) {
for (let j = 0; j < N / 8; j++) {
t[0] = (uint16(a[aa + 0]) >> 0) | (uint16(a[aa + 1]) << 8);
t[1] = (uint16(a[aa + 1]) >> 3) | (uint16(a[aa + 2]) << 5);
t[2] = (uint16(a[aa + 2]) >> 6) | (uint16(a[aa + 3]) << 2) |
(uint16(a[aa + 4]) << 10);
t[3] = (uint16(a[aa + 4]) >> 1) | (uint16(a[aa + 5]) << 7);
t[4] = (uint16(a[aa + 5]) >> 4) | (uint16(a[aa + 6]) << 4);
t[5] = (uint16(a[aa + 6]) >> 7) | (uint16(a[aa + 7]) << 1) |
(uint16(a[aa + 8]) << 9);
t[6] = (uint16(a[aa + 8]) >> 2) | (uint16(a[aa + 9]) << 6);
t[7] = (uint16(a[aa + 9]) >> 5) | (uint16(a[aa + 10]) << 3);
aa = aa + 11;
for (let k = 0; k < 8; k++) {
r[i][8 * j + k] = (uint32(t[k] & 0x7FF) * Q + 1024) >> 11;
}
}
}
return r;
}

// decompressV de-serializes and subsequently decompresses a polynomial,
// representing the approximate inverse of compress2.
// Note that compression is lossy, and thus decompression will not match the
// original input.
protected override _decompressV(a: Uint8Array): Array<number> {
const r = new Array<number>(384);
const t = new Array<number>(8);
for (let aa = 0, i = 0; i < N / 8; i++) {
t[0] = a[aa + 0] >> 0;
t[1] = (a[aa + 0] >> 5) | (a[aa + 1] << 3);
t[2] = a[aa + 1] >> 2;
t[3] = (a[aa + 1] >> 7) | (a[aa + 2] << 1);
t[4] = (a[aa + 2] >> 4) | (a[aa + 3] << 4);
t[5] = a[aa + 3] >> 1;
t[6] = (a[aa + 3] >> 6) | (a[aa + 4] << 2);
t[7] = a[aa + 4] >> 3;
aa = aa + 5;
for (let j = 0; j < 8; j++) {
r[8 * i + j] = int16(((uint32(t[j] & 31 >>> 0) * uint32(Q)) + 16) >> 5);
}
}
return r;
}
}
Loading

0 comments on commit 5600547

Please sign in to comment.