Skip to content

Commit 86c3d24

Browse files
committed
fix assertion hash
1 parent b7dcd8a commit 86c3d24

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

lib/tdf3/src/assertions.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ export function isAssertionConfig(obj: unknown): obj is AssertionConfig {
110110
*/
111111
export async function verify(
112112
thiz: Assertion,
113-
aggregateHash: string,
114-
key: AssertionKey
113+
aggregateHash: Uint8Array,
114+
key: AssertionKey,
115+
isLegacyTDF: boolean
115116
): Promise<void> {
116117
let payload: AssertionPayload;
117118
try {
@@ -126,14 +127,23 @@ export async function verify(
126127

127128
// Get the hash of the assertion
128129
const hashOfAssertion = await hash(thiz);
129-
const combinedHash = aggregateHash + hashOfAssertion;
130-
const encodedHash = base64.encode(combinedHash);
131130

132131
// check if assertionHash is same as hashOfAssertion
133132
if (hashOfAssertion !== assertionHash) {
134133
throw new IntegrityError('Assertion hash mismatch');
135134
}
136135

136+
let encodedHash: string;
137+
if (isLegacyTDF) {
138+
const aggregateHashAsStr = new TextDecoder('utf-8').decode(aggregateHash);
139+
const combinedHash = aggregateHashAsStr + hashOfAssertion;
140+
encodedHash = base64.encode(combinedHash);
141+
} else {
142+
const combinedHash = concatenateUint8Arrays(aggregateHash,
143+
new Uint8Array(hex.decodeArrayBuffer(assertionHash)));
144+
encodedHash = base64.encodeArrayBuffer(combinedHash);
145+
}
146+
137147
// check if assertionSig is same as encodedHash
138148
if (assertionSig !== encodedHash) {
139149
throw new IntegrityError('Failed integrity check on assertion signature');
@@ -144,7 +154,7 @@ export async function verify(
144154
* Creates an Assertion object with the specified properties.
145155
*/
146156
export async function CreateAssertion(
147-
aggregateHash: string,
157+
aggregateHash: Uint8Array,
148158
assertionConfig: AssertionConfig
149159
): Promise<Assertion> {
150160
if (!assertionConfig.signingKey) {
@@ -162,8 +172,8 @@ export async function CreateAssertion(
162172
};
163173

164174
const assertionHash = await hash(a);
165-
const combinedHash = aggregateHash + assertionHash;
166-
const encodedHash = base64.encode(combinedHash);
175+
const combinedHash = concatenateUint8Arrays(aggregateHash, new Uint8Array(hex.decodeArrayBuffer(assertionHash)));
176+
const encodedHash = base64.encodeArrayBuffer(combinedHash);
167177

168178
return await sign(a, assertionHash, encodedHash, assertionConfig.signingKey);
169179
}
@@ -189,3 +199,13 @@ export type AssertionVerificationKeys = {
189199
DefaultKey?: AssertionKey;
190200
Keys: Record<string, AssertionKey>;
191201
};
202+
203+
function concatenateUint8Arrays(array1: Uint8Array, array2: Uint8Array): Uint8Array {
204+
const combinedLength = array1.length + array2.length;
205+
const combinedArray = new Uint8Array(combinedLength);
206+
207+
combinedArray.set(array1, 0);
208+
combinedArray.set(array2, array1.length);
209+
210+
return combinedArray;
211+
}

lib/tdf3/src/tdf.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -755,8 +755,7 @@ export async function writeStream(cfg: EncryptConfiguration): Promise<DecoratedR
755755
alg: 'HS256',
756756
key: new Uint8Array(cfg.keyForEncryption.unwrappedKeyBinary.asArrayBuffer()),
757757
};
758-
const combinedHashString = new TextDecoder().decode(aggregateHash);
759-
const assertion = await assertions.CreateAssertion(combinedHashString, {
758+
const assertion = await assertions.CreateAssertion(aggregateHash, {
760759
...assertionConfig,
761760
signingKey,
762761
});
@@ -1239,16 +1238,20 @@ export async function readStream(cfg: DecryptConfiguration) {
12391238
// check if the TDF is a legacy TDF
12401239
const isLegacyTDF = manifest.tdf_spec_version ? false : true;
12411240

1242-
// check the combined string of hashes
1243-
const aggregateHash = segments.map(({ hash }) => base64.decode(hash)).join('');
1241+
// Decode each hash and store it in an array of Uint8Array
1242+
const segmentHashList = segments.map(({ hash }) => new Uint8Array(base64.decodeArrayBuffer(hash)));
1243+
1244+
// Concatenate all segment hashes into a single Uint8Array
1245+
const aggregateHash = await concatenateUint8Array(segmentHashList);
1246+
12441247
const integrityAlgorithm = rootSignature.alg;
12451248
if (integrityAlgorithm !== 'GMAC' && integrityAlgorithm !== 'HS256') {
12461249
throw new UnsupportedError(`Unsupported integrity alg [${integrityAlgorithm}]`);
12471250
}
12481251

12491252
const payloadForSigCalculation = isLegacyTDF
1250-
? Binary.fromString(hex.encode(aggregateHash))
1251-
: Binary.fromString(aggregateHash);
1253+
? Binary.fromString(hex.encodeArrayBuffer(aggregateHash))
1254+
: Binary.fromArrayBuffer(aggregateHash.buffer);
12521255
const payloadSigInHex = await getSignature(
12531256
keyForDecryption,
12541257
payloadForSigCalculation,
@@ -1278,7 +1281,7 @@ export async function readStream(cfg: DecryptConfiguration) {
12781281
assertionKey = foundKey;
12791282
}
12801283
}
1281-
await assertions.verify(assertion, aggregateHash, assertionKey);
1284+
await assertions.verify(assertion, aggregateHash, assertionKey, isLegacyTDF);
12821285
}
12831286
}
12841287

0 commit comments

Comments
 (0)