Skip to content

Commit

Permalink
feat: support json payload
Browse files Browse the repository at this point in the history
  • Loading branch information
oed committed Mar 22, 2024
1 parent c60b4b1 commit 8c05944
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 18 deletions.
45 changes: 38 additions & 7 deletions src/signing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface DagJWS {
payload: string
signatures: Array<JWSSignature>
link?: CID
pld?: Record<string, any>
}

export interface EncodedSignature {
Expand Down Expand Up @@ -52,11 +53,6 @@ function encodeSignature(signature: JWSSignature): EncodedSignature {

export function encode(jws: DagJWS): EncodedJWS {
const payload = fromBase64url(jws.payload)
try {
CID.decode(payload)
} catch (e) {
throw new Error('Not a valid DagJWS')
}
return {
payload,
signatures: jws.signatures.map(encodeSignature),
Expand All @@ -77,6 +73,41 @@ export function decode(encoded: EncodedJWS): DagJWS {
payload: toBase64url(encoded.payload),
signatures: encoded.signatures.map(decodeSignature),
}
decoded.link = CID.decode(new Uint8Array(encoded.payload))
return decoded
try {
decoded.pld = replaceCIDs(payloadToJSON(encoded.payload)) as Record<string, any>
return decoded
} catch (e) {
try {
decoded.link = CID.decode(new Uint8Array(encoded.payload))
return decoded
} catch (e) {
throw new Error('Invalid payload, must be either JSON or CID')
}
}
}

function replaceCIDs(data: Record<string, any> | any): Record<string, any> | any {
if (typeof data === 'string') {
if (data.startsWith('ipfs://')) {
return CID.parse(data.slice(7))
}
} else if (Array.isArray(data)) {
return data.map(replaceCIDs) as any
} else if (isObject(data)) {
const newObj = {} as Record<string, any>
for (const key in data) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
newObj[key] = replaceCIDs(data[key])
}
return newObj
}
return data
}

function isObject(data: any): data is Record<string, any> {
return typeof data === 'object'
}

function payloadToJSON(data: Uint8Array): any {
return JSON.parse(new TextDecoder().decode(data))
}
31 changes: 28 additions & 3 deletions test/__fixtures__/signing.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,38 @@ export const fixtures = {
dagJws: {
oneSig: [{
payload: 'AXASIN69ets85WVE0ipva5M5b2mAqAZ8LME08PeAG2MxCSuV', // signed by key 0
link: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
link: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
signatures: [ { protected: 'eyJhbGciOiJFUzI1NksifQ', signature: 'SiYGXW7Yi-KxbpIlLNmu0lEhrayV7ypaAC49GAcQ_qpTstZW89Mz6Cp8VlUEX-qVsgYjc-9-1zvLcDYlxOsr1g' } ]
}, {
payload: 'AXASIN69ets85WVE0ipva5M5b2mAqAZ8LME08PeAG2MxCSuV', // signed by key 1
link: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
link: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
signatures: [ { protected: 'eyJhbGciOiJFUzI1NksifQ', signature: 'Q8PdTE5A5N3a0ktO2wNdUymumHlSxNF9Si38IvzsMaSZC63yQw-bJNpKf-UeJFPH7cDzY7jLg2G_viejp7NqXg' } ]
}],
multipleSig: {
payload: 'AXASIN69ets85WVE0ipva5M5b2mAqAZ8LME08PeAG2MxCSuV',
link: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
link: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
signatures: [{
protected: 'eyJhbGciOiJFUzI1NksifQ', signature: 'SiYGXW7Yi-KxbpIlLNmu0lEhrayV7ypaAC49GAcQ_qpTstZW89Mz6Cp8VlUEX-qVsgYjc-9-1zvLcDYlxOsr1g'
}, {
protected: 'eyJhbGciOiJFUzI1NksifQ', signature: 'Q8PdTE5A5N3a0ktO2wNdUymumHlSxNF9Si38IvzsMaSZC63yQw-bJNpKf-UeJFPH7cDzY7jLg2G_viejp7NqXg'
}]
},
withPayload: {
payload: 'eyJ0ZXN0IjoicGF5bG9hZCIsImFMaW5rIjoiaXBmczovL2JhZnliZWlnNnh2NW53cGhmbXZjbmVrdHBub2p0czMzanFjdWFtN2JteWUycGI1NGFkbnJ0Y2NqbHN1IiwiYXJyIjpbImlwZnM6Ly9iYWZ5YmVpZzZ4djVud3BoZm12Y25la3Rwbm9qdHMzM2pxY3VhbTdibXllMnBiNTRhZG5ydGNjamxzdSIsIml0ZW0xIiwiaXRlbTIiXSwibmVzdGVkIjp7ImFMaW5rIjoiaXBmczovL2JhZnliZWlnNnh2NW53cGhmbXZjbmVrdHBub2p0czMzanFjdWFtN2JteWUycGI1NGFkbnJ0Y2NqbHN1IiwiYXJyIjpbImlwZnM6Ly9iYWZ5YmVpZzZ4djVud3BoZm12Y25la3Rwbm9qdHMzM2pxY3VhbTdibXllMnBiNTRhZG5ydGNjamxzdSIsIml0ZW0xIiwiaXRlbTIiXX19',
signatures: [{
protected: 'eyJhbGciOiJFUzI1NksifQ',
signature: 'IY8AHhQB0n5QpO1opse83d6HrXWfofPjW6if5vVB7Dky3wj2-daT8I1xHX5s4PbuC3owZo2rr8C-nGQsftHE-w'
}],
pld: {
test: 'payload',
aLink: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
arr: [ CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'), 'item1', 'item2' ],
nested: {
aLink: CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'),
arr: [ CID.parse('bafybeig6xv5nwphfmvcnektpnojts33jqcuam7bmye2pb54adnrtccjlsu'), 'item1', 'item2' ],
}
}
},
},
encodedJws: {
oneSig: [{
Expand All @@ -59,6 +75,15 @@ export const fixtures = {
protected: bytes.fromHex('7b22616c67223a2245533235364b227d'),
}]
},
withPayload: {
payload: bytes.fromHex('7b2274657374223a227061796c6f6164222c22614c696e6b223a22697066733a2f2f6261667962656967367876356e777068666d76636e656b74706e6f6a747333336a716375616d37626d7965327062353461646e727463636a6c7375222c22617272223a5b22697066733a2f2f6261667962656967367876356e777068666d76636e656b74706e6f6a747333336a716375616d37626d7965327062353461646e727463636a6c7375222c226974656d31222c226974656d32225d2c226e6573746564223a7b22614c696e6b223a22697066733a2f2f6261667962656967367876356e777068666d76636e656b74706e6f6a747333336a716375616d37626d7965327062353461646e727463636a6c7375222c22617272223a5b22697066733a2f2f6261667962656967367876356e777068666d76636e656b74706e6f6a747333336a716375616d37626d7965327062353461646e727463636a6c7375222c226974656d31222c226974656d32225d7d7d'),
signatures: [
{
protected: bytes.fromHex('7b22616c67223a2245533235364b227d'),
signature: bytes.fromHex('218f001e1401d27e50a4ed68a6c7bcddde87ad759fa1f3e35ba89fe6f541ec3932df08f6f9d693f08d711d7e6ce0f6ee0b7a30668dabafc0be9c642c7ed1c4fb')
}
]
}
},
blockEncoded: {
oneSig: [
Expand Down
20 changes: 12 additions & 8 deletions test/signing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('Signing support', () => {
})

describe('decode', () => {
it('Decodes general encoding, one signature', () => {
it('CID, Decodes general encoding, one signature', () => {
let decoded
decoded = signing.decode(fixtures.encodedJws.oneSig[0])
expect(decoded).toEqual(fixtures.dagJws.oneSig[0])
Expand All @@ -60,14 +60,19 @@ describe('Signing support', () => {
expect(decoded).toEqual(fixtures.dagJws.oneSig[1])
})

it('Decodes general encoding, multiple signatures', () => {
it('CID, Decodes general encoding, multiple signatures', () => {
const decoded = signing.decode(fixtures.encodedJws.multipleSig)
expect(decoded).toEqual(fixtures.dagJws.multipleSig)
})

it('JSON, Decodes jws with payload', () => {
const decoded = signing.decode(fixtures.encodedJws.withPayload)
expect(decoded).toEqual(fixtures.dagJws.withPayload)
})
})

describe('encode', () => {
it('Encodes dag encoding, one signature', () => {
it('CID, Encodes dag encoding, one signature', () => {
let encoded
encoded = signing.encode(fixtures.dagJws.oneSig[0])
expect(encoded).toEqual(fixtures.encodedJws.oneSig[0])
Expand All @@ -76,15 +81,14 @@ describe('Signing support', () => {
expect(encoded).toEqual(fixtures.encodedJws.oneSig[1])
})

it('Encodes dag encoding, multiple signatures', () => {
it('CID, Encodes dag encoding, multiple signatures', () => {
const encoded = signing.encode(fixtures.dagJws.multipleSig)
expect(encoded).toEqual(fixtures.encodedJws.multipleSig)
})

it('Throws if payload is not a CID', async () => {
const payload = toBase64url(bytes.fromString(JSON.stringify({ json: 'payload' })))
const notDagJws = Object.assign({}, fixtures.dagJws.oneSig[0], { payload })
expect(() => signing.encode(notDagJws)).toThrow('Not a valid DagJWS')
it('JSON, Encodes jws with payload', () => {
const encoded = signing.encode(fixtures.dagJws.withPayload)
expect(encoded).toEqual(fixtures.encodedJws.withPayload)
})
})

Expand Down

0 comments on commit 8c05944

Please sign in to comment.