javascript - What is the purpose of the computed_hashes.json and verified_contents.json files in a secure Chrome extension? - St

I've seen some Chrome extensions that hashes their folder and file names. They have a folder named

I've seen some Chrome extensions that hashes their folder and file names. They have a folder named 'metadata' and two files inside it: 'puted_hashes.json' and 'verified_contents.json'. What are these files, what do they do and how can I get them or use them?

I've seen some Chrome extensions that hashes their folder and file names. They have a folder named 'metadata' and two files inside it: 'puted_hashes.json' and 'verified_contents.json'. What are these files, what do they do and how can I get them or use them?

Share Improve this question edited Jul 7, 2022 at 8:30 Glenn 'devalias' Grant 2,4762 gold badges27 silver badges34 bronze badges asked Mar 4, 2018 at 18:20 Xenz LSDXenz LSD 711 silver badge4 bronze badges 6
  • 1 Chrome creates those automatically, not extensions. – woxxom Commented Mar 4, 2018 at 18:20
  • So my Chrome extension will hash the file and folder names automatically? – Xenz LSD Commented Mar 4, 2018 at 18:22
  • 1 No, your extension won't do anything. Chrome does that. – woxxom Commented Mar 4, 2018 at 18:23
  • @wOxxOm Do you know the hashing algorithm of puted_hashes.json ? – SebMa Commented Sep 11, 2020 at 10:08
  • No, but it should be somewhere in the source code. – woxxom Commented Sep 11, 2020 at 10:10
 |  Show 1 more ment

1 Answer 1

Reset to default 8

puted_hashes.json

puted_hashes.json calculates the SHA256 hash of the blocks of the files included in the extension, which is presumably used for file integrity and/or security purposes to ensure the files haven't been corrupted/tampered with.

I go into this in depth in this StackOverflow answer, where I reference the various relevant sections in the Chromium source code.

The main relevant files are:

  • extensions/browser/puted_hashes.h
  • extensions/browser/puted_hashes

And within this, the main relevant functions are:

  • Compute
  • ComputeAndCheckResourceHash
  • GetHashesForContent

And the actual hash calculation can be seen in the ComputedHashes::GetHashesForContent function.

verified_contents.json

Short Answer

This is used for file integrity and/or security purposes to ensure that the extension files haven't been corrupted/tampered with.

verified_contents.json ensures that the Base64 encoded payload of the signed_content object within the object with a description of treehash per file validates against the signature of the object within signatures that has a header.kid of webstore. This is validated using crypto::SignatureVerifier::RSA_PKCS1_SHA256 across the concatenated values of protected + . + payload.

If the signature validates correctly, the SHA256 hash of the blocks of the files included in the extension are then calculated and pared as per puted_hashes.json (described above).

Deep Dive Explanation

To determine the internal specifics of how verified_contents.json is created/validated, we can search the chromium source code for verified_contents as follows:

  • https://source.chromium/search?q=verified_contents

This returns a number of interesting files, including:

  • extensions/browser/verified_contents.h
  • extensions/browser/verified_contents

Looking in verified_contents.h we can see a ment describing the purpose of verified_contents.json, and how it's created by the webstore:

// This class encapsulates the data in a "verified_contents.json" file
// generated by the webstore for a .crx file. That data includes a set of
// signed expected hashes of file content which can be used to check for
// corruption of extension files on local disk.

We can also see a number of function prototypes that sound like they are used for parsing and validating the verified_contents.json file:

  // Returns verified contents after successfully parsing verified_contents.json
  // file at |path| and validating the enclosed signature. Returns nullptr on
  // failure.
  // Note: |public_key| must remain valid for the lifetime of the returned
  // object.
  static std::unique_ptr<VerifiedContents> CreateFromFile(
      base::span<const uint8_t> public_key,
      const base::FilePath& path);
  // Returns verified contents after successfully parsing |contents| and
  // validating the enclosed signature. Returns nullptr on failure. Note:
  // |public_key| must remain valid for the lifetime of the returned object.
  static std::unique_ptr<VerifiedContents> Create(
      base::span<const uint8_t> public_key,
      base::StringPiece contents);
  // Returns the base64url-decoded "payload" field from the |contents|, if
  // the signature was valid.
  bool GetPayload(base::StringPiece contents, std::string* payload);
  // The |protected_value| and |payload| arguments should be base64url encoded
  // strings, and |signature_bytes| should be a byte array. See ments in the
  //  file on GetPayload for where these e from in the overall input
  // file.
  bool VerifySignature(const std::string& protected_value,
                       const std::string& payload,
                       const std::string& signature_bytes);

We can find the function definitions for these in verified_contents:

  • VerifiedContents::CreateFromFile calls base::ReadFileToString (which then calls ReadFileToStringWithMaxSize that reads the file as a binary file with mode rb) to load the contents of the file, and then passes this to Create
  • VerifiedContents::Create
    • calls VerifiedContents::GetPayload to extract/validate/decode the contents of the Base64 encoded payload field within verified_contents.json (see below for deeper explanation of this)
    • parses this as JSON with base::JSONReader::Read
    • extracts the item_id key, validates it with crx_file::id_util::IdIsValid, and adds it to verified_contents as extension_id_
    • extracts the item_version key, validates it with Version::IsValid(), and adds it to verified_contents as version_
    • extracts all of the content_hashes objects and
      • verifies that the format of each is treehash
      • extracts the block_size and hash_block_size, ensures they have the same value, and addsblock_size to verified_contents as block_size_
      • extracts all of the files objects
        • extracts the path and root_hash keys and ensures that root_hash is Base64 decodeable
      • calculates the canonical_path using content_verifier_utils::CanonicalizeRelativePath and base::FilePath::FromUTF8Unsafe, and inserts it into root_hashes_ in the verified_contents
    • finally, returns the verified_contents
  • VerifiedContents::GetPayload
    • parses the contents as JSON with base::JSONReader::Read
    • finds an object in the JSON that has the description key set to treehash per file
      • extracts the signed_content object
        • extracts the signatures array
          • finds an object in the signatures array that has a header.kid set to webstore
            • extracts the protected / signature keys and Base64 decodes the signature into signature_bytes
        • extracts the payload key
        • calls VerifySignature with protected / payload / signature_bytes
          • if the signature is valid, Base64 decodes the payload into a JSON string
  • VerifiedContents::VerifySignature
    • calls SignatureVerifier::VerifyInit using crypto::SignatureVerifier::RSA_PKCS1_SHA256
    • uses this to validate protected_value + . + payload

Since this didn't show how the file hashes themselves were verified, I then searched for where VerifiedContents::CreateFromFile was called:

  • https://source.chromium/search?q=VerifiedContents::CreateFromFile

Which pointed me to the following files:

  • extensions/browser/content_verifier/content_hash

Where

  • VerifiedContents::CreateFromFile is called by ReadVerifiedContents
  • ReadVerifiedContents is called by ContentHash::GetVerifiedContents, and when the contents are successfully verified, it will pass them to verified_contents_callback
  • GetVerifiedContents is called by ContentHash::Create, which passes ContentHash::GetComputedHashes as the verified_contents_callback
  • ContentHash::GetComputedHashes calls ContentHash::BuildComputedHashes
  • ContentHash::BuildComputedHashes will read/create the puted_hashes.json file by calling file_util::GetComputedHashesPath, ComputedHashes::CreateFromFile, CreateHashes (which calls ComputedHashes::Compute), etc

Note that ComputedHashes::CreateFromFile and ComputedHashes::Compute are the functions described in the puted_hashes.json section above (used to calculate the SHA256 hash of the blocks of the files included in the extension), and which I go into much more detail about in this StackOverflow answer.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744322054a4568467.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信