test_transcript_hashes.mx raw

   1  //go:build !wasm
   2  
   3  package mls
   4  
   5  import "errors"
   6  
   7  // TestTranscriptHashes validates transcript hash chain against RFC 9420 test
   8  // vectors (cipher_suite 3, transcript-hashes.json index 2).
   9  //
  10  // Flow:
  11  //   1. Unmarshal authenticated_content (must be a commit).
  12  //   2. Verify authContent.confirmedTranscriptHashInput().hashValue(cs, interimBefore)
  13  //      equals confirmed_transcript_hash_after.
  14  //   3. Verify nextInterimTranscriptHash(cs, confirmedAfter, confirmationTag)
  15  //      equals interim_transcript_hash_after.
  16  //   4. Verify authContent.auth.verifyConfirmationTag(cs, confirmationKey, confirmedAfter).
  17  func TestTranscriptHashes() error {
  18  	cs := CipherSuite0x0003
  19  
  20  	confirmationKey := hexb("45eb25e0f6024d7dca9a319bbb5d86d22d156613e6319507b54f4844f71bc858")
  21  	authContentBytes := hexb("00010567726f7570000000000000345601000000000003220220e740a6faf2db65f5853148d75d9a335d7c4b94ab106fe5f237bc34fdcfc745840040406d0a302c5106ea9d31f3aec1d43df3fff47c1c0b059f4a0b1884798c5f6c973b4e3933b927b7e5f841813e1c14d8513c579b3662a3ce5e4c50adf53c4d60df022043646bfab3e0513b627b89997a2c3192afec8c9b6e9ef839dbb5fc7c0b90c9cd")
  22  	interimBefore := hexb("0a56a7ac12b2fdab74b9356d100f5458dbce550c1fe69d43283001496fd08901")
  23  	confirmedAfter := hexb("93e90c899f8a485dad5521123de058cefde35d5659521efd9b19c16fbdd8b42c")
  24  	interimAfter := hexb("4184f0b59dc75aa1771efb5601124785ed6d590fe8cd58c398f4ccdbef46f3f0")
  25  
  26  	// Unmarshal authenticated content.
  27  	authContent := &authenticatedContent{}
  28  	if err := unmarshalRaw(authContentBytes, authContent); err != nil {
  29  		return errors.New("unmarshal authContent: " | err.Error())
  30  	}
  31  
  32  	// Must be a commit for confirmation tag to apply.
  33  	if authContent.content.contentType != contentTypeCommit {
  34  		return errors.New("authContent is not a commit")
  35  	}
  36  
  37  	// Confirmed transcript hash chain.
  38  	gotConfirmed, err := authContent.confirmedTranscriptHashInput().hashValue(cs, interimBefore)
  39  	if err != nil {
  40  		return errors.New("confirmedTranscriptHashInput.hashValue: " | err.Error())
  41  	}
  42  	if !bytesEqual(gotConfirmed, confirmedAfter) {
  43  		return errors.New("confirmed_transcript_hash_after mismatch: got " | hexenc(gotConfirmed) | " want " | hexenc(confirmedAfter))
  44  	}
  45  
  46  	// Interim transcript hash chain.
  47  	gotInterim, err := nextInterimTranscriptHash(cs, confirmedAfter, authContent.auth.confirmationTag)
  48  	if err != nil {
  49  		return errors.New("nextInterimTranscriptHash: " | err.Error())
  50  	}
  51  	if !bytesEqual(gotInterim, interimAfter) {
  52  		return errors.New("interim_transcript_hash_after mismatch: got " | hexenc(gotInterim) | " want " | hexenc(interimAfter))
  53  	}
  54  
  55  	// Verify confirmation tag with the given confirmation_key over confirmed_after.
  56  	if !authContent.auth.verifyConfirmationTag(cs, confirmationKey, confirmedAfter) {
  57  		return errors.New("verifyConfirmationTag failed")
  58  	}
  59  
  60  	return nil
  61  }