MCPcopy Create free account
hub / github.com/aboutcode-org/vulnerablecode / get_purl_hash

Function get_purl_hash

aboutcode/hashid/__init__.py:343–410  ·  view source on GitHub ↗

Return a short lower cased hash string from a ``purl`` string or object. The PURL is normalized and we drop its version, qualifiers and subpath. This function takes a normalized PURL string and a ``_bit_count`` argument defaulting to 0 bits which represents 2**0 = 1 possible hash v

(purl: Union[PackageURL, str], _bit_count: int = 0)

Source from the content-addressed store, hash-verified

341
342
343def get_purl_hash(purl: Union[PackageURL, str], _bit_count: int = 0) -> str:
344 """
345 Return a short lower cased hash string from a ``purl`` string or object. The PURL is normalized
346 and we drop its version, qualifiers and subpath.
347
348 This function takes a normalized PURL string and a ``_bit_count`` argument defaulting to 0 bits
349 which represents 2**0 = 1 possible hash value. It returns a fixed length short hash string
350 that is left-padded with zeros.
351
352 The hash length is derived from the bit_count and the number of bits-per-byte stored in an hex
353 encoding of this bits count. For 10 bits, this means up to 3 characters.
354
355 The function is carefully designed to be portable across tech stacks and easy to implement in
356 many programming languages:
357
358 - the hash is computed using sha256 which is available is all common language,
359 - the hash is using simple lowercased HEX encoding,
360 - we use simple arithmetics on integer with modulo.
361
362 The processing goes through these steps:
363
364 First, a SHA256 hash computed on the PURL bytes encoded as UTF-8.
365
366 Then, the hash digest bytes are converted to an integer, which is reduced modulo the largest
367 possible value for the bit_count.
368
369 Finally, this number is converted to hex, left-padded with zero up to the hash_length, and
370 returned as a lowercase string.
371
372 For example::
373
374 The hash does not change with version or qualifiers::
375 >>> get_purl_hash("pkg:pypi/univers@30.12.0", 7)
376 '09'
377 >>> get_purl_hash("pkg:pypi/univers@10.12.0", 7)
378 '09'
379 >>> get_purl_hash("pkg:pypi/univers@30.12.0?foo=bar#sub/path", 7)
380 '09'
381
382 The hash is left padded with zero if it::
383 >>> get_purl_hash("pkg:pypi/expressionss", 7)
384 '57'
385
386 We normalize the PURL. Here pypi normalization always uses dash for underscore ::
387
388 >>> get_purl_hash("pkg:pypi/license_expression", 7)
389 '50'
390 >>> get_purl_hash("pkg:pypi/license-expression", 7)
391 '50'
392
393 Originally from:
394 https://github.com/nexB/purldb/pull/235/files#diff-a1fd023bd42d73f56019d540f38be711255403547add15108540d70f9948dd40R154
395 """
396
397 core_purl = get_core_purl(purl).to_string()
398 # compute the hash from a UTF-8 encoded string
399 purl_bytes = core_purl.encode("utf-8")
400 hash_bytes = sha256(purl_bytes).digest()

Callers 1

package_path_elementsFunction · 0.85

Calls 2

get_core_purlFunction · 0.85
to_stringMethod · 0.45

Tested by

no test coverage detected