Skip to content

Commit b5aa4f1

Browse files
authored
proper utf-8 encoding in DSSE PAE (#1657)
Signed-off-by: Brian DeHamer <bdehamer@github.com>
1 parent c7a34e0 commit b5aa4f1

3 files changed

Lines changed: 38 additions & 8 deletions

File tree

.changeset/dirty-games-juggle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sigstore/core': patch
3+
---
4+
5+
Apply UTF-8 encoding to payload type during PAE calculation

packages/core/src/__tests__/dsse.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,30 @@ describe('preAuthEncoding', () => {
2323
const pae = preAuthEncoding(payloadType, payload);
2424
expect(pae).toEqual(Buffer.from('DSSEv1 10 text/plain 13 Hello, World!'));
2525
});
26+
27+
it('should use utf-8 byte length for non-ASCII payloadType', () => {
28+
// U+00E9 (é) is 2 bytes in UTF-8
29+
const nonAsciiType = 'application/typ\u00e9';
30+
const pae = preAuthEncoding(nonAsciiType, payload);
31+
32+
const typeBytes = Buffer.from(nonAsciiType, 'utf-8');
33+
expect(typeBytes.length).toBe(17); // 16 ASCII chars + 2 byte é = 17
34+
35+
const expected = Buffer.concat([
36+
Buffer.from(`DSSEv1 ${typeBytes.length} `, 'ascii'),
37+
typeBytes,
38+
Buffer.from(` ${payload.length} `, 'ascii'),
39+
payload,
40+
]);
41+
expect(pae).toEqual(expected);
42+
});
43+
44+
it('should produce distinct PAE for Unicode payloadType variants', () => {
45+
// U+0174 has same low byte as 't' (0x74) — the old ascii
46+
// encoding would have mapped both to the same byte
47+
const original = preAuthEncoding('text/plain', payload);
48+
const mutant = preAuthEncoding('\u0174ext/plain', payload);
49+
50+
expect(original).not.toEqual(mutant);
51+
});
2652
});

packages/core/src/dsse.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ const PAE_PREFIX = 'DSSEv1';
1717

1818
// DSSE Pre-Authentication Encoding
1919
export function preAuthEncoding(payloadType: string, payload: Buffer): Buffer {
20-
const prefix = [
21-
PAE_PREFIX,
22-
payloadType.length,
23-
payloadType,
24-
payload.length,
25-
'',
26-
].join(' ');
20+
const typeBytes = Buffer.from(payloadType, 'utf-8');
2721

28-
return Buffer.concat([Buffer.from(prefix, 'ascii'), payload]);
22+
return Buffer.concat([
23+
Buffer.from(`${PAE_PREFIX} ${typeBytes.length} `, 'ascii'),
24+
typeBytes,
25+
Buffer.from(` ${payload.length} `, 'ascii'),
26+
payload,
27+
]);
2928
}

0 commit comments

Comments
 (0)