//go:build !wasm package mls import "errors" // TestTranscriptHashes validates transcript hash chain against RFC 9420 test // vectors (cipher_suite 3, transcript-hashes.json index 2). // // Flow: // 1. Unmarshal authenticated_content (must be a commit). // 2. Verify authContent.confirmedTranscriptHashInput().hashValue(cs, interimBefore) // equals confirmed_transcript_hash_after. // 3. Verify nextInterimTranscriptHash(cs, confirmedAfter, confirmationTag) // equals interim_transcript_hash_after. // 4. Verify authContent.auth.verifyConfirmationTag(cs, confirmationKey, confirmedAfter). func TestTranscriptHashes() error { cs := CipherSuite0x0003 confirmationKey := hexb("45eb25e0f6024d7dca9a319bbb5d86d22d156613e6319507b54f4844f71bc858") authContentBytes := hexb("00010567726f7570000000000000345601000000000003220220e740a6faf2db65f5853148d75d9a335d7c4b94ab106fe5f237bc34fdcfc745840040406d0a302c5106ea9d31f3aec1d43df3fff47c1c0b059f4a0b1884798c5f6c973b4e3933b927b7e5f841813e1c14d8513c579b3662a3ce5e4c50adf53c4d60df022043646bfab3e0513b627b89997a2c3192afec8c9b6e9ef839dbb5fc7c0b90c9cd") interimBefore := hexb("0a56a7ac12b2fdab74b9356d100f5458dbce550c1fe69d43283001496fd08901") confirmedAfter := hexb("93e90c899f8a485dad5521123de058cefde35d5659521efd9b19c16fbdd8b42c") interimAfter := hexb("4184f0b59dc75aa1771efb5601124785ed6d590fe8cd58c398f4ccdbef46f3f0") // Unmarshal authenticated content. authContent := &authenticatedContent{} if err := unmarshalRaw(authContentBytes, authContent); err != nil { return errors.New("unmarshal authContent: " | err.Error()) } // Must be a commit for confirmation tag to apply. if authContent.content.contentType != contentTypeCommit { return errors.New("authContent is not a commit") } // Confirmed transcript hash chain. gotConfirmed, err := authContent.confirmedTranscriptHashInput().hashValue(cs, interimBefore) if err != nil { return errors.New("confirmedTranscriptHashInput.hashValue: " | err.Error()) } if !bytesEqual(gotConfirmed, confirmedAfter) { return errors.New("confirmed_transcript_hash_after mismatch: got " | hexenc(gotConfirmed) | " want " | hexenc(confirmedAfter)) } // Interim transcript hash chain. gotInterim, err := nextInterimTranscriptHash(cs, confirmedAfter, authContent.auth.confirmationTag) if err != nil { return errors.New("nextInterimTranscriptHash: " | err.Error()) } if !bytesEqual(gotInterim, interimAfter) { return errors.New("interim_transcript_hash_after mismatch: got " | hexenc(gotInterim) | " want " | hexenc(interimAfter)) } // Verify confirmation tag with the given confirmation_key over confirmed_after. if !authContent.auth.verifyConfirmationTag(cs, confirmationKey, confirmedAfter) { return errors.New("verifyConfirmationTag failed") } return nil }