V0.6.9 Arroyo Toad
Added support for P256 curve and suppressed the one for P521 for testing reasons
This commit is contained in:
parent
e9abeb9bb6
commit
fa71d33a53
39
.vscode/launch.json
vendored
Normal file
39
.vscode/launch.json
vendored
Normal 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
2
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
Binary file not shown.
16
Private/cert.pem
Normal file
16
Private/cert.pem
Normal 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-----
|
||||
@ -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-----
|
||||
@ -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
14
deno.lock
generated
@ -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"
|
||||
|
||||
@ -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`;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
export enum SignatureType {
|
||||
P521 = 10
|
||||
P521 = 10,
|
||||
P384 = 11,
|
||||
P256 = 12,
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
|
||||
console.log("Hu")
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
59
src/utils/signatureVerifier.ts
Normal file
59
src/utils/signatureVerifier.ts
Normal 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"],
|
||||
);
|
||||
}
|
||||
@ -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() {
|
||||
|
||||
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user