Copyright | (c) 2024 Auth Global |
---|---|
License | Apache2 |
Safe Haskell | Safe-Inferred |
Language | Haskell2010 |
Crypto.G3P.V1
Description
Synopsis
- data G3PInputBlock = G3PInputBlock {}
- data G3PInputArgs = G3PInputArgs {
- g3pInputArgs_username :: !ByteString
- g3pInputArgs_password :: !ByteString
- g3pInputArgs_credentials :: !(Vector ByteString)
- newtype G3PInputRole = G3PInputRole {
- g3pInputRole_roleTags :: Vector ByteString
- newtype G3PInputEcho = G3PInputEcho {}
- data G3PSeed = G3PSeed {}
- data G3PKey = G3PKey {}
- data G3PGen = G3PGen {}
- g3pHash :: G3PInputBlock -> G3PInputArgs -> G3PInputRole -> G3PInputEcho -> Stream ByteString
- g3pHash_seedInit :: G3PInputBlock -> G3PInputArgs -> G3PSeed
- g3pHash_keyInit :: G3PInputRole -> G3PSeed -> G3PKey
- g3pHash_finalizeGen :: G3PInputEcho -> G3PKey -> G3PGen
- g3pGen_read :: G3PGen -> (ByteString, G3PGen)
- g3pGen_finalizeStream :: G3PGen -> Stream ByteString
Documentation
data G3PInputBlock Source #
These input parameters are grouped together because the envisioned use for them is that they are constants (or near-constants) specified by a deployment. 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
, longTag
, bcryptTag
, and bcryptSaltTag
parameters. Specifying an empty string in any 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
G3PInputBlock | |
Fields
|
Instances
Show G3PInputBlock Source # | |
Defined in Crypto.G3P.V1 Methods showsPrec :: Int -> G3PInputBlock -> ShowS # show :: G3PInputBlock -> String # showList :: [G3PInputBlock] -> ShowS # | |
Eq G3PInputBlock Source # | |
Defined in Crypto.G3P.V1 Methods (==) :: G3PInputBlock -> G3PInputBlock -> Bool # (/=) :: G3PInputBlock -> G3PInputBlock -> Bool # | |
Ord G3PInputBlock Source # | |
Defined in Crypto.G3P.V1 Methods compare :: G3PInputBlock -> G3PInputBlock -> Ordering # (<) :: G3PInputBlock -> G3PInputBlock -> Bool # (<=) :: G3PInputBlock -> G3PInputBlock -> Bool # (>) :: G3PInputBlock -> G3PInputBlock -> Bool # (>=) :: G3PInputBlock -> G3PInputBlock -> Bool # max :: G3PInputBlock -> G3PInputBlock -> G3PInputBlock # min :: G3PInputBlock -> G3PInputBlock -> G3PInputBlock # |
data G3PInputArgs Source #
The username and password are grouped together because they are normally expected to be supplied by users or other observers of a deployment.
Furthermore, the credentials vector is here because it is an ideal location to include other user 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 3 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. Note that the bcrypt tag can subtract up to 113 bytes from the 8 KiB total, and don't effect the 3 KiB total.
In the case of all of the inputs in this record, longer values incur one SHA256 block per 64 bytes.
Constructors
G3PInputArgs | |
Fields
|
Instances
Show G3PInputArgs Source # | |
Defined in Crypto.G3P.V1 Methods showsPrec :: Int -> G3PInputArgs -> ShowS # show :: G3PInputArgs -> String # showList :: [G3PInputArgs] -> ShowS # | |
Eq G3PInputArgs Source # | |
Defined in Crypto.G3P.V1 | |
Ord G3PInputArgs Source # | |
Defined in Crypto.G3P.V1 Methods compare :: G3PInputArgs -> G3PInputArgs -> Ordering # (<) :: G3PInputArgs -> G3PInputArgs -> Bool # (<=) :: G3PInputArgs -> G3PInputArgs -> Bool # (>) :: G3PInputArgs -> G3PInputArgs -> Bool # (>=) :: G3PInputArgs -> G3PInputArgs -> Bool # max :: G3PInputArgs -> G3PInputArgs -> G3PInputArgs # min :: G3PInputArgs -> G3PInputArgs -> G3PInputArgs # |
newtype G3PInputRole Source #
These parameters are used to tweak the final output, without redoing any expensive key stretching. A possible use case is including a high entropy secret in the role itself that isn't available until after a successful stage of authentication.
Since these parameters are processed in a context that could conceivably be performance sensitive, we don't apply any length padding or side-channel hardening. Instead we opt for maximizing free tagging space. Thus we want to avoid incurring additional SHA256 block computations, one of the favorite techniques employed by the key-stretching phase of the G3P to harden against timing side-channels.
A deployment could conceivably harden this expansion phase against timing side channels themselves, if the were sufficiently inclined. There are several techniques. For starters, a deployment could ensure that these parameters themselves are constant-length. Alternatively, a deployment could specify an additional variable-length string in the role vector, used to control the ending position relative to the SHA256 buffer.
Constructors
G3PInputRole | |
Fields
|
Instances
Show G3PInputRole Source # | |
Defined in Crypto.G3P.V1 Methods showsPrec :: Int -> G3PInputRole -> ShowS # show :: G3PInputRole -> String # showList :: [G3PInputRole] -> ShowS # | |
Eq G3PInputRole Source # | |
Defined in Crypto.G3P.V1 | |
Ord G3PInputRole Source # | |
Defined in Crypto.G3P.V1 Methods compare :: G3PInputRole -> G3PInputRole -> Ordering # (<) :: G3PInputRole -> G3PInputRole -> Bool # (<=) :: G3PInputRole -> G3PInputRole -> Bool # (>) :: G3PInputRole -> G3PInputRole -> Bool # (>=) :: G3PInputRole -> G3PInputRole -> Bool # max :: G3PInputRole -> G3PInputRole -> G3PInputRole # min :: G3PInputRole -> G3PInputRole -> G3PInputRole # |
newtype G3PInputEcho Source #
Constructors
G3PInputEcho | |
Fields
|
Instances
Show G3PInputEcho Source # | |
Defined in Crypto.G3P.V1 Methods showsPrec :: Int -> G3PInputEcho -> ShowS # show :: G3PInputEcho -> String # showList :: [G3PInputEcho] -> ShowS # | |
Eq G3PInputEcho Source # | |
Defined in Crypto.G3P.V1 | |
Ord G3PInputEcho Source # | |
Defined in Crypto.G3P.V1 Methods compare :: G3PInputEcho -> G3PInputEcho -> Ordering # (<) :: G3PInputEcho -> G3PInputEcho -> Bool # (<=) :: G3PInputEcho -> G3PInputEcho -> Bool # (>) :: G3PInputEcho -> G3PInputEcho -> Bool # (>=) :: G3PInputEcho -> G3PInputEcho -> Bool # max :: G3PInputEcho -> G3PInputEcho -> G3PInputEcho # min :: G3PInputEcho -> G3PInputEcho -> G3PInputEcho # |
A plain-old-data explicit representation of the intermediate g3pHash
computation after the G3PInputBlock
and G3PInputArgs
have been
processed and key stretching has been completed, but before the tweaks
have been applied and the final output generated.
If you ever need to serialize or persist a seed, you probably want this.
Intended to be generated by g3pHash_seedInit
and consumed
by g3pHash_seedFinalize
.
Constructors
G3PSeed | |
Fields
|
Constructors
G3PKey | |
Fields |
Constructors
G3PGen | |
Fields |
g3pHash :: G3PInputBlock -> G3PInputArgs -> G3PInputRole -> G3PInputEcho -> Stream ByteString Source #
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.
let mySeed = g3pHash block args myKey0 = mySeed myRole0 myKey1 = mySeed myRole1 in [ myKey0 myEcho, myKey0 altEcho, myKey1 myEcho, myKey1 altEcho ]
Although the savings from sharing the computation of the seed among all
four computations is much larger, this expression also shares the
computation of the G3PKey
among these four output streams, so that
only two keys are computed.
In the case that you want or need to persist or serialize the intermediate
seed, or change the seguid or domain tag before final output expansion,
then the plain-old-datatype G3PSeed
and its companion functions
g3pHash_keyInit
and g3pHash_finalizeGen
are needed.
g3pHash_seedInit :: G3PInputBlock -> G3PInputArgs -> G3PSeed Source #
This generates a seed, which encapsulates the expensive key-stretching
component of g3pHash
into a reusable, tweakable cryptographic value.
This function is way slower than it's companions, g3pHash_keyInit
and
g3pHash_finalizeGen
Broadly comparable to PBKDF2, and incorporates bcrypt.
g3pHash_keyInit :: G3PInputRole -> G3PSeed -> G3PKey Source #
This applies the role vector to a computed G3P seed to arrive at
a precomputed G3P key used during the final output expansion.
Broadly comparable to HKDF-Extract
. This function applies no
key stretching, and thus output can be available in as little as
6 or 7 SHA256 block computations when you vary its parameters.
Note that this function ignores g3pSeed_seguid
in favor of
g3pSeed_seguidKey
.
g3pHash_finalizeGen :: G3PInputEcho -> G3PKey -> G3PGen Source #
Apply the echo tag parameter to a precomputed G3P key, obtaining a
cryptographically secure output generator. Broadly comparable to
HKDF-Expand
. Applies no key stretching, so output is available in
as little as 2 SHA256 block computations.
g3pGen_read :: G3PGen -> (ByteString, G3PGen) Source #
Read a 32-byte hash from the G3P's output generator.
g3pGen_finalizeStream :: G3PGen -> Stream ByteString Source #
Turn a G3P output generator into an unbounded stream.