Skip to content

Commit

Permalink
Merge pull request #9 from transmute-industries/feat/refactor-registr…
Browse files Browse the repository at this point in the history
…y-examples

Update scitt registry related diagnostics
  • Loading branch information
OR13 authored Oct 24, 2023
2 parents 08fd3ff + 9d63a44 commit 245aefe
Show file tree
Hide file tree
Showing 15 changed files with 584 additions and 109 deletions.
73 changes: 40 additions & 33 deletions src/rfc/beautify/beautifyProtectedHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,48 @@ import { addComment } from "./addComment"


import cbor from "../../cbor";
import { maxBstrTruncateLength } from './constants'

// https://www.iana.org/assignments/cose/cose.xhtml
const protectedHeaderTagToDescription = (tag: number) => {
const descriptions = new Map();
descriptions.set(1, 'Algorithm')
descriptions.set(2, 'Critical parameters')
descriptions.set(3, 'Content type')
descriptions.set(4, 'Key identifier')
descriptions.set(-11111, 'Verifiable data structure')

return descriptions.get(tag) || `${tag} unknown cbor content`
}

import { bufferToTruncatedBstr } from "./bufferToTruncatedBstr";
import { default as tags } from "../../unprotectedHeader";


export const beautifyProtectedHeader = async (data: Buffer | Uint8Array) => {
const diagnostic = await cbor.web.diagnose(data)
const mapItemSpacer = ` `
let result = diagnostic;
result = result.replace('{', `{\n${mapItemSpacer}`)
result = result.replace(/, /g, `,\n${mapItemSpacer}`)
result = result.replace('}', `\n}`)
result = result.split('\n').map((line: string) => {
if (line.trim() === '{') {
line = addComment(`{`, `Protected`)
return line
}
if (line.includes(`h'`) && line.length > maxBstrTruncateLength) {
line = line.replace(/h'(.{8}).+(.{8})'/g, `h'$1...$2'`)
}
if (line === '' || line.trim() === '{' || line.trim() === '}') {
return line
const protectedHeader = await cbor.web.decode(data)
const lines = [] as string[]
for (const [label, value] of protectedHeader.entries()) {
if (label === 1) {
lines.push(addComment(` ${label}: ${value},`, 'Algorithm'))
} else if (label === 2) {
lines.push(addComment(` ${label}: ${value},`, 'Criticality'))
} else if (label === 3) {
lines.push(addComment(` ${label}: ${value},`, 'Content type'))
} else if (label === 4) {
lines.push(addComment(` ${label}: ${bufferToTruncatedBstr(value)},`, 'Key identifier'))
} else if (label === 13) {
lines.push(addComment(` ${label}: {`, 'CWT Claims'))
for (const [claimKey, claimValue] of value.entries()) {
if (claimKey === 1) {
lines.push(addComment(` ${claimKey}: ${claimValue},`, 'Issuer'))
} else if (claimKey === 2) {
lines.push(addComment(` ${claimKey}: ${claimValue},`, 'Subject'))
} else {
lines.push(addComment(` ${claimKey}: ${claimValue},`, 'Claim'))
}

}
lines.push(` }`)
} else if (label === tags.verifiable_data_structure) {
lines.push(addComment(` ${label}: ${value},`, 'Verifiable Data Structure'))
} else {
lines.push(addComment(` ${label}: ${value},`, 'Parameter'))
}
const maybeIntLabel = parseInt(line.split(':')[0], 10)
return addComment(line, `${protectedHeaderTagToDescription(maybeIntLabel)}`)
}).join('\n')
return result

}


return `
${addComment('{', 'Protected')}
${lines.join('\n')}
}
`.trim()
}
5 changes: 4 additions & 1 deletion src/rfc/beautify/beautifyReceipts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { bufferToTruncatedBstr } from './bufferToTruncatedBstr';

import { beautifyCoseSign1 } from "./beautifyCoseSign1";

import { default as tags } from '../../unprotectedHeader'


export const beautifyReceipts = async (receipts: Buffer[]) => {
const blocks = [
`${addComment(` 300: [`, `Receipts (${receipts.length})`)}
`${addComment(` ${tags.scitt_receipt}: [`, `Receipts (${receipts.length})`)}
${receipts.map((receipt, i: number) => {
const truncated = bufferToTruncatedBstr(receipt)
return addComment(` ${truncated}`, `Receipt ${i + 1}`)
Expand Down
3 changes: 2 additions & 1 deletion src/scitt/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as statement from './statement'
import * as receipt from './receipt'

export { receipt }
export { statement, receipt }
8 changes: 7 additions & 1 deletion src/scitt/receipt/issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { SecretCoseKeyMap } from '../../key/types'
import getSigner from "../../lib/signer"

export type RequestScittReceipt = {
iss: string
sub: string
index: number
entries?: ArrayBuffer[]
leaves?: Uint8Array[]
Expand All @@ -24,7 +26,7 @@ export type RequestScittReceipt = {
secretCoseKey?: SecretCoseKeyMap
}

export const issue = async ({ index, entries, leaves, signer, secretCoseKey }: RequestScittReceipt): Promise<ArrayBuffer> => {
export const issue = async ({ iss, sub, index, entries, leaves, signer, secretCoseKey }: RequestScittReceipt): Promise<ArrayBuffer> => {
let treeLeaves = leaves
if (entries) {
treeLeaves = entries.map((entry: ArrayBuffer) => {
Expand All @@ -41,12 +43,16 @@ export const issue = async ({ index, entries, leaves, signer, secretCoseKey }: R
)
let receiptSigner = signer
const protectedHeaderMap = new Map()
const cwtClaimsMap = new Map()
cwtClaimsMap.set(1, iss)
cwtClaimsMap.set(2, sub)
if (secretCoseKey) {
const secretKeyJwk = await key.exportJWK(secretCoseKey as any)
secretKeyJwk.alg = key.utils.algorithms.toJOSE.get(secretCoseKey.get(3) as number)
protectedHeaderMap.set(1, secretCoseKey.get(3) as number) // set alg from the restricted key
protectedHeaderMap.set(4, secretCoseKey.get(2) as number) // set kid from the restricted key
protectedHeaderMap.set(unprotectedHeader.verifiable_data_structure, 1) // using RFC9162 verifiable data structure
protectedHeaderMap.set(13, cwtClaimsMap)
receiptSigner = getSigner({
secretKeyJwk: secretKeyJwk as any
})
Expand Down
26 changes: 26 additions & 0 deletions src/scitt/statement/addReceipt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

import cbor from '../../cbor'

import { default as tags } from '../../unprotectedHeader'

type RequestAddReceipt = {
statement: ArrayBuffer // really signed statement
receipt: ArrayBuffer
}

export const addReceipt = ({ statement, receipt }: RequestAddReceipt) => {
const decoded = cbor.decode(statement)
let unprotectedHeader = decoded.value[1]
if (!(unprotectedHeader instanceof Map)) {
unprotectedHeader = new Map()
}
const existingReceipts = unprotectedHeader.get(tags.scitt_receipt)
if (!existingReceipts) {
unprotectedHeader.set(tags.scitt_receipt, [receipt])
} else {
existingReceipts.push(receipt)
}
decoded.value[1] = unprotectedHeader
return cbor.encode(decoded)
}

2 changes: 2 additions & 0 deletions src/scitt/statement/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './issue'
export * from './addReceipt'
44 changes: 44 additions & 0 deletions src/scitt/statement/issue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@


import detachPayload from '../../detachPayload'
import { typedArrayToBuffer } from '../../utils'
import * as key from '../../key'
import { SecretCoseKeyMap } from '../../key/types'
import getSigner from "../../lib/signer"

export type RequestScittSignedStatement = {
iss: string
sub: string
cty: string
payload: ArrayBuffer
signer?: any,
secretCoseKey?: SecretCoseKeyMap
}

export const issue = async ({ iss, sub, cty, payload, signer, secretCoseKey }: RequestScittSignedStatement): Promise<ArrayBuffer> => {
let receiptSigner = signer
const protectedHeaderMap = new Map()
const unprotectedHeaderMap = new Map()
const cwtClaimsMap = new Map()
cwtClaimsMap.set(1, iss)
cwtClaimsMap.set(2, sub)
if (secretCoseKey) {
const secretKeyJwk = await key.exportJWK(secretCoseKey as any)
secretKeyJwk.alg = key.utils.algorithms.toJOSE.get(secretCoseKey.get(3) as number)
protectedHeaderMap.set(1, secretCoseKey.get(3) as number) // set alg from the restricted key
protectedHeaderMap.set(3, cty) // content type of the payload
protectedHeaderMap.set(4, secretCoseKey.get(2) as number) // set kid from the restricted key
protectedHeaderMap.set(13, cwtClaimsMap)
receiptSigner = getSigner({
secretKeyJwk: secretKeyJwk as any
})
}
const signedStatement = await receiptSigner.sign({
protectedHeader: protectedHeaderMap,
unprotectedHeader: unprotectedHeaderMap,
payload
})
const { signature } = await detachPayload(signedStatement)
return typedArrayToBuffer(signature)

}
2 changes: 1 addition & 1 deletion src/types/UnprotectedHeader.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export type UnprotectedHeader = Map<number, string | number | object>
export type UnprotectedHeader = Map<number | string, string | number | object>
6 changes: 3 additions & 3 deletions src/unprotectedHeader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ const unprotectedHeaderTags = {
counter_signature: 7,

// will be registered in https://github.com/ietf-scitt/draft-steele-cose-merkle-tree-proofs
verifiable_data_structure: -11111, // int
verifiable_data_structure_proofs: -22222, // a map of ints to array of bstrs
verifiable_data_structure: -111, // 'TBD_1', // int
verifiable_data_structure_proofs: -222, //'TBD_2', // a map of ints to array of bstrs

// will be registered in https://datatracker.ietf.org/doc/draft-birkholz-scitt-receipts/
scitt_receipt: -33333,
scitt_receipt: -333, //'TBD_3',
}

const unprotectedHeader = {
Expand Down
4 changes: 2 additions & 2 deletions src/verifiable_data_structure_proofs.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@


const verifiable_data_structure_proofs = {
inclusion_proof: 1,
consistency_proof: 2,
inclusion_proof: -1,
consistency_proof: -2,
}

export default verifiable_data_structure_proofs
8 changes: 4 additions & 4 deletions test/cometre/consistency-proof.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
[
h'a3012604...392b6601', / Protected /
{ / Unprotected /
-22222: { / Proofs /
2: [ / Consistency proofs (1) /
-222: { / Proofs /
-2: [ / Consistency proofs (1) /
h'83040682...2e73a8ab', / Consistency proof 1 /
]
},
},
h'430b6fd7...f74c7fc4', / Payload /
h'9ddf2848...90b06dad' / Signature /
h'd97befea...f30631cb' / Signature /
]
)
~~~~
Expand All @@ -19,7 +19,7 @@
{ / Protected /
1: -7, / Algorithm /
4: h'68747470...6d706c65', / Key identifier /
-11111: 1 / Verifiable data structure /
-11111: 1, / Parameter /
}
~~~~

Expand Down
8 changes: 4 additions & 4 deletions test/cometre/inclusion-proof.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
[
h'a3012604...392b6601', / Protected /
{ / Unprotected /
-22222: { / Proofs /
1: [ / Inclusion proofs (1) /
-222: { / Proofs /
-1: [ / Inclusion proofs (1) /
h'83040282...1f487bb1', / Inclusion proof 1 /
]
},
},
h'', / Detached payload /
h'affc058e...c340d8bc' / Signature /
h'94d8f4a3...250f27b2' / Signature /
]
)
~~~~
Expand All @@ -19,7 +19,7 @@
{ / Protected /
1: -7, / Algorithm /
4: h'68747470...6d706c65', / Key identifier /
-11111: 1 / Verifiable data structure /
-11111: 1, / Parameter /
}
~~~~

Expand Down
Loading

0 comments on commit 245aefe

Please sign in to comment.