| Copyright | 2020 Input Output (Hong Kong) Ltd. 2021-2022 Input Output Global Inc. (IOG) 2023-2025 Intersect |
|---|---|
| License | Apache-2.0 |
| Safe Haskell | None |
| Language | Haskell2010 |
Cardano.Address.Crypto
Description
Cryptographic primitives used by cardano-addresses.
This module centralises all cryptographic dependencies so that alternative backends (e.g. libsodium, pure-Haskell, WebCrypto) can be provided by replacing this single module.
Hashing a public key into a credential
Cardano Shelley addresses contain a 28-byte Blake2b-224 hash of the verification key (or script). This is the credential that appears on-chain.
>>> import Cardano.Address.Crypto >>> import qualified Data.ByteString as BS >>> let pubKeyBytes = BS.replicate 32 0 >>> BS.length (blake2b224 pubKeyBytes) 28 >>> credentialHashSize 28
Generating a root key from a seed
Byron uses ccGenerate (derivation scheme 1), Icarus and Shelley
use ccGenerateNew (derivation scheme 2 with PBKDF2).
>>> import Cardano.Address.Crypto
>>> import Data.ByteArray (ScrubbedBytes, convert)
>>> import qualified Data.ByteString as BS
>>> let seed = convert ("this is a seed that is at least 32 bytes long!!" :: BS.ByteString) :: ScrubbedBytes
>>> let xprv = ccGenerate seed (mempty :: ScrubbedBytes)
>>> let xpub = ccToXPub xprv
>>> BS.length (ccUnXPrv xprv)
128
Deriving child keys
Hardened derivation (index >= 0x80000000) requires the private key. Soft derivation can be done from the public key alone.
>>> import Cardano.Address.Crypto
>>> import Data.ByteArray (ScrubbedBytes, convert)
>>> import qualified Data.ByteString as BS
>>> let seed = convert ("this is a seed that is at least 32 bytes long!!" :: BS.ByteString) :: ScrubbedBytes
>>> let rootKey = ccGenerate seed (mempty :: ScrubbedBytes)
>>> let childKey = ccDeriveXPrv DerivationScheme2 (mempty :: ScrubbedBytes) rootKey 0x80000000
>>> let childPub = ccToXPub childKey
>>> BS.length (ccUnXPrv childKey)
128
Signing and verifying
>>> import Cardano.Address.Crypto
>>> import Data.ByteArray (ScrubbedBytes, convert)
>>> import qualified Data.ByteString as BS
>>> let seed = convert ("this is a seed that is at least 32 bytes long!!" :: BS.ByteString) :: ScrubbedBytes
>>> let xprv = ccGenerate seed (mempty :: ScrubbedBytes)
>>> let xpub = ccToXPub xprv
>>> let sig = ccSign (mempty :: ScrubbedBytes) xprv ("hello" :: BS.ByteString)
>>> ccVerify xpub ("hello" :: BS.ByteString) sig
True
Synopsis
- blake2b160 :: ByteArrayAccess a => a -> ByteString
- blake2b224 :: ByteArrayAccess a => a -> ByteString
- blake2b256 :: ByteArrayAccess a => a -> ByteString
- sha3_256 :: ByteArrayAccess a => a -> ByteString
- credentialHashSize :: Int
- pbkdf2HmacSha512 :: (ByteArrayAccess password, ByteArrayAccess salt) => Int -> Int -> password -> salt -> ScrubbedBytes
- hmacSha256 :: (ByteArrayAccess key, ByteArrayAccess msg) => key -> msg -> ByteString
- hmacSha512 :: (ByteArrayAccess key, ByteArrayAccess msg) => key -> msg -> ByteString
- encryptChaChaPoly1305 :: ByteArrayAccess key => key -> ByteString -> ByteString -> CryptoFailable ByteString
- decryptChaChaPoly1305 :: ByteArrayAccess key => key -> ByteString -> ByteString -> CryptoFailable ByteString
- ed25519ScalarMult :: ByteString -> Maybe ByteString
- ccXPrv :: ByteString -> Either String XPrv
- ccXPub :: ByteString -> Either String XPub
- ccUnXPrv :: XPrv -> ByteString
- ccToXPub :: XPrv -> XPub
- ccSign :: ByteArrayAccess msg => ScrubbedBytes -> XPrv -> msg -> XSignature
- ccVerify :: ByteArrayAccess msg => XPub -> msg -> XSignature -> Bool
- ccGenerate :: ByteArrayAccess seed => seed -> ScrubbedBytes -> XPrv
- ccGenerateNew :: (ByteArrayAccess seed, ByteArrayAccess sndFactor) => seed -> sndFactor -> ScrubbedBytes -> XPrv
- ccDeriveXPrv :: DerivationScheme -> ScrubbedBytes -> XPrv -> Word32 -> XPrv
- ccDeriveXPub :: DerivationScheme -> XPub -> Word32 -> Maybe XPub
- getEntropy :: Int -> IO ScrubbedBytes
- crc32 :: ByteString -> Word32
- data CryptoError
- = CryptoError_KeySizeInvalid
- | CryptoError_IvSizeInvalid
- | CryptoError_SeedSizeInvalid
- | CryptoError_AEADModeNotSupported
- | CryptoError_SecretKeySizeInvalid
- | CryptoError_SecretKeyStructureInvalid
- | CryptoError_PublicKeySizeInvalid
- | CryptoError_SharedSecretSizeInvalid
- | CryptoError_EcScalarOutOfBounds
- | CryptoError_PointSizeInvalid
- | CryptoError_PointFormatInvalid
- | CryptoError_PointFormatUnsupported
- | CryptoError_PointCoordinatesInvalid
- | CryptoError_ScalarMultiplicationInvalid
- | CryptoError_MacKeyInvalid
- | CryptoError_AuthenticationTagSizeInvalid
- | CryptoError_PrimeSizeInvalid
- | CryptoError_SaltTooSmall
- | CryptoError_OutputLengthTooSmall
- | CryptoError_OutputLengthTooBig
- data CryptoFailable a
- eitherCryptoError :: CryptoFailable a -> Either CryptoError a
- data ScrubbedBytes
- class ByteArrayAccess ba
- convert :: (ByteArrayAccess bin, ByteArray bout) => bin -> bout
Hashing
blake2b160 :: ByteArrayAccess a => a -> ByteString #
Blake2b-160 hash (20 bytes). Used for wallet ID computation from an extended root or account key.
blake2b224 :: ByteArrayAccess a => a -> ByteString #
Blake2b-224 hash (28 bytes), used for credential hashing.
blake2b256 :: ByteArrayAccess a => a -> ByteString #
Blake2b-256 hash (32 bytes). Used for Byron seed hashing (double CBOR-serialized entropy).
sha3_256 :: ByteArrayAccess a => a -> ByteString #
SHA3-256 hash. Used together with blake2b224 to compute
Byron address roots: blake2b224 . sha3_256.
Size in bytes of a Blake2b-224 credential hash (28).
Key derivation functions
Arguments
| :: (ByteArrayAccess password, ByteArrayAccess salt) | |
| => Int | Number of iterations |
| -> Int | Desired output length in bytes |
| -> password | |
| -> salt | |
| -> ScrubbedBytes |
PBKDF2 with HMAC-SHA512. Used for:
- Byron HD passphrase derivation (500 iterations, 32 bytes)
- Icarus/Shelley mnemonic-to-seed (4096 iterations, 96 bytes)
- Ledger hardware wallet BIP39 seed (2048 iterations, 64 bytes)
HMAC
hmacSha256 :: (ByteArrayAccess key, ByteArrayAccess msg) => key -> msg -> ByteString #
HMAC-SHA256. Used in Ledger hardware wallet key derivation for computing the chain code from the initial seed.
hmacSha512 :: (ByteArrayAccess key, ByteArrayAccess msg) => key -> msg -> ByteString #
HMAC-SHA512. Used in Ledger hardware wallet key derivation
(SLIP-0010 master key generation with "ed25519 seed" as key).
Symmetric encryption
Arguments
| :: ByteArrayAccess key | |
| => key | |
| -> ByteString | 12-byte nonce |
| -> ByteString | Plaintext |
| -> CryptoFailable ByteString | Ciphertext with 16-byte authentication tag appended |
ChaCha20-Poly1305 authenticated encryption. Used for encrypting Byron address derivation paths (account and address indices) with the HD passphrase.
The key must be 32 bytes, the nonce 12 bytes.
Arguments
| :: ByteArrayAccess key | |
| => key | |
| -> ByteString | 12-byte nonce |
| -> ByteString | Ciphertext with 16-byte authentication tag appended |
| -> CryptoFailable ByteString |
ChaCha20-Poly1305 authenticated decryption. Used for decrypting Byron address derivation paths when inspecting Byron addresses with a known root public key.
The key must be 32 bytes, the nonce 12 bytes.
Ed25519 curve operations
ed25519ScalarMult :: ByteString -> Maybe ByteString #
Ed25519 scalar multiplication: decode a scalar from a long
bytestring and compute the corresponding public point.
Used internally by xprvFromBytes
to reconstruct the public key from a 96-byte extended private key.
Extended keys (re-exports from cardano-crypto)
ccXPrv :: ByteString -> Either String XPrv #
Construct an XPrv from raw bytes (128 bytes: 64 private + 32 public + 32 chain code).
ccXPub :: ByteString -> Either String XPub #
Construct an XPub from raw bytes (64 bytes: 32 public + 32 chain code).
ccUnXPrv :: XPrv -> ByteString #
Extract raw bytes from an XPrv (128 bytes: 64 prv + 32 pub + 32 cc).
ccSign :: ByteArrayAccess msg => ScrubbedBytes -> XPrv -> msg -> XSignature #
Sign a message with an XPrv.
ccVerify :: ByteArrayAccess msg => XPub -> msg -> XSignature -> Bool #
Verify a signature with an XPub.
ccGenerate :: ByteArrayAccess seed => seed -> ScrubbedBytes -> XPrv #
Generate an XPrv from a seed (legacy Byron method).
The seed must be >= 32 bytes. Uses HMAC-SHA512 internally
with repeated hashing until a valid Ed25519 extended key is found.
ccGenerateNew :: (ByteArrayAccess seed, ByteArrayAccess sndFactor) => seed -> sndFactor -> ScrubbedBytes -> XPrv #
Generate an XPrv from a seed with second factor (Icarus/Shelley method).
Uses PBKDF2-HMAC-SHA512 (4096 iterations, 96 bytes) to stretch
the mnemonic entropy. The second factor is an optional passphrase.
ccDeriveXPrv :: DerivationScheme -> ScrubbedBytes -> XPrv -> Word32 -> XPrv #
Derive a child XPrv from a parent XPrv.
Supports both hardened (index >= 0x80000000) and soft derivation.
DerivationScheme1 is used for Byron, DerivationScheme2 for
Icarus/Shelley (BIP-44 compatible).
ccDeriveXPub :: DerivationScheme -> XPub -> Word32 -> Maybe XPub #
Random
getEntropy :: Int -> IO ScrubbedBytes #
Obtain cryptographic entropy from the system.
Used for BIP-39 entropy generation (genEntropy).
CRC32 (Byron address checksum)
crc32 :: ByteString -> Word32 #
CRC32 checksum (ISO 3309 / ITU-T V.42).
Crypto error handling (re-exports from crypton)
data CryptoError #
Enumeration of all possible errors that can be found in this library
Constructors
Instances
data CryptoFailable a #
A simple Either like type to represent a computation that can fail
2 possibles values are:
CryptoPassed: The computation succeeded, and contains the result of the computationCryptoFailed: The computation failed, and contains the cryptographic error associated
Constructors
| CryptoPassed a | |
| CryptoFailed CryptoError |
Instances
eitherCryptoError :: CryptoFailable a -> Either CryptoError a #
Transform a CryptoFailable to an Either
Byte array utilities (re-exports from memory)
data ScrubbedBytes #
ScrubbedBytes is a memory chunk which have the properties of:
- Being scrubbed after its goes out of scope.
- A Show instance that doesn't actually show any content
- A Eq instance that is constant time
Instances
class ByteArrayAccess ba #
Class to Access size properties and data of a ByteArray
Minimal complete definition
Instances
convert :: (ByteArrayAccess bin, ByteArray bout) => bin -> bout #
Convert a bytearray to another type of bytearray