Documentation
¶
Overview ¶
Go implementation of the XMSS[MT] post-quantum stateful hash-based signature scheme as described in RFC 8391.
Example ¶
// Create a new keypair. See ListNames(). sk, pk, err := xmssmt.GenerateKeyPair("XMSSMT-SHA2_20/4_256", "key") if err != nil { panic(err) } // Sign a message sig, err := sk.Sign([]byte("Example message!")) if err != nil { panic(err) } sigBytes, _ := sig.MarshalBinary() // serialize signature pkBytes, _ := pk.MarshalBinary() // serialize public key fmt.Printf("len(sigBytes)=%d len(pkBytes)=%d\n", len(sigBytes), len(pkBytes)) sk.Close() // close the private key container // To verify we can simply use the Verify() method on PublicKey valid, _ := pk.Verify(sig, []byte("Example message!")) fmt.Printf("Valid=%v\n", valid) // Or we can use the helper xmssmt.Verify() on serialized signature and pk valid, _ = xmssmt.Verify(pkBytes, sigBytes, []byte("Example message!")) fmt.Printf("Valid=%v\n", valid) // To sign a new message, we open the private key container again sk, pk, _, _ = xmssmt.LoadPrivateKey("key") sig2, _ := sk.Sign([]byte("Other message")) valid, _ = pk.Verify(sig2, []byte("Other message")) fmt.Printf("Valid=%v\n", valid) sk.Close() // Or pwe can simply use the xmssmt.Sign() helper. pkBytes, _ = pk.MarshalBinary() sig3Bytes, _ := xmssmt.Sign("key", []byte("Third message")) valid, _ = xmssmt.Verify(pkBytes, sig3Bytes, []byte("Third message")) fmt.Printf("Valid=%v\n", valid)
Output:
Index ¶
- Constants
- func EnableLogging()
- func GenerateKeyPair(alg, privKeyPath string) (*PrivateKey, *PublicKey, Error)
- func ListNames() (names []string)
- func ListNames2() (names []string)
- func LoadPrivateKey(path string) (sk *PrivateKey, pk *PublicKey, lostSigs uint32, err Error)
- func LoadPrivateKeyFrom(ctr PrivateKeyContainer) (sk *PrivateKey, pk *PublicKey, lostSigs uint32, err Error)
- func NewContext(params Params) (ctx *Context, err Error)
- func NewContextFromName2(name string) (*Context, Error)
- func OpenFSPrivateKeyContainer(path string) (PrivateKeyContainer, Error)
- func ParamsFromName2(name string) (*Params, Error)
- func SetLogger(logger Logger)
- type Context
- func (ctx *Context) Derive(path string, pubSeed, skSeed, skPrf []byte) (*PrivateKey, *PublicKey, Error)
- func (ctx *Context) DeriveInto(ctr PrivateKeyContainer, pubSeed, skSeed, skPrf []byte) (*PrivateKey, *PublicKey, Error)
- func (ctx *Context) FromNIST() bool
- func (ctx *Context) FromRFC() bool
- func (ctx *Context) GenerateKeyPair(path string) (*PrivateKey, *PublicKey, Error)
- func (ctx *Context) MT() bool
- func (ctx *Context) Name() string
- func (ctx *Context) Oid() uint32
- func (ctx *Context) Params() Params
- func (ctx *Context) SignatureSize() uint32
- type Error
- type HashFunc
- type Logger
- type Params
- func (params *Params) BareSubTreeSize() int
- func (params *Params) CachedSubTreeSize() int
- func (params *Params) LookupNameAndOid() (string, uint32)
- func (params *Params) MarshalBinary() ([]byte, error)
- func (params *Params) MaxSignatureSeqNo() uint64
- func (params *Params) PrivateKeySize() int
- func (p Params) String() string
- func (params *Params) UnmarshalBinary(buf []byte) error
- func (params *Params) WotsLen() uint32
- func (params *Params) WotsLen1() uint32
- func (params *Params) WotsLen2() uint32
- func (params *Params) WotsLogW() uint8
- func (params *Params) WotsSignatureSize() uint32
- func (params *Params) WriteInto(buf []byte) error
- type PrfConstruction
- type PrivateKey
- func (sk *PrivateKey) BorrowExactly(amount uint32) Error
- func (sk *PrivateKey) BorrowExactlyIfBelow(amount, treshHold uint32) Error
- func (sk *PrivateKey) BorrowedSeqNos() uint32
- func (sk *PrivateKey) CachedSubTrees() int
- func (sk *PrivateKey) Close() Error
- func (sk *PrivateKey) Context() *Context
- func (sk *PrivateKey) DangerousSetSeqNo(seqNo SignatureSeqNo)
- func (sk *PrivateKey) EnableSubTreePrecomputation()
- func (sk *PrivateKey) PublicKey() *PublicKey
- func (sk *PrivateKey) SeqNo() SignatureSeqNo
- func (sk *PrivateKey) Sign(msg []byte) (*Signature, Error)
- func (sk *PrivateKey) SignFrom(msg io.Reader) (*Signature, Error)
- func (sk *PrivateKey) UnretiredSeqNos() uint32
- type PrivateKeyContainer
- type PublicKey
- func (pk *PublicKey) Context() *Context
- func (pk *PublicKey) MarshalBinary() ([]byte, error)
- func (pk *PublicKey) MarshalText() ([]byte, error)
- func (pk *PublicKey) UnmarshalBinary(buf []byte) error
- func (pk *PublicKey) UnmarshalText(text []byte) error
- func (pk *PublicKey) Verify(sig *Signature, msg []byte) (bool, Error)
- func (pk *PublicKey) VerifyFrom(sig *Signature, msg io.Reader) (bool, Error)
- func (pk *PublicKey) WriteInto(buf []byte) error
- type Signature
- type SignatureSeqNo
- type SubTreeAddress
Examples ¶
Constants ¶
const ( ADDR_TYPE_OTS = 0 ADDR_TYPE_LTREE = 1 ADDR_TYPE_HASHTREE = 2 )
const ( // First 8 bytes (in hex) of the secret key file FS_CONTAINER_KEY_MAGIC = "4089430a5ced6844" // First 8 bytes (in hex) of the subtree cache file FS_CONTAINER_CACHE_MAGIC = "e77957607ef79446" FS_CONTAINER_CACHE_MAGIC2 = "5a11d7cf4a1f6314" )
const ( HASH_PADDING_F = 0 HASH_PADDING_H = 1 HASH_PADDING_HASH = 2 HASH_PADDING_PRF = 3 HASH_PADDING_PRF_KEYGEN = 4 )
Variables ¶
This section is empty.
Functions ¶
func EnableLogging ¶
func EnableLogging()
Enables logging to log package. For more flexibility, see SetLogger().
func GenerateKeyPair ¶
func GenerateKeyPair(alg, privKeyPath string) (*PrivateKey, *PublicKey, Error)
Generate a new keypair for the given XMSS[MT] instance alg.
Stores the private key at privKeyPath. This will create two files: <privKeyPath> and <privKeyPath>.cache. The first contains the private key and the second contains sensitive cached information derived from the private key used to increase signing performance a lot.
Use ListNames() to list the supported instances of XMSS[MT] from the RFC. This library supports more instances than those listed in the RFC. To check whether an instance is supported by the RFC, use Context.FromRFC().
For more flexibility use NewContextFromName[2]() to create a Context and then call Context.GenerateKeyPair() or Context.DeriveInto().
NOTE Do not forget to Close() the PrivateKey.
func ListNames2 ¶ added in v1.2.0
func ListNames2() (names []string)
List names of supported and useful XMSS[MT] instances (that might not be named in RFC8391 and thus might not be supported by other implementations.)
func LoadPrivateKey ¶
func LoadPrivateKey(path string) ( sk *PrivateKey, pk *PublicKey, lostSigs uint32, err Error)
Loads the private key from the given filesystem container.
If the container wasn't properly closed, there might have been signatures lost. The amount of returned in lostSigs.
NOTE Takes ownership of ctr. Do not forget to Close() the PrivateKey.
func LoadPrivateKeyFrom ¶
func LoadPrivateKeyFrom(ctr PrivateKeyContainer) ( sk *PrivateKey, pk *PublicKey, lostSigs uint32, err Error)
Loads the private key from the given private key container.
If the container wasn't properly closed, there might have been signatures lost. The amount of returned in lostSigs.
NOTE Takes ownership of ctr. Do not forget to Close() the PrivateKey.
func NewContextFromName2 ¶ added in v1.2.0
Return new context for the given XMSS[MT] instance, which might not be listed in the RFC.
func OpenFSPrivateKeyContainer ¶
func OpenFSPrivateKeyContainer(path string) (PrivateKeyContainer, Error)
Returns a PrivateKeyContainer backed by the filesystem.
func ParamsFromName2 ¶ added in v1.2.0
Returns parameters for a XMSS[MT] instance (which might not be listed in the RFC.)
Types ¶
type Context ¶
type Context struct { // Number of worker goroutines ("threads") to use for expensive operations. // Will guess an appropriate number if set to 0. Threads int // contains filtered or unexported fields }
XMSS[MT] instance. Create one using NewContextFromName[2], NewContextFromOid or NewContext.
func NewContextFromName ¶
Return new context for the given named XMSS[MT] instance (and nil if the algorithm name is unknown).
func NewContextFromOid ¶
Return new context for the given XMSS[MT] oid (and nil if it's unknown).
func (*Context) Derive ¶
func (ctx *Context) Derive(path string, pubSeed, skSeed, skPrf []byte) ( *PrivateKey, *PublicKey, Error)
Derives an XMSS[MT] public/private keypair from the given seeds and stores it at the given path on the filesystem. NOTE Do not forget to Close() the returned PrivateKey
func (*Context) DeriveInto ¶
func (ctx *Context) DeriveInto(ctr PrivateKeyContainer, pubSeed, skSeed, skPrf []byte) (*PrivateKey, *PublicKey, Error)
Derives an XMSS[MT] public/private keypair from the given seeds and stores it in the container. pubSeed, skSeed and skPrf should be secret random ctx.p.N length byte slices.
func (*Context) FromNIST ¶ added in v1.4.0
Returns whether this XMSS[MT] instance is listed in the NIST Special Publication.
func (*Context) FromRFC ¶ added in v1.2.0
Returns whether this XMSS[MT] instance is listed in the RFC (and thus should also be supported by other implementations).
func (*Context) GenerateKeyPair ¶
func (ctx *Context) GenerateKeyPair(path string) ( *PrivateKey, *PublicKey, Error)
Generates an XMSS[MT] public/private keypair and stores it at the given path on the filesystem.
NOTE Do not forget to Close() the returned PrivateKey
func (*Context) Name ¶
Returns the name of the XMSSMT instance and an empty string if it has no name.
func (*Context) SignatureSize ¶
Returns the size of signatures of this XMSS[MT] instance
type Error ¶
type Error interface { error Locked() bool // Is this error because something (like a file) was locked? Inner() error // Returns the wrapped error, if any }
type HashFunc ¶
type HashFunc uint8
Hash function to use.
func HashFuncString ¶ added in v1.0.1
HashFuncString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.
func HashFuncValues ¶ added in v1.0.1
func HashFuncValues() []HashFunc
HashFuncValues returns all values of the enum
func (HashFunc) IsAHashFunc ¶ added in v1.0.1
IsAHashFunc returns "true" if the value is listed in the enum definition. "false" otherwise
type Params ¶
type Params struct { Func HashFunc // which has function to use N uint32 // security parameter: influences length of hashes FullHeight uint32 // full height of tree D uint32 // number of subtrees; 1 for XMSS, >1 for XMSSMT // WOTS+ Winternitz parameter. Only 4, 16 and 256 are supported. WotsW uint16 // Method to use for construction of the PRFs. Prf PrfConstruction }
Parameters of an XMSS[MT] instance
func ParamsFromName ¶
Returns parameters for a named XMSS[MT] instance (and nil if there is no such algorithm listed in the RFC.)
func (*Params) BareSubTreeSize ¶
Returns the size of the subtrees for this parameter.
func (*Params) CachedSubTreeSize ¶
Returns the size of the cached subtrees for this parameter.
func (*Params) LookupNameAndOid ¶
Returns the name and OID of this set of parameters, it is has them.
func (*Params) MarshalBinary ¶
Encodes parameters in the reserved Oid space as follows (big endian).
8-bit magic should be 0xEA 3-bit version should be 0 1-bit prf 0 for RFC and 1 for NIST 4-bit compr-n contains (n/8)-1 for the parameter n 2-bit hash the hash function 2-bit w 0 for WotsW=4, 1 for WotsW=16, 2 for WotsW=256 6-bit full-height the full height parameter 6-bit d the parameter d We assume XMSS if d == 1 and XMSSMT otherwise.
func (*Params) MaxSignatureSeqNo ¶
Returns the maximum signature sequence number
func (*Params) PrivateKeySize ¶
Size of the private key as stored by PrivateKeyContainer. NOTE this is not equal to the privateKeySize of the spec, which includes
the signature sequence number, OID and root
func (*Params) UnmarshalBinary ¶
Decodes parameters as encoded by MarshalBinary().
func (*Params) WotsSignatureSize ¶
Returns the size of a WOTS+ signature
type PrfConstruction ¶ added in v1.4.0
type PrfConstruction uint8
Way to construct the various PRFs from the hash function.
const ( // As described by RFC8391. RFC PrfConstruction = iota // As described by NIST SP 800-208. NIST )
type PrivateKey ¶
type PrivateKey struct {
// contains filtered or unexported fields
}
XMSS[MT] private key
func (*PrivateKey) BorrowExactly ¶
func (sk *PrivateKey) BorrowExactly(amount uint32) Error
Ensures there are exactly the given number of signature sequence numbers are reserved for use by Sign().
In a typical setup, each call to Sign() will write and fsync() the current signature sequence number to disk, such that signature sequence numbers aren't reused in a crash. This does slow down Sign() quite a bit. To speed things up, we can reserve signatures; write the fact that we did this to disk and correct the signature sequence number on Close(). The drawback is that with a crash or a missing Close(), we will loose the signatures that were reserved.
func (*PrivateKey) BorrowExactlyIfBelow ¶
func (sk *PrivateKey) BorrowExactlyIfBelow(amount, treshHold uint32) Error
Atomically runs BorrowExactly(amount) if BorrowedSeqNos() <= treshHold.
func (*PrivateKey) BorrowedSeqNos ¶
func (sk *PrivateKey) BorrowedSeqNos() uint32
Returns the number of signature sequence numbers borrowed from the container. See BorrowExactly() or PrivateKeyContainer.BorrowSeqNos()
func (*PrivateKey) CachedSubTrees ¶
func (sk *PrivateKey) CachedSubTrees() int
Returns the number of subtrees that are cached
func (*PrivateKey) Context ¶
func (sk *PrivateKey) Context() *Context
func (*PrivateKey) DangerousSetSeqNo ¶
func (sk *PrivateKey) DangerousSetSeqNo(seqNo SignatureSeqNo)
You probably should not use this function
Sets the signature sequence number. Be very careful not to use the same signature sequence number twice.
func (*PrivateKey) EnableSubTreePrecomputation ¶
func (sk *PrivateKey) EnableSubTreePrecomputation()
Enable subtree precomputation.
By default, a subtree is computed when it's needed. So with subtrees of height 10, every 1024th Sign() will be slow because a new subtree is generated.
When subtree precomputation is enabled, the next subtree is already computed in a separate thread when the previous subtree is consumed. This is useful when running a server which cannot tolerate a sudden spike in the duration of the Sign() function.
func (*PrivateKey) PublicKey ¶
func (sk *PrivateKey) PublicKey() *PublicKey
Returns the PublicKey for this PrivateKey.
func (*PrivateKey) SeqNo ¶
func (sk *PrivateKey) SeqNo() SignatureSeqNo
Returns the signature sequence used next.
func (*PrivateKey) Sign ¶
func (sk *PrivateKey) Sign(msg []byte) (*Signature, Error)
Signs the given message.
func (*PrivateKey) SignFrom ¶
func (sk *PrivateKey) SignFrom(msg io.Reader) (*Signature, Error)
Reads a message from the io.Reader and signs it.
func (*PrivateKey) UnretiredSeqNos ¶
func (sk *PrivateKey) UnretiredSeqNos() uint32
Returns the number of unretired signature sequence numbers.
The PrivateKey keeps track of which signature sequence numbers might still be in use by a Sign() operation. If a Sign() operation finishes it "retires" the signature seqno it used so that private key container can drop caches that are no longer relevant.
type PrivateKeyContainer ¶
type PrivateKeyContainer interface { // Reset (or initialize) the cache that stores the subtrees. It is always // called before use. ResetCache() Error // Returns the buffer for the given subtree. If the subtree does not // have a buffer yet, allocate it of the size params.CachedSubTreeSize() // with params as specified in the last call to Reset(). // The exists return value indicates whether the subtree was present. // The container should write changes to buf back to the storage. // The containe does not have to ensure integrity, a checksum is added // to the end of the buffer. GetSubTree(address SubTreeAddress) (buf []byte, exists bool, err Error) // Returns whether the given subtree is in the cache. Returns false // if the cache is not initialized. HasSubTree(address SubTreeAddress) bool // Drops the given subtree from the cache (if it was even cached to begin // with). DropSubTree(address SubTreeAddress) Error // Returns the list of cached subtrees ListSubTrees() ([]SubTreeAddress, Error) // Reset (or initialize) the container with the given private key // and parameters. Calls ResetCache(). Reset(privateKey []byte, params Params) Error // Returns the current signature sequence number and increment // the stored sequence number by the given amount. // The user can use the signatures in this range freely, // but should call SetSeqNo() later to record the actual number // of signatures used. BorrowSeqNos(amount uint32) (SignatureSeqNo, Error) // Sets the signature sequence number to the given value. // Removes the possible-lost-signatures record set by BorrowSeqNos. SetSeqNo(seqNo SignatureSeqNo) Error // Returns the current signature sequence number. // If BorrowSeqNos() has been called without corresponding SetSeqNo() // there might have been signatures lost. In that case, calls to // GetSeqNo will return the number of possibly lost signatures // until SetSeqNo() has been called. GetSeqNo() (seqNo SignatureSeqNo, lostSigs uint32, err Error) // Returns the private key. GetPrivateKey() ([]byte, Error) // Returns the algorithm parameters if the container is initialized // (eg. the file exist) and nil if not. Initialized() *Params // Returns whether the cache is initialized. If not, it can be // initialized by calling ResetCache(). CacheInitialized() bool // Closes the container. Close() Error }
A PrivateKeyContainer has two tasks
- It has to store the XMSS[MT] secret key and sequence number of the first unused signature.
- It has to cache the precomputed subtrees to increase signing performance.
NOTE A PrivateKeyContainer does not have to be thread safe.
type PublicKey ¶
type PublicKey struct {
// contains filtered or unexported fields
}
XMSS[MT] public key
func (*PublicKey) MarshalBinary ¶
Returns representation of the public key with parameters compressed into the reserved space of the Oid prefix. See Params.MarshalBinary().
func (*PublicKey) MarshalText ¶
Returns base64 encoded version of the public key
func (*PublicKey) UnmarshalBinary ¶
Initializes the PublicKey as was stored by MarshalBinary.
func (*PublicKey) UnmarshalText ¶
Initializes the Signature as stored by MarshalText.
func (*PublicKey) Verify ¶
Check whether the sig is a valid signature of this public key for the given message.
func (*PublicKey) VerifyFrom ¶
Reads a message from the io.Reader and verifies whether the provided signature is valid for this public key and message.
type Signature ¶
type Signature struct {
// contains filtered or unexported fields
}
Represents a XMSS[MT] signature
func (*Signature) MarshalBinary ¶
Returns representation of signature with parameters compressed into the reserved space of the Oid prefix. See Params.MarshalBinary().
func (*Signature) SeqNo ¶ added in v1.0.1
func (sig *Signature) SeqNo() SignatureSeqNo
Returns the sequence number of this signature.
func (*Signature) UnmarshalBinary ¶
Initializes the Signature as stored by MarshalBinary.
type SignatureSeqNo ¶
type SignatureSeqNo uint64
Sequence number of signatures. (Corresponds with leaf indices in the implementation.)
type SubTreeAddress ¶
type SubTreeAddress struct { // The height of the subtree. The leaf-subtrees have layer=0 Layer uint32 // The offset in the subtree. The leftmost subtrees have tree=0 Tree uint64 }
Represents the position of a subtree in the full XMSSMT tree.