g3p-hash-2.0.0.0: Global Password Prehash Protocol
Copyright(c) 2024 Auth Global
LicenseApache2
Safe HaskellSafe-Inferred
LanguageHaskell2010

Crypto.G3P.V2

Description

 
Synopsis

Documentation

g3pHash Source #

Arguments

:: Foldable f 
=> G3PSalt

All the parameters needed throughout the entire key-stretching computation.

-> G3PInputs

All the parameters that can be forgotten as soon as they are hashed once.

-> G3PSeedInputs

All the parameters needed for bcrypt-based key stretching

-> HmacKey

Sprout Seguid. A good default is to duplicate g3pSalt_seguid.

-> f ByteString

Sprout Role, an arbitrary number of bytestring parameters for late domain separation occuring after key-stretching is complete. Meaning is deployment defined.

-> ByteString

Sprout Tag. A good default is to duplicate g3pSalt_domainTag.

-> ByteString

This echo key is the right half of the output key. It is truncated to 32 bytes.

-> ByteString

The echo header is truncated to 32 bytes.

As the initial state of the output stream generator, if more than one block of the resulting output stream is ever examined, then this parameter must not include any new secrets. Otherwise the old secrets are potentially still crackable from the relationship between output stream blocks.

This problem can be avoided by ensuring at least one of these are true:

  1. Sticking to anodyne messages that aren't too specifically related to this password attempt, like a company name.
  2. including data that's already been included earlier in the derivation chain, i.e. deeper in the Merkle tree
  3. duplicating the content of this parameter in the echo key and/or echo tag parameters.
  4. never examine more than one output block.

It is possible to use this parameter safely in ways that don't exactly meet any of the criteria above, but these criteria would seem to fairly comprehensively cover typical use cases. I'm not sure why a deployment designer might feel a need to go beyond these criteria.

Also note that if you feed an output block from _G3Pb2 echo_ back into this parameter, keep the keys and tag the same, and update the counter accordingly, then this will "collide" with the next output block of the original generator. This issue can be avoided by a deployment, so it's better to not get too creative with this specific parameter.

-> Word32

echo counter

-> ByteString

echo tag. A good default is to duplicate the sprout's tag.

-> ByteString

a 32-byte output hash. You can use the stream variant if you want more blocks. This is the first output block of that stream.

The Global Password Prehash Protocol (G3P). Note that this function is very intentionally implemented in such a way that the following idiom is efficient. It performs the expensive key stretching phase only once, and results in 3 cryptographically independent output hashes, i.e. statistically independent to any efficient attacker that does not have access to the underlying password and other secrets.

 let myDomain = "my.domain.example"
     myLoginDomain = "login.my.domain.example"
     myStorageDomain = "cloud.my.domain.example"
     myLongTag = "My Corporation, Inc. https://my.domain.example/.well-known/security.txt"
     mySeguid = hmacKey "9c08053b7e507a78b571b5b93e1326674540d7106da6408fcafeddcfcdf1ed76"
     userRandomSalt = "60473b8010e16d46"
     userSecondSecretHash = "0c06f683f093cb899b4a1e9836fc7281"
     mySalt =
       G3PSalt {
         g3pSalt_seguid = mySeguid,
         g3pSalt_longTag = myLongTag,
         g3pSalt_contextTags = [userRandomSalt],
         g3pSalt_domainTag = myDomain,
         g3pSalt_phkdfRounds = 20240
       }
     myInputs =
       G3PInputs {
         g3pInputs_username = userRandomSalt,
         g3pInputs_password = "correct horse battery staple",
         g3pInputs_credentials = [userSecondSecretHash]
       }
     mySeedInputs =
       G3PSeedInputs {
         g3pSeedInputs_bcryptSeguid = mySeguid,
         g3pSeedInputs_bcryptCredentials = [],
         g3pSeedInputs_bcryptLongTag = myLongTag,
         g3pSeedInputs_bcryptContextTags = [],
         g3pSeedInputs_bcryptDomainTag = myDomain,
         g3pSeedInputs_bcryptRounds = 4202
       }
     mySprout = g3pHash mySalt myInputs mySeedInputs mySeguid
     myHeader = userRandomSalt <> myDomain
     myAuthKey = mySprout ["auth",userRandomSalt]
                     myLoginDomain myHeader myHeader (word32 AUTH)
     myDiskKey = mySprout
                    ["disk", myStorageDomain, myLongTag,
                     "key", "7014dad47f0e7f7157d99b39a06553ce"]
                    myStorageDomain myHeader myHeader (word32 DISK)
  in [ myAuthKey myLongTag
     , myDiskKey "filename0.txt"
     , myDiskKey "quarterly-report.pdf"
     ]

In addition to sharing the main key-stretching computation among all three independent output hashes, myDiskKey also shares the G3PSprout to G3PKey computation among two different calls. Although this savings is relatively miniscule, it can also be relevant in certain contexts.

Note that this example is intended to be an extremely accurate sketch of what a good authentication deployment that uses random salts or hashed usernames and not plaintext usernames would look like.

Other details are more to stimulate ideas about how one might use these things: for example I'd highly recommend using 64-byte binary mySeguid, a 16-byte binary userRandomSalt, and a 32-byte binary userSecondSecretHash, and I'd probably not use myDiskKey in exactly that way.

This example emphasizes that the G3P is designed to preserve endless possibilites for keying end-to-end encryption (E2EE) off of the user's password, though deploying a the G3P as a client-side prehash function is absolutely required to make use of that particular capability.

In the example above, the extended interface could be used to partially evaluate the sprout on the storage domain, allowing the G3PSeed to be immediately forgotten. Later, the continuation of that partially evaluated sprout can be finalized once the storage key is provided by the server upon a successful authentication.

This approach has the minor complication of needing to ensure that any important data has been fully committed to and isn't sitting around inside the sprout's SHA256 context buffer. This can be done by including at least 63 bytes of non-committing data anywhere you need a safe partial evaluation point.

Thus the inclusion of myLongTag in the storage role vector ensures that the original seed, the "disk", and the "cloud.my.domain.example" strings can be fully committed to while waiting for the disk key.

Another possibility is to use filler padding to control the context buffer position; I suggest using 32-95 or more bytes, as this ensures the encoded length is 3 bytes long and thus ensures that your desired buffer position can be reached from any starting point.

In the case that you want or need to persist or serialize the intermediate structures, then the plain-old-datatypes G3PSpark, G3PSeed, G3PSprout, G3PTree,G3PKey, G3PSource, and their associated functions are more relevant than implicit closures.

These data structures explicitly represent the result of a partial evaluation, and provide a continuation onward to any one of innumerable final results.

g3pStream Source #

Arguments

:: Foldable f 
=> G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> Stream ByteString 

This variant of g3pHash returns an unbounded stream of 32-byte output blocks. Use as many or as few as you want. Assuming the non-echo-header inputs contain at least one strong secret, the output blocks are cryptographically independent. You can partition the output into non-overlapping chunks and use those chunks however you see fit.

NIST SP 800-108 recommendations imply that you shouldn't look at more than 137.4 GB of output. This recommendation is extremely cautious, and it's probably okay-ish in most circumstances to exceed that limit by a considerable margin.

On the other hand, if you really want that much CSPRNG data, you may well be better off using this function to generate keys for another, faster CSPRNG.

data G3PSalt Source #

These input parameters are grouped together because they are the parameters that will have to persist in memory for most or all of the PHKDF-based key-stretching computation.

It is intended that deployments of an authentication database will specify these as constants or near-constants. User-supplied inputs would typically not go here. In this role, all these parameters function as salt.

The seguid parameter acts as a deployment-wide salt. Cryptographically speaking, the most important thing a deployment can do is specify a constant seguid. It is highly recommended that the seguid input be a genuine Self-Documenting Globally Unique Identifier attesting to the parameters, purposes, and public playbook of the protocol for y'all to follow to use the deployment to spec.

The remaining string parameters are all directly-documenting, embedded attributions. A deployment can use these tags to encode a message into the password hash function so that it must be known to whomever can compute it. There are a variety of different parameters because there are different lengths of messages that can be expressed for free, and there are different incremental costs for exceeding that limit.

It is particularly important to include some kind of actionable message in the domainTag and longTag parameter. Specifying an empty string in either of these parameters means that a significant quantity of cryptoacoustic messaging space will be filled with silence.

Especially useful messages include URIs, legal names, and domain names.

Constructors

G3PSalt 

Fields

  • g3pSalt_seguid :: !HmacKey

    usable as a high-repetition indirect tag via self-documenting globally unique identifiers (seguids)

  • g3pSalt_longTag :: !ByteString

    plaintext tag with 1x repetition, then cycled for roughly 8 kilobytes which is used as filler padding after the password.

    This is typically duplicated as the g3pSeedInputs_bcryptLongTag parameter, which provides a very large number of cryptoacoustic repetitions. If this step is not taken, then this parameter can be discarded after the first call to HMAC is complete, making it essentially horn-loaded which would be a bit of an anomaly for this input block.

    The first 0-63 bytes is also used as filler padding after the contextTags, possibly making part of this parameter not horn-loaded.

    Constant time on inputs 0-4095 bytes. Overages incur one sha256 block per 64 bytes, rounded up.

  • g3pSalt_contextTags :: !(Vector ByteString)

    plaintext tags with 4x repetition. Constant-time on 0-63 encoded bytes, which includes the length encoding of each string. Thus 60 of those free bytes are usable if the tags vector is a single string, or less if it contains two or more strings. The empty vector is a good default choice here.

    Overages incur four sha256 blocks per 64 bytes.

    This parameter is notable because it is the least expensive purely auxiliary input that is not horn-loaded. Thus if you want a very long salt input that provides a bit of extra collision resistance, this would be a logical candidate input location to consider.

    If your deployment uses a random salt per account, this is an ideal location in which to place a copy of that salt. This is also a reasonable location for salts derived from hashed usernames.

    If your deployment uses a plain login name as the username salt, by including it here your deployment would then require that anybody who can crack the password must know the login name.

    This would be a highly atypical deployment design decision. In most contexts, it would seem to be better to omit plaintext login names from this parameter.

  • g3pSalt_domainTag :: !ByteString

    plaintext tag with one repetition per PHKDF round. 0-19 bytes are free, 20-83 bytes cost five additional sha256 blocks plus one block per PHKDF round, with every 64 bytes thereafter incurring a similar cost.

    In the case of long domain tags, it is strategically advantageous to ensure that the first 32 bytes are highly actionable, as these bytes are commonly used as filler padding.

    This parameter provides domain separation. (also see the NIST glossary) A suggested value is a ICANN domain name controlled by the deployment.

    The name is also a bit of an homage to the "realm" parameter of HTTP basic authentication, which in part inspired the domain tag by inspiring the question "What would the realm parameter do if it did something useful?"

  • g3pSalt_phkdfRounds :: !Word32

    How expensive will the PHKDF component be? An optimal implementation computes exactly two SHA256 blocks per round if the domain tag is 19 bytes or less, plus one block per round for every 64 characters over 19, rounded up.

    I recommend 20,000 rounds or so. You might consider adjusting that recommendation downward in the case of domain tags that exceed 19 bytes in length: 13,333 rounds of PHKDF with a domain tag that is 83 bytes long will cost exactly one SHA256 block less than 20,000 rounds of PHKDF with a domain tag that is 19 bytes long.

    Note that this cost comparison is exact only when looking at only the PHKDF key stretching phase. The G3P also computes a reasonably large but constant number of additional SHA256 blocks as part of it's initial HMAC-Extract operation, G3Pb2 alfa.

    Thus if you are tuning this parameter via empirical timing tests, the direct linear relationship between this parameter and time is approximate, not exact, due to a this reasonably large offset.

Instances

Instances details
Eq G3PSalt Source # 
Instance details

Defined in Crypto.G3P.V2

Methods

(==) :: G3PSalt -> G3PSalt -> Bool #

(/=) :: G3PSalt -> G3PSalt -> Bool #

data G3PInputs Source #

These parameters are grouped together because they are hashed once near the beginning of the protocol and then are no longer needed, unless a deployment specifies duplicating (part of) one of these parameters into another. Thus all of these parameters are horn-loaded.

The input string to the "username" parameter could be provided directly by the user. Alternatively, it could be a random salt retrieved from a server or database, typically looked up via a plaintext username. The password is normally expected to be supplied by the users of a deployment.

Furthermore, the credentials vector is here because it is an ideal location to include other input. For example, one could implement a Two-Secret Key Derivation (2SKD) scheme analogous to 1Password's.

A deployment can also specify additional constant tags as part of the credentials vector. As the plaintext of these tags is only ever hashed into the output a single time, this alongside the bcrypt tag and long tag are incrementally the least expensive options for plaintext tagging.

Note that the username and password are subjected to additional length hardening. The G3P operates in a constant number of SHA256 blocks so long as the combined length of the username and password is less than about 4 KiB, or the combined length of the username, password, and long tag is less than about 8 KiB. The actual numbers are somewhat less in both cases, but this is a reasonable approximation.

In the case of all of the inputs in this record, longer values incur one SHA256 block per 64 bytes.

Constructors

G3PInputs 

Fields

  • g3pInputs_username :: !ByteString

    constant time on 0-293 bytes, or if the combined length of the username and password is less than about 4 kilobytes, or if the combined length of the username, password, and long tag is less than about 8 kilobytes.

    Using deployment-identifying seguids and domain tags makes it perfectly safe to put normalized plaintext login names here, as then this salt would then only need to be unique within a deployment.

    This approach comes with the cost that you will have to reliably perform username normalization everywhere this hash function is computed. Offering a server-side remote procedure call to perform this normalization is recommended.

    The G3P is intentionally designed to allow the plaintext username to be hidden from a password cracker via partial evaluation, preventing the cracker from immediately logging in if successful. However, this partial application doesn't apply any key-stretching, meaning that guessable login names can be cracked relatively quickly.

    Thus this approach is less of a defensive line and more of a "sand in the gears" tactic. It might also be useful as a legal damages enhancement strategy against unauthorized password crackers who fail to take this step to help protect users' privacy.

    Even better, apply key-stretching to the plaintext login name, possibly via another call to the G3P, and duplicate that derived salt in the g3pInputs_username and g3pSalt_contextTags parameters, and inside the role parameter of G3PSprout.

    This repetition of an account's salt ensures that any collision that happens between accounts must occur quite late. Even if a cryptographically non-trivial collision happens before the repetition, the account's salt will push the output hashes apart once again.

    Including the account's salt in either the echo key or echo tag parameters implies a cryptographically non-trivial collision must happen on the very last HMAC call that generates any output block, and that must happen on every output block.

    Disconnecting login names from publicly-facing screen names can represent a significant upgrade of "sand in the gears" to something resembling a proper defensive line, though this disconnection can also benefit any approach.

    For another upgrade, using a random salt per acccount has the potential to be a far more meaningful defensive line. This brings the advantage of completely disconnecting public salts from login names, except by talking to (or compromising) a salt server.

    In a rare alignment of interests, this can serve both legitimate deployments and the password hash thieves that attack them. Some thieves will want to be able to outsource password cracking work without giving successful crackers an opportunity to log in, and this makes it easier for the thief to securely withhold the login name from the cracker.

    The cost is that in typical client-side prehashing scenarios, a salt server will have to reveal the actual salt for arbitrary accounts to arbitrary members of the public. This has the potential to leak information about the (non-)existence of accounts and to leak information about recent account activity.

    Of particular concern is providing reidentification hooks that enable deanonymization attacks. Though I don't exactly understand how a public-facing salt server could become such a hook, it's also something that seems possible.

    This issue could be largely mitigated by ensuring your salt server is capable of handing out convincing nonsense that is consistent over time. The server does not even need to remember every fake salt you've ever handed out. For example, the server could generate a fake salt by hashing a normalized version of the nonexistent login name with a secret key.

    If you are running a sufficiently sensitive identity service to justify the additional complexity and ongoing operational costs, running a salt server seems very much worthwhile.

    One reason is that when a password hash is stolen, having a login name in its derivation can be a reidentification hook without even needing to talk to a server. On the other hand, salt derived from a login name seems far preferable to a poorly implemented salt server.

    A poorly implemented server can become a toehold for attackers to get inside your infrastructure, and has the potential to leak whether or not an account exists, possibly even to the general public. Account existence can itself be an extremely juicy reidentification hook, and querying a public server doesn't require stealing password hashes first.

    In a few specialized cases it might be possible to hide a random salt from members of the general public by requiring pre-authentication before the password can even be attempted. However, this cannot be a general-purpose solution, as passwords are one of the fundamental solutions to the problem of key management, and key management is the fundamental problem behind authentication.

    One might also supplement or replace any salt applied here with an oblivious pseudorandom function (OPRF) in your authentication flow, especially if password-authenticated key agreement (PAKE) is used.

    Through the magic of multiparty computation, it's possible to apply a salt that only the server knows to a password attempt that only the client knowns. However, OPRF cannot be directly integrated into the G3P, though the G3P should be an excellent choice for a key derivation function to prepare a password for OPRF.

    I see this choice of plain usernames versus random salts or possibly even none at all as a fairly fundamental tradeoff in the design of G3P deployments. I took the time to ensure that all are possible.

    In my estimation, of the approaches that I've started to sketch, deriving salts directly from plaintext login names in a public, non-secret way is the hardest to mess up badly.

    Implementing a salt server potentially enables signficant security advantages, but also represents additional complexity, operational expense, and itself creates additional attack surfaces and security risks.

    This decision has significant strategic consequences. I don't think there exists a one-size-fits-all solution, and there are quite a few ways to sensibly customize each approach. Any can be executed poorly, and any can be executed well. Pick your poison wisely.

  • g3pInputs_password :: !ByteString

    constant time on 0-293 bytes, or if any of the other conditions are met.

  • g3pInputs_credentials :: !(Vector ByteString)

    constant time on 0-282 encoded bytes. This includes variable-length fields that encode the bit length of each string; these fields itself require two or more bytes per string.

Instances

Instances details
Eq G3PInputs Source # 
Instance details

Defined in Crypto.G3P.V2

data G3PSeedInputs Source #

Constructors

G3PSeedInputs

bcrypt parameters

Fields

  • g3pSeedInputs_bcryptSeguid :: !HmacKey

    Key to used to generate keys for bcrypt superrounds and to soak up the entropy from bcrypt's state at the end of each superround. Duplicating the g3pSalt_seguid is a good default choice.

  • g3pSeedInputs_bcryptCredentials :: !(Vector ByteString)

    Used directly once to derive key0 for the first bcrypt superround, and indirectly affects every cryptographic operation after that.

    0-29 bytes are free. The length encoding for each bytestring needs to be included, thus 0-27 data bytes incur zero incremental cost if you encode everything in one string, or less if you use more than one string.

    Overages cost one SHA256 block per 64 bytes, rounded up. Thus, this is a horn-loaded parameter introduced after the phkdf key-stretching phase is complete.

    If some unusual deployment of the G3P accepts arbitrary external inputs into the bcryptLongTag, one possible way to handle this situation efficiently and safely would be to include the entire input in this parameter. This is not necessary if such a deployment duplicated the external input into both the g3pSalt_longTag and g3pSeedInputs_bcryptLongTag parameters.

  • g3pSeedInputs_bcryptLongTag :: !ByteString

    Be aware this is truncated to (rounds + 1) * 4136 bytes, but length still matters after that. The primary intended use is to duplicate g3pSalt_longTag a very large number of times.

    Also be aware that nobody should trust this parameter with arbitrary, potentially hostile input that is selected after all of the other inputs to the bcrypt computation are known. There are, however, a large number of ways to avoid any potential issue, including:

    1. Ensuring that this input is fully commited to before looking at all of the other input parameters by convention, which is true in the primary intended use case as an extended plaintext salt for password hashing.
    2. Ensure that this input has been committed to by including the entirety of its contents in the derivation of at least one other input parameter. Note that duplicating g3pSalt_longTag is sufficient to meet this requirement. Including it somewhere in a G3PSalt parameter is highly recommended as it ensures that varying any part of this parameter is expensive as possible.
    3. Ensure that this input is 4287 bytes or less. Local HMAC computations ensure at least this many bytes are automatically committed to before the bcrypt key stretching is allowed to move forward.
    4. Ensure that this input has some kind, any kind, of recognizable pattern. If this input is a valid UTF8 encoding, it doesn't matter if the textual content is random gibberish. It's extremely doubtful that an attacker could achieve any particularly nefarious goal under this restriction.

    Note that any single one of these conditions should be sufficient to avoid problems, and that the primary intended use case for this parameter meets all of them. After all, the entire point of this parameter is to ensure the delivery of plaintext salts from authentication database deployments to password crackers.

    Failing all of that, there's still an attempt to make the G3P resistant to hostile inputs. Within each bcrypt round, the exact same longTag bytes are repeated four times in a combinatorial block design that ensures nonlinear effects.

    I wouldn't want to rely on this design feature of last resort without careful study, which is likely to suggest further improvements. Yet this hedge doesn't cost anything with respect to the intended use case, and seems plausibly strong in situations that fall well outside any intended use case.

    Regarding condition 2, any of the G3PInput parameters would also qualify. However, it would be rather silly to repeat the user's password here, as that would prevent the bcrypt key stretching computation from being securely outsourced to a semi-trusted device.

    Regarding condition 3, the actual size of a parameter that is fully committed to via baked-in hashing is likely more than 8192 bytes, but this would require further verification.

    The shortest plausible attack string would seem to need to be as long as the truncation limit, which is north of 16 megabytes if you specify the suggested 4000 rounds.

    Here, the attack model of concern is preventing any external input from affecting the final bcrypt state in any way that's better than a multiplicity of fair coin flips.

    Failing to fully commit to the bcrypt long tag up-front potentially allows external input to tweak the final result without redoing the entirety of the key-stretching computation, even if the desired fairness property is ensured.

    This final bcrypt state is then consumed as part of an HMAC message. This outer HMAC provides the next line of defense against this type of attack. This line of defense pretends this outer HMAC doesn't exist.

  • g3pSeedInputs_bcryptContextTags :: !(Vector ByteString)

    Also used to derive super round keys for bcrypt. 0-63 encoded bytes are free, meaning that 60 bytes impose zero incremental cost if you encode everything into one string, or somewhat less if you use more than one string.

    Overages cost two SHA-256 blocks per 64 bytes per bcrypt superround.

    Leaving this empty is a good default choice. In particular, one should not default to duplicating anything between this parameter and the g3pSeed_contextTags parameter.

    For example, if your deployment uses a random account salt, or an account salt derived transparently from a login name, then it's a good idea to include that salt in the username and contextTags parameters, but exclude the plaintext of that salt from bcryptContextTags.

    This use of an account salt implies that if some or all of the bcrypt computation is outsourced to another device, that device cannot break the password without knowing the salt, or successfully guessing both the salt and password at the same time.

    Assuming simplest and most-intended outsourcing algorithm, directly including that account salt in the bcryptContextTags vector would require that the plaintext of this salt be known to the device performing the key-stretching computation, thus automatically obviating this possible line of defense.

    If one is absolutely set on including that random salt here, one could hash the salt first to derive a new salt that cannot itself be used to crack the password. What things are forgotten and when are important details in cryptographic processes, and these choices have strategic implications.

    Alternatively, one could implement the G3P using a more sophisticated outsourcing algorithm. This would require interactive communication every transition between bcrypt superrounds. By contrast, the design intension is to be able to treat outsourcing bcrypt as (relatively) simple remote procedure call (RPC).

  • g3pSeedInputs_bcryptDomainTag :: !ByteString

    Used to derive the keys for a super round in bcrypt-xs-ctr mode. Duplicating the g3pSalt_domainTag is a good default choice.

    0-19 bytes are free. 20-83 bytes and every 64 bytes thereafter impose a cost of two SHA-256 blocks per bcrypt superround.

  • g3pSeedInputs_bcryptRounds :: !Word32

    How expensive will the bcrypt component be? 4000 rounds recommended, give or take a factor of 2 or so. Each bcrypt round is approximately as time consuming as 60 PHKDF rounds. Using the recommended cost, parameters, the cost should be dominated by bcrypt.

    The number of superrounds matters for some cost calculations. This is always ceiling ((bcryptRounds + 1) / 128).

data G3PSpark Source #

Represents the completion of the PBKDF2-like key stretching computation, and ready for bcrypt. Technically, a partial evaluation at the completion of G3Pb2 bravo, ready for G3Pb2 charlie.

Instances

Instances details
Eq G3PSpark Source # 
Instance details

Defined in Crypto.G3P.V2.Subtle

g3pSpark Source #

Arguments

:: G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSpark

the end of G3Pb2 bravo, the beginning of G3P charlie

g3pSpark encompasses calls to G3Pb2 alfa and G3Pb2 bravo, which provides the PHKDF-based key-stretching phase.

All 8 parameters get unambiguously encoded into G3Pb2 alfa, which is the initial call to HMAC. 7 of them can be unambiguously parsed out of the input message, thus proving that all collisions over them are cryptographically non-trivial. The eighth is used as the HMAC key.

Moreover, the G3P's syntax generators never examine the content of any input, only length. Thus by parametricity, any vaguely reasonable attempt to implement the G3P cannot be directly responsible for introducing a data-dependent side channel.

The hash resulting from this initial HMAC-Extract, in addition to the G3PSalt parameters, determine the exact size, shape, and content of the Merkle tree that describes the resulting spark. At this point in time every computation is fully determined all the way to the end of the PHKDF key-stretching phase. The next opportunity to make a choice is the bcrypt key-stretching phase.

A spark consists of two cryptographically independent keys: keyB which begins bcrypt, and keyC which is the continuation control key. The continuation control key allows some or all of the bcrypt computation to be outsourced to another semi-trusted device, without giving that device the ability to compute the final seed.

g3pSpark_toSeed Source #

Arguments

:: G3PSpark

the end of G3Pb2 bravo, the beginning of G3Pb2 charlie

-> G3PSeedInputs

bcrypt parameters

-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

The bcrypt key-stretching phase.

g3pSpark_toSprout Source #

Arguments

:: G3PSpark

a partial evaluation of G3Pb2 bravo

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> G3PSprout

the middle of G3Pb2 delta

g3pSpark_toTree Source #

Arguments

:: Foldable f 
=> G3PSpark

a partial evaluation of G3Pb2 bravo

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

g3pSpark_toKey Source #

Arguments

:: Foldable f 
=> G3PSpark

a partial evaluation of G3Pb2 bravo

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PKey

the middle of G3Pb2 echo

g3pSpark_toSource Source #

Arguments

:: Foldable f 
=> G3PSpark

a partial evaluation of G3Pb2 bravo

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSource

plain-old data representation of an output stream

g3pSpark_toStream Source #

Arguments

:: Foldable f 
=> G3PSpark

a partial evaluation of G3Pb2 bravo

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> Stream ByteString 

data G3PSeed Source #

A plain 32-byte hash that represents the completion of both phkdf and bcrypt key stretching phases. Technically, a partial evaluation at the completion of G3Pb2 charlie, ready for G3Pb2 delta.

Instances

Instances details
Eq G3PSeed Source # 
Instance details

Defined in Crypto.G3P.V2.Subtle

Methods

(==) :: G3PSeed -> G3PSeed -> Bool #

(/=) :: G3PSeed -> G3PSeed -> Bool #

g3pSeed Source #

Arguments

:: G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSeedInputs 
-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

g3pSeed_fromSpark Source #

Arguments

:: G3PSeedInputs

bcrypt parameters

-> G3PSpark

a partial evaluation of G3Pb2 bravo

-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

g3pSeed_toSprout Source #

Arguments

:: G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> HmacKey

Sprout Seguid

-> G3PSprout

the middle of G3Pb2 delta

Start a call to G3Pb2 delta, starting with the Sprout's Seguid.

g3pSeed_toTree Source #

Arguments

:: Foldable f 
=> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

g3pSeed_toKey Source #

Arguments

:: Foldable f 
=> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PKey

the middle of G3Pb2 echo

g3pSeed_toSource Source #

Arguments

:: Foldable f 
=> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSource

plain-old data representation of an output stream

g3pSeed_toStream Source #

Arguments

:: Foldable f 
=> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> Stream ByteString 

data G3PSprout Source #

Represents a partial evaluation of G3P delta, initialized with the Sprout Seguid and possibly commited to part of the role argument. This comes before the Sprout Domain Tag, and in fact can be finalized with that parameter at any time.

g3pSprout Source #

Arguments

:: G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> G3PSprout

the middle of G3Pb2 delta

g3pSprout_feedArg Source #

Arguments

:: ByteString

arg

-> G3PSprout

the middle of G3Pb2 delta

-> G3PSprout

a later middle of G3Pb2 delta, ready for more args, or grow into a G3PTree

flipped version of g3pSprout_arg

g3pSprout_feedArgs Source #

Arguments

:: Foldable f 
=> f ByteString

zero or more args

-> G3PSprout

the middle of G3Pb2 delta

-> G3PSprout

a later middle of G3Pb2 delta, ready for more args, or grow into a G3PTree

flipped version of g3pSprout_args

g3pSprout_arg Source #

Arguments

:: G3PSprout

the middle of G3Pb2 delta

-> ByteString

arg

-> G3PSprout

a later middle of G3Pb2 delta, ready for more args, or grow into a G3PTree

The name of this function is a mnemonic for the argument order, which takes an sprout and adds a single length-delimited argument to it.

g3pSprout_args Source #

Arguments

:: Foldable f 
=> G3PSprout

the middle of G3Pb2 delta

-> f ByteString

zero or more args

-> G3PSprout

a later middle of G3Pb2 delta, ready for more args, or grow into a G3PTree

The name of this function is a mnemonic for the argument order, which takes a sprout and adds zero or more length-delimited arguments to it.

g3pSprout_fromSpark Source #

Arguments

:: G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> G3PSpark

the end of G3Pb2 bravo, the beginning of G3P charlie

-> G3PSprout

the middle of G3Pb2 delta

g3pSprout_fromSeed Source #

Arguments

:: HmacKey

sprout seguid

-> G3PSeed 
-> G3PSprout

the middle of G3Pb2 delta

g3pSprout_toTree Source #

Arguments

:: G3PSprout

the middle of G3Pb2 delta

-> ByteString

Sprout Domain Tag

-> G3PTree 

g3pSprout_toKey Source #

Arguments

:: Foldable f 
=> G3PSprout

a partial evaluation of G3Pb2 delta

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PKey

the beginning of G3P echo

g3pSprout_toSource Source #

Arguments

:: Foldable f 
=> G3PSprout

the middle of G3Pb2 delta

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSource

plain-old data representation of an output stream

g3pSprout_toStream Source #

Arguments

:: Foldable f 
=> G3PSprout

the middle of G3Pb2 delta

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> Stream ByteString 

data G3PTree Source #

A plain 32-byte hash that represents the leftmost bytes of the output hmac key. Technically, a partial evaluation ending at G3Pb2 delta and ready for the right half of the echo key, as needed to begin the evaluation of G3Pb2 echo

Instances

Instances details
Eq G3PTree Source # 
Instance details

Defined in Crypto.G3P.V2.Subtle

Methods

(==) :: G3PTree -> G3PTree -> Bool #

(/=) :: G3PTree -> G3PTree -> Bool #

g3pTree Source #

Arguments

:: Foldable f 
=> G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

g3pTree_fromSpark Source #

Arguments

:: Foldable f 
=> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> G3PSpark

the end of G3Pb2 bravo, the beginning of G3Pb2 charlie

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

g3pTree_fromSeed Source #

Arguments

:: Foldable f 
=> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

g3pTree_fromSprout Source #

Arguments

:: ByteString

sprout tag

-> G3PSprout 
-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

g3pTree_toKey Source #

Arguments

:: G3PTree 
-> ByteString

echo key right

-> G3PKey

the middle of G3Pb2 echo

g3pTree_toSource Source #

Arguments

:: G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSource

plain-old data representation of an output stream

g3pTree_toStream Source #

Arguments

:: G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> Stream ByteString 

data G3PKey Source #

A precomputed hmac key intended for use with G3Pb2 echo. Technically, a partial evaluation of the HMAC-SHA256 construction.

g3pKey Source #

Arguments

:: Foldable f 
=> G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PKey

the beginning of G3P echo

g3pKey_fromSpark Source #

Arguments

:: Foldable f 
=> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PSpark

a partial evaluation of G3P bravo

-> G3PKey

the beginning of G3P echo

g3pKey_fromSeed Source #

Arguments

:: Foldable f 
=> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> G3PKey

the middle of G3Pb2 echo

g3pKey_fromSprout Source #

Arguments

:: Foldable f 
=> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> G3PSprout

the middle of G3Pb2 delta

-> G3PKey

the middle of G3Pb2 echo

g3pKey_fromTree Source #

Arguments

:: ByteString

echo key right

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

-> G3PKey

the middle of G3Pb2 echo

g3pKey_toSource Source #

Arguments

:: G3PKey

the middle of G3Pb2 echo

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSource

plain-old data representation of an output stream

Variant of g3pKey_toStream that returns plain old data.

g3pKey_toStream Source #

Arguments

:: G3PKey

the middle of G3Pb2 echo

-> ByteString

echo header

-> Word32

The echo counter, functionally a bonus HKDF info parameter. The test suite defaults to (word32 "OUTx00")

-> ByteString

The echo tag, functionally identical to HKDF's info parameter.

-> Stream ByteString 

Turn a secret, derived HmacKeyHashed into an unbounded stream of 32-byte output blocks.

g3pSource Source #

Arguments

:: Foldable f 
=> G3PSalt

salt parameters, typically specified by deployment, typically needed throughout PHKDF key stretching

-> G3PInputs

input parameters, often provided by the user, ready to be forgotten soon after the computation starts

-> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSource

A plain-old-data representation of a G3P output stream

g3pSource_fromSpark Source #

Arguments

:: Foldable f 
=> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSpark 
-> G3PSource

plain-old data representation of an output stream

g3pSource_fromSeed Source #

Arguments

:: Foldable f 
=> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> G3PSource

plain-old data representation of an output stream

g3pSource_fromSprout Source #

Arguments

:: Foldable f 
=> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSprout

the middle of G3Pb2 delta

-> G3PSource

plain-old data representation of an output stream

g3pSource_fromTree Source #

Arguments

:: ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PTree

the end of G3Pb2 delta, the beginning of G3Pb2 echo

-> G3PSource

plain-old data representation of an output stream

g3pSource_fromKey Source #

Arguments

:: ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PKey

the middle of G3Pb2 echo

-> G3PSource

plain-old data representation of an output stream

data Stream a #

An infinite sequence.

Beware: If you use any function from the Eq or Ord class to compare two equal streams, these functions will diverge.

Constructors

Cons a (Stream a) infixr 5 

Instances

Instances details
Applicative Stream 
Instance details

Defined in Data.Stream

Methods

pure :: a -> Stream a #

(<*>) :: Stream (a -> b) -> Stream a -> Stream b #

liftA2 :: (a -> b -> c) -> Stream a -> Stream b -> Stream c #

(*>) :: Stream a -> Stream b -> Stream b #

(<*) :: Stream a -> Stream b -> Stream a #

Functor Stream 
Instance details

Defined in Data.Stream

Methods

fmap :: (a -> b) -> Stream a -> Stream b #

(<$) :: a -> Stream b -> Stream a #

Monad Stream 
Instance details

Defined in Data.Stream

Methods

(>>=) :: Stream a -> (a -> Stream b) -> Stream b #

(>>) :: Stream a -> Stream b -> Stream b #

return :: a -> Stream a #

Arbitrary a => Arbitrary (Stream a) 
Instance details

Defined in Data.Stream

Methods

arbitrary :: Gen (Stream a) #

shrink :: Stream a -> [Stream a] #

CoArbitrary a => CoArbitrary (Stream a) 
Instance details

Defined in Data.Stream

Methods

coarbitrary :: Stream a -> Gen b -> Gen b #

Show a => Show (Stream a)

A Show instance for Streams that takes the right associativity into account and so doesn't put parenthesis around the tail of the Stream. Note that show returns an infinite String.

Instance details

Defined in Data.Stream

Methods

showsPrec :: Int -> Stream a -> ShowS #

show :: Stream a -> String #

showList :: [Stream a] -> ShowS #

Eq a => Eq (Stream a) 
Instance details

Defined in Data.Stream

Methods

(==) :: Stream a -> Stream a -> Bool #

(/=) :: Stream a -> Stream a -> Bool #

Ord a => Ord (Stream a) 
Instance details

Defined in Data.Stream

Methods

compare :: Stream a -> Stream a -> Ordering #

(<) :: Stream a -> Stream a -> Bool #

(<=) :: Stream a -> Stream a -> Bool #

(>) :: Stream a -> Stream a -> Bool #

(>=) :: Stream a -> Stream a -> Bool #

max :: Stream a -> Stream a -> Stream a #

min :: Stream a -> Stream a -> Stream a #

Serial a => Serial (Stream a) 
Instance details

Defined in Data.Stream

Methods

series :: Series (Stream a) #

g3pStream_fromSpark Source #

Arguments

:: Foldable f 
=> G3PSeedInputs

bcrypt parameters

-> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSpark 
-> Stream ByteString 

g3pStream_fromSeed Source #

Arguments

:: Foldable f 
=> HmacKey

sprout seguid

-> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSeed

the end of G3Pb2 charlie, the beginning of G3Pb2 delta

-> Stream ByteString 

g3pStream_fromSprout Source #

Arguments

:: Foldable f 
=> f ByteString

sprout role

-> ByteString

sprout tag

-> ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PSprout 
-> Stream ByteString 

g3pStream_fromTree Source #

Arguments

:: ByteString

echo key right

-> ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PTree 
-> Stream ByteString 

g3pStream_fromKey Source #

Arguments

:: ByteString

echo header

-> Word32

echo counter

-> ByteString

echo tag

-> G3PKey 
-> Stream ByteString 

word32 :: ByteString -> Word32 #

>>> let buf = pack [1,2,3,4,5,6,7,8]
>>> word32 buf
16909060