split binary_types + clean up
This commit is contained in:
parent
9fe1d76dc4
commit
0c5622324c
8 changed files with 449 additions and 515 deletions
326
src/bin_type.ml
Normal file
326
src/bin_type.ml
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
(* https://docs.taler.net/core/api-common.html#binary-formats
|
||||
|
||||
numeric values are in network byte order (big endian) *)
|
||||
|
||||
(* structs that are 'packed' and do not contain pointers and are
|
||||
thus suitable for hashing or similar operations are distinguished
|
||||
by adding a 'P' at the end of the name.
|
||||
(NEW) Note that this convention does not hold for the GNUnet-structs (yet).
|
||||
|
||||
structs that are used with a purpose for signatures,
|
||||
additionally get an 'S' at the end of the name.
|
||||
|
||||
(from https://docs.taler.net/taler-developer-manual.html) *)
|
||||
|
||||
(* TODO
|
||||
- correctly handle endianness
|
||||
- check that our struct are well packed
|
||||
- it looks like Bin only define packed structs
|
||||
- we don't need to worry about struct having "P" suffix
|
||||
remove them
|
||||
- test them
|
||||
- union: not sure what to do of them
|
||||
not needed or relevant i think
|
||||
- some purpose (`TALER_SIGNATURE_XXX`) are missing
|
||||
- exchange and gana master branch are not in sync
|
||||
and we should use a specific git tag instead
|
||||
- outdated doc(?)
|
||||
- some missing struct documentation
|
||||
|
||||
- better way to have module aliases?
|
||||
*)
|
||||
|
||||
(* TODO hash and C(ancer)-terminated strings
|
||||
|
||||
- "A JSON object is canonicalized by converting it to an ASCII byte array
|
||||
with the algorithm specified in RFC 8785. The resulting bytes are
|
||||
terminated with a single 0-byte and then hashed with SHA512."
|
||||
- from the code it looks like its the same for all stringy-strings
|
||||
! not strings that are raw-bytes-data-like
|
||||
? only for "HashCode" and "ShortHashCode"
|
||||
*)
|
||||
|
||||
module Taler_signatures = Include.Taler_signatures
|
||||
open Crypto
|
||||
|
||||
let int32_size = 4
|
||||
let int64_size = 8
|
||||
|
||||
module Bytes_32 = struct
|
||||
type t = string
|
||||
|
||||
let bin = Bin.bytes 32
|
||||
end
|
||||
|
||||
module Bytes_64 = struct
|
||||
type t = string
|
||||
|
||||
let bin = Bin.bytes 64
|
||||
end
|
||||
|
||||
(* microseconds since the UNIX Epoch
|
||||
UINT64_MAX represents "never" *)
|
||||
module INT64 = struct
|
||||
type t = int64
|
||||
|
||||
let bin = Bin.neint64
|
||||
let of_ptime v = Util.ptime_to_int64 v
|
||||
end
|
||||
|
||||
module INT64_NBO = struct
|
||||
type t = int64
|
||||
|
||||
let bin = Bin.beint64
|
||||
let of_ptime = Util.ptime_to_int64
|
||||
end
|
||||
|
||||
(* -- Time -- *)
|
||||
module type Time_S = sig
|
||||
type t
|
||||
|
||||
val bin : t Bin.t
|
||||
val of_ptime : Ptime.t -> t
|
||||
end
|
||||
|
||||
module TimeAbsolute : Time_S = INT64
|
||||
module TimeAbsoluteNBO : Time_S = INT64_NBO
|
||||
module TimeRelative : Time_S = INT64
|
||||
module TimeRelativeNBO : Time_S = INT64_NBO
|
||||
module Timestamp : Time_S = INT64
|
||||
module TimestampNBO : Time_S = INT64_NBO
|
||||
|
||||
(* -- Cryptographic primitives -- *)
|
||||
|
||||
(* Hashes *)
|
||||
|
||||
module Hash_32 = struct
|
||||
type t = Digestif.SHA256.t
|
||||
|
||||
let hash s = Digestif.SHA256.(digest_string s)
|
||||
|
||||
let of_octets s =
|
||||
match String.length s = 32 with
|
||||
| false -> Fmt.failwith "Hash.of_octets failure: data is not 32 bytes"
|
||||
| true -> Digestif.SHA256.of_raw_string s
|
||||
|
||||
let to_octets = Digestif.SHA256.to_raw_string
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
map (bytes 32) of_octets to_octets
|
||||
end
|
||||
|
||||
module Hash_64 = struct
|
||||
type t = Digestif.SHA512.t
|
||||
|
||||
let hash s = Digestif.SHA512.(digest_string s)
|
||||
|
||||
let of_octets s =
|
||||
match String.length s = 64 with
|
||||
| false -> Fmt.failwith "Hash.of_octets failure: data is not 64 bytes"
|
||||
| true -> Digestif.SHA512.of_raw_string s
|
||||
|
||||
let to_octets = Digestif.SHA512.to_raw_string
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
map (bytes 64) of_octets to_octets
|
||||
end
|
||||
|
||||
(* Hash over string + '\0' *)
|
||||
module Hash_32_cstr = struct
|
||||
type t = Digestif.SHA256.t
|
||||
|
||||
let hash s =
|
||||
let s = s ^ "\x00" in
|
||||
Digestif.SHA256.(digest_string s)
|
||||
|
||||
let of_octets s =
|
||||
match String.length s = 32 with
|
||||
| false -> Fmt.failwith "Hash.of_octets failure: data is not 32 bytes"
|
||||
| true -> Digestif.SHA256.of_raw_string s
|
||||
|
||||
let to_octets = Digestif.SHA256.to_raw_string
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
map (bytes 32) of_octets to_octets
|
||||
end
|
||||
|
||||
module Hash_64_cstr = struct
|
||||
type t = Digestif.SHA512.t
|
||||
|
||||
let hash s =
|
||||
let s = s ^ "\x00" in
|
||||
Digestif.SHA512.(digest_string s)
|
||||
|
||||
let of_octets s =
|
||||
match String.length s = 64 with
|
||||
| false -> Fmt.failwith "Hash.of_octets failure: data is not 64 bytes"
|
||||
| true -> Digestif.SHA512.of_raw_string s
|
||||
|
||||
let to_octets = Digestif.SHA512.to_raw_string
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
map (bytes 64) of_octets to_octets
|
||||
end
|
||||
|
||||
module type Hash_S = sig
|
||||
type t
|
||||
|
||||
val bin : t Bin.t
|
||||
val hash : string -> t
|
||||
val of_octets : string -> t
|
||||
val to_octets : t -> string
|
||||
end
|
||||
|
||||
module FullPaytoHash : Hash_S = Hash_32
|
||||
module NormalizedPaytoHash : Hash_S = Hash_32
|
||||
module DenominationHash : Hash_S = Hash_64
|
||||
module PrivateContractHash : Hash_S = Hash_64
|
||||
module ExtensionsPolicyHash : Hash_S = Hash_64
|
||||
module MerchantWireHash : Hash_S = Hash_64
|
||||
module AgeCommitmentHash : Hash_S = Hash_64
|
||||
module BlindedCoinHash : Hash_S = Hash_64
|
||||
module CoinPubHash : Hash_S = Hash_64
|
||||
module OutputCommitmentHash : Hash_S = Hash_64
|
||||
module HashPlanchetsP : Hash_S = Hash_64
|
||||
|
||||
(* --- Various --- *)
|
||||
|
||||
module TransferSecretP = Bytes_64
|
||||
module LinkSecretP = Bytes_64
|
||||
module EncryptedLinkSecretP = Bytes_64
|
||||
module BlindingMasterSeed = Bytes_32
|
||||
module BlindingMasterSecret = Bytes_32
|
||||
module WireTransferIdentifierRawP = Bytes_32
|
||||
module PublicRefreshCoinNonceP = Bytes_64
|
||||
|
||||
(* TODO ? need to use/save a specific nonce for cryptographic blinding *)
|
||||
(* Secret for blinding/unblinding.
|
||||
An RSA blinding secret, which is basically
|
||||
a 256-bit nonce, converted to Crockford `Base32`.
|
||||
|
||||
type DenominationBlindingKeyP = string; *)
|
||||
module DenominationBlindingKeyP = Bytes_32
|
||||
module RefreshCommitmentP = Bytes_64
|
||||
|
||||
(* -- TODO better: -- *)
|
||||
module UUID = struct
|
||||
(* uint32t value[4]; *)
|
||||
type t = { value: string }
|
||||
|
||||
let size = 4 * int32_size
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
record (fun value -> { value })
|
||||
|+ field (bytes size) (fun t -> t.value)
|
||||
|> sealr
|
||||
end
|
||||
|
||||
module WadId = struct
|
||||
(* uint32t value[6]; *)
|
||||
type t = { raw: string }
|
||||
|
||||
let size = 6 * int32_size
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
record (fun raw -> { raw }) |+ field (bytes size) (fun t -> t.raw) |> sealr
|
||||
end
|
||||
|
||||
module AgeMask = struct
|
||||
type t = { mask: int32 }
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
record (fun mask -> { mask }) |+ field beint32 (fun t -> t.mask) |> sealr
|
||||
end
|
||||
|
||||
(* TODO
|
||||
- why is the non-NBO version only used in TALER_WithdrawRequestPS?
|
||||
- correctly do the padding and 0-termination
|
||||
- handle "invalid" values *)
|
||||
(* documentation: *)
|
||||
(* Number of characters (plus 1 for 0-termination) for currency names.
|
||||
typically an ISO 4217 currency code when an alphanumeric 3-digit code is used.
|
||||
For regional currencies, the first character should be a "*" followed
|
||||
by a region-specific name (i.e. "*BRETAGNEFR").
|
||||
Currency codes are compared case-insensitively.
|
||||
|
||||
Currency string, left adjusted and padded with zeros.
|
||||
All zeros for "invalid" values.
|
||||
|
||||
Name of the currency, using either a three-character ISO 4217 currency
|
||||
code, or a regional currency identifier between 4 and 11 characters,
|
||||
consisting of ASCII alphabetic characters ("a-zA-Z").
|
||||
Should be padded to 12 bytes with 0-characters.
|
||||
Currency codes are compared case-insensitively. *)
|
||||
let currency_len = 12
|
||||
|
||||
(* TODO missing doc
|
||||
found in src/include/taler/taler_amount_lib.h *)
|
||||
module AmountP = struct
|
||||
type t = {
|
||||
value: int64;
|
||||
fraction: int32;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
(* TODO BE here? *)
|
||||
let bin =
|
||||
let open Bin in
|
||||
record (fun value fraction currency -> { value; fraction; currency })
|
||||
|+ field beint64 (fun t -> t.value)
|
||||
|+ field beint32 (fun t -> t.fraction)
|
||||
|+ field (bytes currency_len) (fun t -> t.currency)
|
||||
|> sealr
|
||||
end
|
||||
|
||||
module AmountNBO = struct
|
||||
type t = {
|
||||
value: int64;
|
||||
fraction: int32;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
let bin =
|
||||
let open Bin in
|
||||
record (fun value fraction currency -> { value; fraction; currency })
|
||||
|+ field beint64 (fun t -> t.value)
|
||||
|+ field beint32 (fun t -> t.fraction)
|
||||
|+ field (bytes currency_len) (fun t -> t.currency)
|
||||
|> sealr
|
||||
end
|
||||
|
||||
(* TODO keep this?
|
||||
some of those are actuall ecdhe, or union of eddsa|ecdhe *)
|
||||
module Aliases = struct
|
||||
(* TODO add Amount.bin *)
|
||||
module Amount = AmountP
|
||||
|
||||
(* - Keys - *)
|
||||
module PursePublicKey = EddsaPublicKey
|
||||
module AuditorPublicKeyP = EddsaPublicKey
|
||||
module ReservePublicKeyP = EddsaPublicKey
|
||||
module MerchantPublicKeyP = EddsaPublicKey
|
||||
module TransferPublicKeyP = EddsaPublicKey
|
||||
module AmlOfficerPublicKeyP = EddsaPublicKey
|
||||
module ExchangePublicKeyP = EddsaPublicKey
|
||||
module MasterPublicKeyP = EddsaPublicKey
|
||||
module CoinSpendPublicKeyP = EddsaPublicKey
|
||||
module TokenPublicKeyP = EddsaPublicKey
|
||||
module ReservePrivateKeyP = EddsaPrivateKey
|
||||
module MerchantPrivateKeyP = EddsaPrivateKey
|
||||
module TransferPrivateKeyP = EddsaPrivateKey
|
||||
module AmlOfficerPrivateKeyP = EddsaPrivateKey
|
||||
module ExchangePrivateKeyP = EddsaPrivateKey
|
||||
module MasterPrivateKeyP = EddsaPrivateKey
|
||||
module CoinSpendPrivateKeyP = EddsaPrivateKey
|
||||
module MasterSignatureP = EddsaSignature
|
||||
module ReserveSignatureP = EddsaSignature
|
||||
module ExchangeSignatureP = EddsaSignature
|
||||
module CoinSpendSignatureP = EddsaSignature
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue