V0.6.9 Arroyo Toad
Added support for P256 curve and suppressed the one for P521 for testing reasons
This commit is contained in:
@@ -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"],
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user