Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @digitalbazaar/http-digest-header Changelog

## 2.3.0 - 2025-10-dd

### Added
- Support parsing a digest from structured field value, i.e., expressed as
a base64-encoded byte array that is wrapped in colons;
see: https://datatracker.ietf.org/doc/html/rfc9651#name-byte-sequences.

## 2.2.1 - 2025-10-08

### Fixed
Expand Down
9 changes: 8 additions & 1 deletion lib/httpDigest.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,13 @@ function _createMultihash({digest}) {
}

function _parseHeaderValue(headerValue) {
const [key, encodedDigest] = headerValue.split(/=(.+)/);
const [key, digestValue] = headerValue.split(/=(.+)/);

let encodedDigest;
let algorithm;
if(key === 'mh') {
encodedDigest = digestValue;

// if `encodedDigest` starts with `uEi`, then it is a base64url-encoded
// sha-256 multihash
if(encodedDigest.startsWith('uEi')) {
Expand All @@ -89,6 +92,10 @@ function _parseHeaderValue(headerValue) {
`Only base64url-encoded, sha-256 multihash is supported.`);
}
} else {
// per RFC 9651, the digest value could be a structured field value,
// expressed as a base64-encoded byte array wrapped in colons
encodedDigest = digestValue?.replace(/^:(.*):$/, '$1');

algorithm = key.replace('-', '').toLowerCase();
if(algorithm !== 'sha256') {
throw new Error(`Algorithm "${algorithm}" is not supported.`);
Expand Down
31 changes: 31 additions & 0 deletions test/unit/httpDigest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,37 @@ describe('http-signature-digest', () => {
should.exist(verifyResult);
verifyResult.verified.should.equal(true);
});
it('should verify a digest wrapped in colons', async () => {
const data = `{"hello": "world"}`;
const headerValue =
`sha-256=:X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=:`;
let verifyResult;
let err;
try {
verifyResult = await verifyHeaderValue({data, headerValue});
} catch(e) {
err = e;
}
should.not.exist(err);
should.exist(verifyResult);
verifyResult.verified.should.equal(true);
});
it('should verify false if a multihash digest is wrapped in colons',
async () => {
const data = '{"hello":"world"}';
const headerValue =
`mh=:uEiCTojlxqRTl6svwqNJRVM2jCcPBxy-7mRTUfGDzy2gViA:`;
let verifyResult;
let err;
try {
verifyResult = await verifyHeaderValue({data, headerValue});
} catch(e) {
err = e;
}
should.not.exist(err);
should.exist(verifyResult);
verifyResult.verified.should.equal(false);
});
it('should verify false if verifying bad data object', async () => {
const data = {hello: 'world'};
const headerValue = await createHeaderValue(
Expand Down