@oslojs/crypto
Advanced tools
Comparing version 0.3.0 to 0.4.0
@@ -13,10 +13,12 @@ export declare class ECDSAPoint { | ||
} | ||
export declare class ECDSACurve { | ||
g: ECDSAPoint; | ||
export declare class ECDSANamedCurve { | ||
p: bigint; | ||
a: bigint; | ||
b: bigint; | ||
g: ECDSAPoint; | ||
n: bigint; | ||
cofactor: bigint; | ||
size: number; | ||
constructor(p: bigint, a: bigint, b: bigint, g: ECDSAPoint, n: bigint, size: number); | ||
objectIdentifier: string; | ||
constructor(p: bigint, a: bigint, b: bigint, gx: bigint, gy: bigint, n: bigint, cofactor: bigint, size: number, objectIdentifier: string); | ||
add(point1: ECDSAPoint, point2: ECDSAPoint): ECDSAPoint | null; | ||
@@ -28,11 +30,5 @@ private addJacobian; | ||
fromAffine(point: ECDSAPoint): JacobianPoint; | ||
multiply(k: Uint8Array, point: ECDSAPoint): ECDSAPoint | null; | ||
multiply(k: bigint, point: ECDSAPoint): ECDSAPoint | null; | ||
isOnCurve(point: ECDSAPoint): boolean; | ||
} | ||
export declare const p192: ECDSACurve; | ||
export declare const p224: ECDSACurve; | ||
export declare const p256: ECDSACurve; | ||
export declare const p384: ECDSACurve; | ||
export declare const p521: ECDSACurve; | ||
export declare const secp256k1: ECDSACurve; | ||
export {}; |
@@ -0,1 +1,2 @@ | ||
import { bigIntBytes } from "@oslojs/binary"; | ||
import { euclideanMod, inverseMod } from "./math.js"; | ||
@@ -23,16 +24,20 @@ export class ECDSAPoint { | ||
} | ||
export class ECDSACurve { | ||
g; | ||
export class ECDSANamedCurve { | ||
p; | ||
a; | ||
b; | ||
g; | ||
n; | ||
cofactor; | ||
size; | ||
constructor(p, a, b, g, n, size) { | ||
objectIdentifier; | ||
constructor(p, a, b, gx, gy, n, cofactor, size, objectIdentifier) { | ||
this.p = p; | ||
this.a = a; | ||
this.b = b; | ||
this.g = g; | ||
this.g = new ECDSAPoint(gx, gy); | ||
this.n = n; | ||
this.cofactor = cofactor; | ||
this.size = size; | ||
this.objectIdentifier = objectIdentifier; | ||
} | ||
@@ -98,7 +103,10 @@ add(point1, point2) { | ||
} | ||
// Assumes the point is already on the curve | ||
multiply(k, point) { | ||
// For co-factor h > 1, ensure the point is in the prime order subgroup | ||
const kBytes = bigIntBytes(k); | ||
// montgomery ladder | ||
const r = [pointAtInfinity(), new JacobianPoint(point.x, point.y, 1n)]; | ||
for (let i = 0; i < k.byteLength * 8; i++) { | ||
const byte = k[Math.floor(i / 8)]; | ||
for (let i = 0; i < kBytes.byteLength * 8; i++) { | ||
const byte = kBytes[Math.floor(i / 8)]; | ||
const bit = (byte >> (7 - (i % 8))) & 0x01; | ||
@@ -112,2 +120,6 @@ const notBit = bit ^ 1; | ||
isOnCurve(point) { | ||
// For co-factor h > 1, ensure the point is in the prime order subgroup | ||
if (this.cofactor !== 1n && this.multiply(this.n, point) !== null) { | ||
return false; | ||
} | ||
return (euclideanMod(point.y ** 2n, this.p) === | ||
@@ -120,43 +132,1 @@ euclideanMod(point.x ** 3n + this.a * point.x + this.b, this.p)); | ||
} | ||
const P192_P = 0xfffffffffffffffffffffffffffffffeffffffffffffffffn; | ||
const P192_A = 0xfffffffffffffffffffffffffffffffefffffffffffffffcn; | ||
const P192_B = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1n; | ||
const P192_G = new ECDSAPoint(0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012n, 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811n); | ||
const P192_N = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831n; | ||
const P192_SIZE = 24; | ||
export const p192 = new ECDSACurve(P192_P, P192_A, P192_B, P192_G, P192_N, P192_SIZE); | ||
const P224_P = 0xffffffffffffffffffffffffffffffff000000000000000000000001n; | ||
const P224_A = 0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffen; | ||
const P224_B = 0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4n; | ||
const P224_G = new ECDSAPoint(0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21n, 0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34n); | ||
const P224_N = 0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3dn; | ||
const P224_SIZE = 28; | ||
export const p224 = new ECDSACurve(P224_P, P224_A, P224_B, P224_G, P224_N, P224_SIZE); | ||
const P256_P = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffffn; | ||
const P256_A = 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffcn; | ||
const P256_B = 0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604bn; | ||
const P256_G = new ECDSAPoint(0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296n, 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5n); | ||
const P256_N = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551n; | ||
const P256_SIZE = 32; | ||
export const p256 = new ECDSACurve(P256_P, P256_A, P256_B, P256_G, P256_N, P256_SIZE); | ||
const P384_P = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffffn; | ||
const P384_A = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffcn; | ||
const P384_B = 0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aefn; | ||
const P384_G = new ECDSAPoint(0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7n, 0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5fn); | ||
const P384_N = 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973n; | ||
const P384_SIZE = 48; | ||
export const p384 = new ECDSACurve(P384_P, P384_A, P384_B, P384_G, P384_N, P384_SIZE); | ||
const P521_P = 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn; | ||
const P521_A = 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcn; | ||
const P521_B = 0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00n; | ||
const P521_G = new ECDSAPoint(0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66n, 0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650n); | ||
const P521_N = 0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409n; | ||
const P521_SIZE = 66; | ||
export const p521 = new ECDSACurve(P521_P, P521_A, P521_B, P521_G, P521_N, P521_SIZE); | ||
const SECP256K1_P = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn; | ||
const SECP256K1_A = 0x0000000000000000000000000000000000000000000000000000000000000000n; | ||
const SECP256K1_B = 0x0000000000000000000000000000000000000000000000000000000000000007n; | ||
const SECP256K1_G = new ECDSAPoint(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n); | ||
const SECP256K1_N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n; | ||
const SECP256K1_SIZE = 32; | ||
export const secp256k1 = new ECDSACurve(SECP256K1_P, SECP256K1_A, SECP256K1_B, SECP256K1_G, SECP256K1_N, SECP256K1_SIZE); |
@@ -1,22 +0,4 @@ | ||
export { ECDSACurve, ECDSAPoint, p192, p224, p256, p384, p521, secp256k1 } from "./curve.js"; | ||
import type { ECDSACurve } from "./curve.js"; | ||
export declare function verifyECDSA(publicKey: ECDSAPublicKey, hash: Uint8Array, r: bigint, s: bigint): boolean; | ||
export declare class ECDSAPublicKey { | ||
curve: ECDSACurve; | ||
x: bigint; | ||
y: bigint; | ||
constructor(curve: ECDSACurve, x: bigint, y: bigint); | ||
encodeSEC1Uncompressed(): Uint8Array; | ||
encodeSEC1Compressed(): Uint8Array; | ||
} | ||
export declare function decodeSEC1PublicKey(curve: ECDSACurve, bytes: Uint8Array): ECDSAPublicKey; | ||
export declare class ECDSASignature { | ||
r: bigint; | ||
s: bigint; | ||
constructor(r: bigint, s: bigint); | ||
encodeIEEEP1363(curve: ECDSACurve): Uint8Array; | ||
} | ||
export declare function decodeIEEEP1363ECDSASignature(curve: ECDSACurve, bytes: Uint8Array): ECDSASignature; | ||
export declare class ECDSADecodeError extends Error { | ||
constructor(message: string); | ||
} | ||
export { decodeIEEEP1363ECDSASignature, decodeSEC1PublicKey, decodeX509ECDSAPublicKey, decodeX509ECDSASignature, ECDSAPublicKey, ECDSASignature, verifyECDSASignature } from "./ecdsa.js"; | ||
export { p192, p224, p256, p384, p521 } from "./curve-nist.js"; | ||
export { secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1 } from "./curve-sec.js"; | ||
export { ECDSANamedCurve } from "./curve.js"; |
@@ -1,136 +0,4 @@ | ||
export { ECDSACurve, ECDSAPoint, p192, p224, p256, p384, p521, secp256k1 } from "./curve.js"; | ||
import { ECDSAPoint } from "./curve.js"; | ||
import { euclideanMod, inverseMod, tonelliShanks } from "./math.js"; | ||
import { bigIntBytes, bigIntFromBytes } from "@oslojs/binary"; | ||
export function verifyECDSA(publicKey, hash, r, s) { | ||
const q = new ECDSAPoint(publicKey.x, publicKey.y); | ||
if (!publicKey.curve.isOnCurve(q)) { | ||
return false; | ||
} | ||
if (publicKey.curve.multiply(bigIntBytes(publicKey.curve.n), q) !== null) { | ||
return false; | ||
} | ||
const e = hash.slice(0, publicKey.curve.size); | ||
const u1 = euclideanMod(bigIntFromBytes(e) * inverseMod(s, publicKey.curve.n), publicKey.curve.n); | ||
const u1G = publicKey.curve.multiply(bigIntBytes(u1), publicKey.curve.g); | ||
if (u1G === null) { | ||
return false; | ||
} | ||
const u2 = euclideanMod(r * inverseMod(s, publicKey.curve.n), publicKey.curve.n); | ||
const u2Q = publicKey.curve.multiply(bigIntBytes(u2), q); | ||
if (u2Q === null) { | ||
return false; | ||
} | ||
const coord1 = publicKey.curve.add(u1G, u2Q); | ||
if (coord1 === null) { | ||
return false; | ||
} | ||
return euclideanMod(r, publicKey.curve.n) === coord1.x; | ||
} | ||
export class ECDSAPublicKey { | ||
curve; | ||
x; | ||
y; | ||
constructor(curve, x, y) { | ||
this.curve = curve; | ||
this.x = x; | ||
this.y = y; | ||
} | ||
encodeSEC1Uncompressed() { | ||
const bytes = new Uint8Array(1 + this.curve.size * 2); | ||
bytes[0] = 0x04; | ||
const xBytes = bigIntBytes(this.x); | ||
const yBytes = bigIntBytes(this.y); | ||
bytes.set(xBytes, 1 + this.curve.size - xBytes.byteLength); | ||
bytes.set(yBytes, 1 + this.curve.size); | ||
return bytes; | ||
} | ||
encodeSEC1Compressed() { | ||
const bytes = new Uint8Array(1 + this.curve.size); | ||
if (this.y % 2n === 0n) { | ||
bytes[0] = 0x02; | ||
} | ||
else { | ||
bytes[0] = 0x03; | ||
} | ||
const xBytes = bigIntBytes(this.x); | ||
bytes.set(xBytes, 1 + this.curve.size - xBytes.byteLength); | ||
return bytes; | ||
} | ||
} | ||
export function decodeSEC1PublicKey(curve, bytes) { | ||
if (bytes.byteLength < 1) { | ||
throw new Error("Invalid public key"); | ||
} | ||
if (bytes[0] === 0x04) { | ||
if (bytes.byteLength !== curve.size * 2 + 1) { | ||
throw new Error("Invalid public key"); | ||
} | ||
const x = bigIntFromBytes(bytes.slice(1, curve.size + 1)); | ||
const y = bigIntFromBytes(bytes.slice(curve.size + 1)); | ||
return new ECDSAPublicKey(curve, x, y); | ||
} | ||
if (bytes[0] === 0x02) { | ||
if (bytes.byteLength !== curve.size + 1) { | ||
throw new Error("Invalid public key"); | ||
} | ||
const x = bigIntFromBytes(bytes.slice(1)); | ||
const y2 = euclideanMod(x ** 3n + curve.a * x + curve.b, curve.p); | ||
const y = tonelliShanks(y2, curve.p); | ||
if (y % 2n === 0n) { | ||
return new ECDSAPublicKey(curve, x, y); | ||
} | ||
return new ECDSAPublicKey(curve, x, curve.p - y); | ||
} | ||
if (bytes[0] === 0x03) { | ||
if (bytes.byteLength !== curve.size + 1) { | ||
throw new Error("Invalid public key"); | ||
} | ||
const x = bigIntFromBytes(bytes.slice(1)); | ||
const y2 = euclideanMod(x ** 3n + curve.a * x + curve.b, curve.p); | ||
const y = tonelliShanks(y2, curve.p); | ||
if (y % 2n === 1n) { | ||
return new ECDSAPublicKey(curve, x, y); | ||
} | ||
return new ECDSAPublicKey(curve, x, curve.p - y); | ||
} | ||
throw new Error("Unknown encoding format"); | ||
} | ||
export class ECDSASignature { | ||
r; | ||
s; | ||
constructor(r, s) { | ||
if (r < 1n || s < 1n) { | ||
throw new TypeError("Invalid signature"); | ||
} | ||
this.r = r; | ||
this.s = s; | ||
} | ||
encodeIEEEP1363(curve) { | ||
const rs = new Uint8Array(curve.size * 2); | ||
const rBytes = bigIntBytes(this.r); | ||
if (rBytes.byteLength > curve.size) { | ||
throw new Error("'r' is too large"); | ||
} | ||
const sBytes = bigIntBytes(this.r); | ||
if (rBytes.byteLength > curve.size) { | ||
throw new Error("'s' is too large"); | ||
} | ||
rs.set(rBytes, curve.size - rBytes.byteLength); | ||
rs.set(sBytes, rs.byteLength - sBytes.byteLength); | ||
return rs; | ||
} | ||
} | ||
export function decodeIEEEP1363ECDSASignature(curve, bytes) { | ||
if (bytes.byteLength !== curve.size * 2) { | ||
throw new ECDSADecodeError("Invalid signature size"); | ||
} | ||
const r = bigIntFromBytes(bytes.slice(0, curve.size)); | ||
const s = bigIntFromBytes(bytes.slice(curve.size)); | ||
return new ECDSASignature(r, s); | ||
} | ||
export class ECDSADecodeError extends Error { | ||
constructor(message) { | ||
super(message); | ||
} | ||
} | ||
export { decodeIEEEP1363ECDSASignature, decodeSEC1PublicKey, decodeX509ECDSAPublicKey, decodeX509ECDSASignature, ECDSAPublicKey, ECDSASignature, verifyECDSASignature } from "./ecdsa.js"; | ||
export { p192, p224, p256, p384, p521 } from "./curve-nist.js"; | ||
export { secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1 } from "./curve-sec.js"; | ||
export { ECDSANamedCurve } from "./curve.js"; |
@@ -14,3 +14,3 @@ import { bigIntFromBytes } from "@oslojs/binary"; | ||
if (max < 2) { | ||
throw new Error("Argument 'max' must be a positive integer"); | ||
throw new Error("Argument 'max' must be a positive integer larger than 1"); | ||
} | ||
@@ -38,3 +38,3 @@ const inclusiveMaxBitLength = (max - 1n).toString(2).length; | ||
if (max < 2 || max > Number.MAX_SAFE_INTEGER) { | ||
throw new Error("Argument 'max' must be a positive integer"); | ||
throw new Error("Argument 'max' must be a positive integer larger than 1"); | ||
} | ||
@@ -41,0 +41,0 @@ return Number(generateRandomInteger(BigInt(max))); |
{ | ||
"name": "@oslojs/crypto", | ||
"type": "module", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "A very basic crypto library", | ||
@@ -61,3 +61,2 @@ "files": [ | ||
"devDependencies": { | ||
"@oslojs/asn1": "^0.2.0", | ||
"@scure/base": "^1.1.3", | ||
@@ -74,2 +73,3 @@ "@types/node": "^20.8.6", | ||
"dependencies": { | ||
"@oslojs/asn1": "0.2.1", | ||
"@oslojs/binary": "0.2.3" | ||
@@ -76,0 +76,0 @@ }, |
@@ -11,4 +11,2 @@ # @oslojs/crypto documentation | ||
Alongside [`@oslojs/encoding`](https://encoding.oslojs.dev) and [`@oslojs/binary`](https://binary.oslojs.dev), it aims to provide a basic toolbox for implementing auth and auth-related standards. | ||
## Installation | ||
@@ -15,0 +13,0 @@ |
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
59792
9
35
1490
2
32
+ Added@oslojs/asn1@0.2.1
+ Added@oslojs/asn1@0.2.1(transitive)