mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
Introduce Hash::parseExplicitFormatUnprefixed
This commit is contained in:
parent
c6d06ce486
commit
095ac66d4c
3 changed files with 87 additions and 8 deletions
|
|
@ -1,13 +1,17 @@
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
#include "nix/util/hash.hh"
|
#include "nix/util/hash.hh"
|
||||||
|
#include "nix/util/tests/characterization.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class BLAKE3HashTest : public virtual ::testing::Test
|
class HashTest : public CharacterizationTest
|
||||||
{
|
{
|
||||||
|
std::filesystem::path unitTestData = getUnitTestData() / "hash";
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,8 +20,14 @@ public:
|
||||||
*/
|
*/
|
||||||
ExperimentalFeatureSettings mockXpSettings;
|
ExperimentalFeatureSettings mockXpSettings;
|
||||||
|
|
||||||
private:
|
std::filesystem::path goldenMaster(std::string_view testStem) const override
|
||||||
|
{
|
||||||
|
return unitTestData / testStem;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class BLAKE3HashTest : public HashTest
|
||||||
|
{
|
||||||
void SetUp() override
|
void SetUp() override
|
||||||
{
|
{
|
||||||
mockXpSettings.set("experimental-features", "blake3-hashes");
|
mockXpSettings.set("experimental-features", "blake3-hashes");
|
||||||
|
|
@ -137,6 +147,46 @@ TEST(hashString, testKnownSHA512Hashes2)
|
||||||
"c7d329eeb6dd26545e96e55b874be909");
|
"c7d329eeb6dd26545e96e55b874be909");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* parsing hashes
|
||||||
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
TEST(hashParseExplicitFormatUnprefixed, testKnownSHA256Hashes1_correct)
|
||||||
|
{
|
||||||
|
// values taken from: https://tools.ietf.org/html/rfc4634
|
||||||
|
auto s = "abc";
|
||||||
|
|
||||||
|
auto hash = hashString(HashAlgorithm::SHA256, s);
|
||||||
|
ASSERT_EQ(
|
||||||
|
hash,
|
||||||
|
Hash::parseExplicitFormatUnprefixed(
|
||||||
|
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||||
|
HashAlgorithm::SHA256,
|
||||||
|
HashFormat::Base16));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(hashParseExplicitFormatUnprefixed, testKnownSHA256Hashes1_wrongAlgo)
|
||||||
|
{
|
||||||
|
// values taken from: https://tools.ietf.org/html/rfc4634
|
||||||
|
ASSERT_THROW(
|
||||||
|
Hash::parseExplicitFormatUnprefixed(
|
||||||
|
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||||
|
HashAlgorithm::SHA1,
|
||||||
|
HashFormat::Base16),
|
||||||
|
BadHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(hashParseExplicitFormatUnprefixed, testKnownSHA256Hashes1_wrongBase)
|
||||||
|
{
|
||||||
|
// values taken from: https://tools.ietf.org/html/rfc4634
|
||||||
|
ASSERT_THROW(
|
||||||
|
Hash::parseExplicitFormatUnprefixed(
|
||||||
|
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||||
|
HashAlgorithm::SHA256,
|
||||||
|
HashFormat::Nix32),
|
||||||
|
BadHash);
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* parseHashFormat, parseHashFormatOpt, printHashFormat
|
* parseHashFormat, parseHashFormatOpt, printHashFormat
|
||||||
* --------------------------------------------------------------------------*/
|
* --------------------------------------------------------------------------*/
|
||||||
|
|
|
||||||
|
|
@ -99,22 +99,37 @@ struct DecodeNamePair
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
static DecodeNamePair baseExplicit(HashFormat format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case HashFormat::Base16:
|
||||||
|
return {base16::decode, "base16"};
|
||||||
|
case HashFormat::Nix32:
|
||||||
|
return {BaseNix32::decode, "nix32"};
|
||||||
|
case HashFormat::Base64:
|
||||||
|
return {base64::decode, "Base64"};
|
||||||
|
case HashFormat::SRI:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the expected size of the message once decoded it, figure out
|
* Given the expected size of the message once decoded it, figure out
|
||||||
* which encoding we are using by looking at the size of the encoded
|
* which encoding we are using by looking at the size of the encoded
|
||||||
* message.
|
* message.
|
||||||
*/
|
*/
|
||||||
static DecodeNamePair baseFromSize(std::string_view rest, HashAlgorithm algo)
|
static HashFormat baseFromSize(std::string_view rest, HashAlgorithm algo)
|
||||||
{
|
{
|
||||||
auto hashSize = regularHashSize(algo);
|
auto hashSize = regularHashSize(algo);
|
||||||
|
|
||||||
if (rest.size() == base16::encodedLength(hashSize))
|
if (rest.size() == base16::encodedLength(hashSize))
|
||||||
return {base16::decode, "base16"};
|
return HashFormat::Base16;
|
||||||
|
|
||||||
if (rest.size() == BaseNix32::encodedLength(hashSize))
|
if (rest.size() == BaseNix32::encodedLength(hashSize))
|
||||||
return {BaseNix32::decode, "nix32"};
|
return HashFormat::Nix32;
|
||||||
|
|
||||||
if (rest.size() == base64::encodedLength(hashSize))
|
if (rest.size() == base64::encodedLength(hashSize))
|
||||||
return {base64::decode, "Base64"};
|
return HashFormat::Base64;
|
||||||
|
|
||||||
throw BadHash("hash '%s' has wrong length for hash algorithm '%s'", rest, printHashAlgo(algo));
|
throw BadHash("hash '%s' has wrong length for hash algorithm '%s'", rest, printHashAlgo(algo));
|
||||||
}
|
}
|
||||||
|
|
@ -190,7 +205,7 @@ static Hash parseAnyHelper(std::string_view rest, auto resolveAlgo)
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise, decide via the length of the hash (for the
|
/* Otherwise, decide via the length of the hash (for the
|
||||||
given algorithm) what base encoding it is. */
|
given algorithm) what base encoding it is. */
|
||||||
return baseFromSize(rest, algo);
|
return baseExplicit(baseFromSize(rest, algo));
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
@ -225,7 +240,12 @@ Hash Hash::parseAny(std::string_view original, std::optional<HashAlgorithm> optA
|
||||||
|
|
||||||
Hash Hash::parseNonSRIUnprefixed(std::string_view s, HashAlgorithm algo)
|
Hash Hash::parseNonSRIUnprefixed(std::string_view s, HashAlgorithm algo)
|
||||||
{
|
{
|
||||||
return parseLowLevel(s, algo, baseFromSize(s, algo));
|
return parseExplicitFormatUnprefixed(s, algo, baseFromSize(s, algo));
|
||||||
|
}
|
||||||
|
|
||||||
|
Hash Hash::parseExplicitFormatUnprefixed(std::string_view s, HashAlgorithm algo, HashFormat format)
|
||||||
|
{
|
||||||
|
return parseLowLevel(s, algo, baseExplicit(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
Hash Hash::random(HashAlgorithm algo)
|
Hash Hash::random(HashAlgorithm algo)
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,15 @@ struct Hash
|
||||||
*/
|
*/
|
||||||
static Hash parseNonSRIUnprefixed(std::string_view s, HashAlgorithm algo);
|
static Hash parseNonSRIUnprefixed(std::string_view s, HashAlgorithm algo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like `parseNonSRIUnprefixed`, but the hash format has been
|
||||||
|
* explicitly given.
|
||||||
|
*
|
||||||
|
* @param explicitFormat cannot be SRI, but must be one of the
|
||||||
|
* "bases".
|
||||||
|
*/
|
||||||
|
static Hash parseExplicitFormatUnprefixed(std::string_view s, HashAlgorithm algo, HashFormat explicitFormat);
|
||||||
|
|
||||||
static Hash parseSRI(std::string_view original);
|
static Hash parseSRI(std::string_view original);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue