-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #64 from vaxxnz/feature/remove_cbor_package
Feature/remove cbor package
- Loading branch information
Showing
15 changed files
with
266 additions
and
894 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,14 @@ | ||
import { Buffer } from "buffer"; | ||
import { base32 } from "rfc4648"; | ||
import { decodeCBOR, encodeOneCBOR } from "./cbor"; | ||
import { decodeCOSE } from "./cbor"; | ||
|
||
test("CBOR library decodes", async () => { | ||
const res = base32.parse( | ||
"2KCEVIQEIVVWK6JNGEASNICZAEP2KALYDZSGSZB2O5SWEOTOPJRXALTDN53GSZBRHEXGQZLBNR2GQLTOPICRUYMBTIFAIGTUKBAAUYTWMOSGQQDDN5XHIZLYOSBHQJTIOR2HA4Z2F4XXO53XFZ3TGLTPOJTS6MRQGE4C6Y3SMVSGK3TUNFQWY4ZPOYYXQKTIOR2HA4Z2F4XW46TDOAXGG33WNFSDCOJONBSWC3DUNAXG46RPMNXW45DFPB2HGL3WGFTXMZLSONUW63TFGEXDALRQMR2HS4DFQJ2FMZLSNFTGSYLCNRSUG4TFMRSW45DJMFWG6UDVMJWGSY2DN53GSZCQMFZXG4LDOJSWIZLOORUWC3CTOVRGUZLDOSRWSZ3JOZSW4TTBNVSWISTBMNVWUZTBNVUWY6KOMFWWKZ2TOBQXE4TPO5RWI33CNIYTSNRQFUYDILJRGYDVAYFE6VGU4MCDGK7DHLLYWHVPUS2YIDJOA6Y524TD3AZRM263WTY2BE4DPKIF27WKF3UDNNVSVWRDYIYVJ65IRJJJ6Z25M2DO4YZLBHWFQGVQR5ZLIWEQJOZTS3IQ7JTNCFDX" | ||
); | ||
|
||
const cborobj = decodeCBOR(res); | ||
const cborobj = decodeCOSE(res); | ||
|
||
expect(cborobj.err).toEqual(undefined); | ||
expect(cborobj.tag).toEqual(18); | ||
expect(cborobj.value.length).toEqual(4); | ||
}); | ||
|
||
test("CBOR library encodes", async () => { | ||
const res = Buffer.from(base32.parse( | ||
"2KCEVIQEIVVWK6JNGEASNICZAEP2KALYDZSGSZB2O5SWEOTOPJRXALTDN53GSZBRHEXGQZLBNR2GQLTOPICRUYMBTIFAIGTUKBAAUYTWMOSGQQDDN5XHIZLYOSBHQJTIOR2HA4Z2F4XXO53XFZ3TGLTPOJTS6MRQGE4C6Y3SMVSGK3TUNFQWY4ZPOYYXQKTIOR2HA4Z2F4XW46TDOAXGG33WNFSDCOJONBSWC3DUNAXG46RPMNXW45DFPB2HGL3WGFTXMZLSONUW63TFGEXDALRQMR2HS4DFQJ2FMZLSNFTGSYLCNRSUG4TFMRSW45DJMFWG6UDVMJWGSY2DN53GSZCQMFZXG4LDOJSWIZLOORUWC3CTOVRGUZLDOSRWSZ3JOZSW4TTBNVSWISTBMNVWUZTBNVUWY6KOMFWWKZ2TOBQXE4TPO5RWI33CNIYTSNRQFUYDILJRGYDVAYFE6VGU4MCDGK7DHLLYWHVPUS2YIDJOA6Y524TD3AZRM263WTY2BE4DPKIF27WKF3UDNNVSVWRDYIYVJ65IRJJJ6Z25M2DO4YZLBHWFQGVQR5ZLIWEQJOZTS3IQ7JTNCFDX" | ||
)); | ||
|
||
const cborobj = decodeCBOR(res); | ||
const result = encodeOneCBOR(cborobj); | ||
|
||
expect(res.toString("hex")).toEqual(result.toString("hex")); | ||
}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,212 @@ | ||
// centralized place where cbor is included, in case we need to patch it | ||
import { Data } from "./cborTypes"; | ||
import { DecodedCOSEStructure } from "./coseTypes"; | ||
|
||
import { Buffer } from "buffer"; | ||
// author: putara | ||
// https://github.com/putara/nzcp/blob/master/verifier.js | ||
class Stream { | ||
data: Uint8Array; | ||
ptr: number; | ||
len: number; | ||
|
||
import process from "process"; | ||
global.process = process; | ||
constructor(data: Uint8Array) { | ||
this.data = data; | ||
this.ptr = 0; | ||
this.len = data.length; | ||
} | ||
getc() { | ||
if (this.ptr >= this.len) { | ||
throw new Error("invalid data"); | ||
} | ||
return this.data[this.ptr++]; | ||
} | ||
ungetc() { | ||
if (this.ptr <= 0) { | ||
throw new Error("invalid data"); | ||
} | ||
--this.ptr; | ||
} | ||
chop(len: number) { | ||
if (len < 0) { | ||
throw new Error("invalid length"); | ||
} | ||
if (this.ptr + len > this.len) { | ||
throw new Error("invalid data"); | ||
} | ||
const out = this.data.subarray(this.ptr, this.ptr + len); | ||
this.ptr += len; | ||
return out; | ||
} | ||
} | ||
|
||
import util from "util"; | ||
// @ts-ignore | ||
global.TextDecoder = util.TextDecoder; | ||
// @ts-ignore | ||
global.TextEncoder = util.TextEncoder; | ||
// RFC 7049 | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
function decodeCBORStream(stream: Stream) { | ||
function decodeUint(stream: Stream, v: number) { | ||
let x = v & 31; | ||
if (x <= 23) { | ||
// small | ||
} else if (x === 24) { | ||
// 8-bit | ||
x = stream.getc(); | ||
} else if (x === 25) { | ||
// 16-bit | ||
x = stream.getc() << 8; | ||
x |= stream.getc(); | ||
} else if (x === 26) { | ||
// 32-bit | ||
x = stream.getc() << 24; | ||
x |= stream.getc() << 16; | ||
x |= stream.getc() << 8; | ||
x |= stream.getc(); | ||
} else if (x === 27) { | ||
// 64-bit | ||
x = stream.getc() << 56; | ||
x |= stream.getc() << 48; | ||
x |= stream.getc() << 40; | ||
x |= stream.getc() << 32; | ||
x |= stream.getc() << 24; | ||
x |= stream.getc() << 16; | ||
x |= stream.getc() << 8; | ||
x |= stream.getc(); | ||
} else { | ||
throw new Error("invalid data"); | ||
} | ||
return x; | ||
} | ||
function decode(stream: Stream, isKeyString?: boolean): Data { | ||
const v = stream.getc(); | ||
const type = v >> 5; | ||
if (type === 0) { | ||
// positive int | ||
return decodeUint(stream, v); | ||
} else if (type === 1) { | ||
// negative int | ||
return ~decodeUint(stream, v); | ||
} else if (type === 2) { | ||
// byte array | ||
return stream.chop(decodeUint(stream, v)); | ||
} else if (type === 3) { | ||
// utf-8 string | ||
return new TextDecoder("utf-8").decode( | ||
stream.chop(decodeUint(stream, v)) | ||
); | ||
} else if (type === 4) { | ||
// array | ||
const d = new Array(decodeUint(stream, v)) | ||
.fill(undefined) | ||
.map(() => decode(stream)); | ||
return d; | ||
} else if (type === 5) { | ||
// object | ||
const dMap: Map<Data, Data> = new Map(); | ||
const dObj: { [key: string]: Data } = {}; | ||
const len = decodeUint(stream, v); | ||
for (let i = 0; i < len; ++i) { | ||
const key = decode(stream); | ||
const value = decode(stream, typeof key === "string"); | ||
dMap.set(key, value); | ||
dObj[`${key}`] = value; | ||
} | ||
return isKeyString ? dObj : dMap; | ||
} | ||
return null | ||
} | ||
return decode(stream); | ||
} | ||
|
||
import cbor from "cbor"; | ||
const encodeBytes = (data: Uint8Array | never[]) => { | ||
const x = data.length; | ||
if (x === 0) { | ||
return [0x40]; | ||
} else if (x <= 23) { | ||
// small | ||
return [0x40 + x, ...data]; | ||
} else if (x < 256) { | ||
// 8-bit | ||
return [0x40 + 24, x, ...data]; | ||
} else if (x < 65536) { | ||
// 16-bit | ||
return [0x40 + 25, x >> 8, x & 0xff, ...data]; | ||
} // leave 32-bit and 64-bit unimplemented | ||
throw new Error("Too big data"); | ||
}; | ||
|
||
export function encodeToBeSigned(bodyProtected: Uint8Array, payload: Uint8Array): Uint8Array { | ||
const sig_structure = new Uint8Array([ | ||
// array w/ 4 items | ||
0x84, | ||
// #1: context: "Signature1" | ||
0x6a, | ||
0x53, | ||
0x69, | ||
0x67, | ||
0x6e, | ||
0x61, | ||
0x74, | ||
0x75, | ||
0x72, | ||
0x65, | ||
0x31, | ||
// #2: body_protected: CWT headers | ||
...encodeBytes(bodyProtected), | ||
// #3: external_aad: empty | ||
...encodeBytes([]), | ||
// #4: payload: CWT claims | ||
...encodeBytes(payload), | ||
]); | ||
const ToBeSigned = sig_structure; | ||
return ToBeSigned; | ||
} | ||
|
||
function decodeCOSEStream(stream: Stream) { | ||
const vtag = stream.getc(); | ||
const tag = vtag & 31; | ||
|
||
try { | ||
if (vtag !== 0xD2) { | ||
throw new Error('invalid data'); | ||
} | ||
const data = decodeCBORStream(stream); | ||
if (!(data instanceof Array)) { | ||
throw new Error('invalid data'); | ||
} | ||
|
||
const data1 = data[1]; | ||
if (!(data1 instanceof Map)) { | ||
throw new Error('invalid data'); | ||
} | ||
|
||
if (!(data instanceof Array) || data.length !== 4 || !(data[0] instanceof Uint8Array) || typeof data1 !== 'object' || Object.keys(data1).length !== 0 || !(data[2] instanceof Uint8Array) || !(data[3] instanceof Uint8Array)) { | ||
throw new Error('invalid data'); | ||
} | ||
|
||
return { | ||
tag, | ||
value: [ | ||
data[0], | ||
data[1], | ||
data[2], | ||
data[3], | ||
], | ||
err: undefined, | ||
}; | ||
} | ||
catch (err) { | ||
return { | ||
tag, | ||
value: [], | ||
err, | ||
} | ||
} | ||
} | ||
|
||
export const encodeOneCBOR = (obj: any): Buffer => { | ||
return cbor.encodeOne(obj, { genTypes: [Buffer, cbor.Encoder._pushBuffer] }); | ||
export const decodeCBOR = (buf: Uint8Array): Data => { | ||
const data = decodeCBORStream(new Stream(buf)) | ||
return data | ||
}; | ||
|
||
export const decodeCBOR = (buf: Buffer | Uint8Array): any => { | ||
return cbor.decode(buf); | ||
export const decodeCOSE = (buf: Uint8Array): DecodedCOSEStructure => { | ||
const data = decodeCOSEStream(new Stream(buf)) | ||
return data | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type Data = string | number | Uint8Array | Data[] | Map<Data, Data> | { [key: string]: Data } | null; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,17 @@ | ||
type DecodedCOSEValue = (Buffer | Record<string, never>)[]; | ||
import { Data } from "./cborTypes"; | ||
|
||
export interface DecodedCOSEStructure { | ||
tag: number; | ||
value: DecodedCOSEValue; | ||
err?: Error; | ||
type DecodedCOSEValue = Data[]; | ||
|
||
interface DecodedCOSEStructureSuccess { | ||
tag: number | ||
value: DecodedCOSEValue | ||
err: Error | ||
} | ||
|
||
interface DecodedCOSEStructureError { | ||
tag: number | ||
value: DecodedCOSEValue | ||
err: undefined | ||
} | ||
|
||
export type DecodedCOSEStructure = DecodedCOSEStructureSuccess | DecodedCOSEStructureError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.