V0.6.9 Arroyo Toad

Added support for P256 curve and suppressed the one for P521 for testing reasons
This commit is contained in:
Christian Risi 2024-12-07 18:00:35 +00:00
parent e9abeb9bb6
commit fa71d33a53
13 changed files with 169 additions and 27 deletions

39
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,39 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"request": "launch",
"name": "Launch Program",
"type": "node",
"program": "${workspaceFolder}/src/mod.ts",
"cwd": "${workspaceFolder}",
"env": {},
"runtimeExecutable": "/usr/bin/deno",
"runtimeArgs": [
"run",
"--unstable",
"--inspect-wait",
"--allow-all"
],
"attachSimplePort": 9229
},
{
"request": "launch",
"name": "Test Program",
"type": "node",
"cwd": "${workspaceFolder}",
"env": {},
"runtimeExecutable": "/usr/bin/deno",
"runtimeArgs": [
"test",
"--unstable",
"--inspect-wait",
"--allow-all"
],
"attachSimplePort": 9229
}
]
}

2
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,2 @@
{
}

Binary file not shown.

16
Private/cert.pem Normal file
View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICeTCCAdqgAwIBAgIUeKyiiDJdVGH3ParIry5vn/YGnaowCgYIKoZIzj0EAwIw
TjELMAkGA1UEBhMCSVQxDTALBgNVBAgMBEJhcmkxDTALBgNVBAcMBEJhcmkxITAf
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDEyMDIxNjM0NDVa
Fw0yNTAxMDExNjM0NDVaME4xCzAJBgNVBAYTAklUMQ0wCwYDVQQIDARCYXJpMQ0w
CwYDVQQHDARCYXJpMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQw
gZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAAAfWnGEUMElY/XIWUTPvX65HX3N5Ik
JKPdVFzDRtaTHRJKnEEvU7Z5iLAT9NpbVfCabvQXKo7LD5sjoJ1ZpSVcogDgCFCo
pmVin2ZLs5lyMtaetpVDH8m+AIlRQkkuGmkasM+OV62kzSoHl/CL4eNz1xXwqsPt
oBgvPiRFxNIE/0dz96NTMFEwHQYDVR0OBBYEFKW5mYrSXJn68diXLDjhbiEGAxJu
MB8GA1UdIwQYMBaAFKW5mYrSXJn68diXLDjhbiEGAxJuMA8GA1UdEwEB/wQFMAMB
Af8wCgYIKoZIzj0EAwIDgYwAMIGIAkIAhVgtxgnZd6KeefLjZ6Mazgr5xLDcAHyI
NsKtTw3YzT/Pztnk2ccV+NyDZyoTG72lHoPMTiB5mRSUTqORg59XQTkCQgDqHRoN
tRQlPWY3abohilRRdvYZrsoPR8FzB/M4KxT0nk10jc1wtosQ7l/XZGcKe8/k+iVs
HC5CsESzsvnp+Qslyw==
-----END CERTIFICATE-----

View File

@ -1,6 +1,4 @@
-----BEGIN PUBLIC KEY-----
MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAAH1pxhFDBJWP1yFlEz71+uR19zeS
JCSj3VRcw0bWkx0SSpxBL1O2eYiwE/TaW1Xwmm70FyqOyw+bI6CdWaUlXKIA4AhQ
qKZlYp9mS7OZcjLWnraVQx/JvgCJUUJJLhppGrDPjletpM0qB5fwi+Hjc9cV8KrD
7aAYLz4kRcTSBP9Hc/c=
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsszGIDjEgu6k/MkW+p5Bf+UPEU/j
F9bLykzEOzP3rD/HJ2AprRpVm+PNIaLThIdUTPsO2BBBLH2CaAJ/1x65Wg==
-----END PUBLIC KEY-----

View File

@ -1,6 +1,6 @@
{
"tasks": {
"dev": "deno run --watch ./src/main.ts"
"dev": "deno run --watch ./src/mod.ts"
},
"imports": {
"@std/assert": "jsr:@std/assert@1"

14
deno.lock generated
View File

@ -2,7 +2,8 @@
"version": "4",
"specifiers": {
"jsr:@std/assert@1": "1.0.9",
"jsr:@std/internal@^1.0.5": "1.0.5"
"jsr:@std/internal@^1.0.5": "1.0.5",
"npm:@types/node@*": "22.5.4"
},
"jsr": {
"@std/assert@1.0.9": {
@ -15,6 +16,17 @@
"integrity": "54a546004f769c1ac9e025abd15a76b6671ddc9687e2313b67376125650dc7ba"
}
},
"npm": {
"@types/node@22.5.4": {
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
"dependencies": [
"undici-types"
]
},
"undici-types@6.19.8": {
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
}
},
"workspace": {
"dependencies": [
"jsr:@std/assert@1"

View File

@ -11,7 +11,7 @@ export class Message {
public deviceType: DeviceType;
public signatureType: SignatureType;
public timestamp: bigint;
public timestamp: number;
public deviceID: bigint;
public location: DeviceLocation;
public fields: Field[];
@ -23,7 +23,7 @@ export class Message {
deviceType: DeviceType,
RESERVED: number,
signatureType: SignatureType,
timestamp: bigint,
timestamp: number,
deviceID: bigint,
location: DeviceLocation,
fields: Field[],
@ -50,7 +50,7 @@ Message ----------------------
\tDevice Type: \t${this.deviceType}
\tRESERVED: \t${this.RESERVED}
\tSignature Type: \t${this.signatureType}
\tTimestamp: \t${ new Date(Number(this.timestamp / 10000000n))}
\tTimestamp: \t${ new Date(this.timestamp * 1000)}
\tDevice ID: \t${this.deviceID}
\tLocation: \tX: ${this.location.x}\tY: ${this.location.y}\tZ: ${this.location.z}
\tFields: \n`;

View File

@ -1,3 +1,5 @@
export enum SignatureType {
P521 = 10
P521 = 10,
P384 = 11,
P256 = 12,
}

View File

@ -1 +1,2 @@
console.log("Hu")

View File

@ -4,8 +4,10 @@ import { DeviceType } from "../enums/DeviceType.ts";
import { MessageType } from "../enums/MessageType.ts";
import { SignatureType } from "../enums/SignatureType.ts";
import { DeviceLocation } from "../classes/Location.ts";
import { signatureVerifierV1 } from "./signatureVerifier.ts";
import * as mod from "node:crypto";
export function deserializerV1(buffer: ArrayBuffer) {
export async function deserializerV1(buffer: ArrayBuffer, key: mod.webcrypto.CryptoKey) {
const version: number = new Uint8Array(buffer.slice(0, 1))[0];
// UGLY Force typecasting
@ -31,7 +33,7 @@ export function deserializerV1(buffer: ArrayBuffer) {
] as keyof typeof SignatureType
];
const timestamp: bigint = new BigUint64Array(buffer.slice(8, 16))[0];
const timestamp: number = new Float64Array(buffer.slice(8, 16))[0];
// UGLY: sum the 2 bigints to a sing bigint
const deviceID_Buffer = new BigUint64Array(buffer.slice(16, 32));
@ -44,7 +46,7 @@ export function deserializerV1(buffer: ArrayBuffer) {
let index = 56;
let MORE_FIELDS = true;
let fields: Field[] = Array<Field>();
const fields: Field[] = Array<Field>();
while (MORE_FIELDS) {
const nextchunk = new BigUint64Array(buffer.slice(index, index + 8))[0];
@ -71,11 +73,19 @@ export function deserializerV1(buffer: ArrayBuffer) {
index += paddingBytes + 8;
const signatureStart = index
const msgBuffer = buffer.slice(0, signatureStart)
const signature = new Uint8Array(buffer.slice(index))
if (signature.length != signatureBytesMapper(signatureType)) {
throw new Error("This signature is not valid")
const result = await signatureVerifierV1(msgBuffer, signature, key)
if (!result) {
throw new Error("Invalid message")
}
return new Message(
version,
@ -92,12 +102,5 @@ export function deserializerV1(buffer: ArrayBuffer) {
}
export function signatureBytesMapper(signatureType: SignatureType) {
switch (signatureType) {
case SignatureType.P521 : {
return 132
}
}
}

View File

@ -0,0 +1,59 @@
import * as mod from "node:crypto";
import { atob } from "node:buffer";
/// Copy pasted from Mozilla
function str2ab(str: string) {
const buf = new ArrayBuffer(str.length);
const bufView = new Uint8Array(buf);
for (let i = 0, strLen = str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
export async function signatureVerifierV1(
msgData: ArrayBuffer,
signature: ArrayBuffer,
Ku: mod.webcrypto.CryptoKey,
) {
// UGLY: Assuming ECDSA P-256
return await mod.subtle.verify(
{
name: "ECDSA",
hash: "SHA-256",
},
Ku,
signature,
msgData,
);
}
export async function pem2key(filePath: string) {
const publicKeyBytes = await Deno.readFile(filePath);
const pemKey = new TextDecoder().decode(publicKeyBytes);
// fetch the part of the PEM string between header and footer
const pemHeader = "-----BEGIN PUBLIC KEY-----";
const pemFooter = "-----END PUBLIC KEY-----";
const pemContents = pemKey.substring(
pemHeader.length,
pemKey.length - pemFooter.length - 1,
);
// base64 decode the string to get the binary data
// convert from a binary string to an ArrayBuffer
const a = atob(pemContents);
const binaryDer = str2ab(a);
// UGLY: Assuming P-256
return mod.subtle.importKey(
"spki",
binaryDer,
{
name: "ECDSA",
namedCurve: "P-256",
},
true,
["verify"],
);
}

View File

@ -1,12 +1,22 @@
import { assertEquals } from "@std/assert";
import { assertEquals, assert } from "@std/assert";
import { deserializerV1 } from "../src/utils/deserializer.ts";
import { pem2key, signatureVerifierV1 } from "../src/utils/signatureVerifier.ts";
import * as mod from "node:crypto";
Deno.test(async function deserializerV1Test() {
Deno.test(async function verifySignatureV1Test() {
const messageBuffer = (await Deno.readFile("./Private/Message.bin")).buffer
const msg = deserializerV1(messageBuffer)
const publicKey = await pem2key("./Private/public-key.pem")
const Ku = await pem2key("./Private/public-key.pem")
const msg = await deserializerV1(messageBuffer, Ku)
console.log(msg.toString())
//Assert
})
Deno.test(async function verifySignatureV1Test() {
})