crypto.mx raw

   1  // Copyright 2011 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  // Package crypto collects common cryptographic constants.
   6  package crypto
   7  
   8  import (
   9  	"hash"
  10  	"io"
  11  	"strconv"
  12  )
  13  
  14  // Hash identifies a cryptographic hash function that is implemented in another
  15  // package.
  16  type Hash uint
  17  
  18  // HashFunc simply returns the value of h so that [Hash] implements [SignerOpts].
  19  func (h Hash) HashFunc() Hash {
  20  	return h
  21  }
  22  
  23  func (h Hash) String() string {
  24  	switch h {
  25  	case MD4:
  26  		return "MD4"
  27  	case MD5:
  28  		return "MD5"
  29  	case SHA1:
  30  		return "SHA-1"
  31  	case SHA224:
  32  		return "SHA-224"
  33  	case SHA256:
  34  		return "SHA-256"
  35  	case SHA384:
  36  		return "SHA-384"
  37  	case SHA512:
  38  		return "SHA-512"
  39  	case MD5SHA1:
  40  		return "MD5+SHA1"
  41  	case RIPEMD160:
  42  		return "RIPEMD-160"
  43  	case SHA3_224:
  44  		return "SHA3-224"
  45  	case SHA3_256:
  46  		return "SHA3-256"
  47  	case SHA3_384:
  48  		return "SHA3-384"
  49  	case SHA3_512:
  50  		return "SHA3-512"
  51  	case SHA512_224:
  52  		return "SHA-512/224"
  53  	case SHA512_256:
  54  		return "SHA-512/256"
  55  	case BLAKE2s_256:
  56  		return "BLAKE2s-256"
  57  	case BLAKE2b_256:
  58  		return "BLAKE2b-256"
  59  	case BLAKE2b_384:
  60  		return "BLAKE2b-384"
  61  	case BLAKE2b_512:
  62  		return "BLAKE2b-512"
  63  	default:
  64  		return "unknown hash value " + string(strconv.Itoa(int(h)))
  65  	}
  66  }
  67  
  68  const (
  69  	MD4         Hash = 1 + iota // import golang.org/x/crypto/md4
  70  	MD5                         // import crypto/md5
  71  	SHA1                        // import crypto/sha1
  72  	SHA224                      // import crypto/sha256
  73  	SHA256                      // import crypto/sha256
  74  	SHA384                      // import crypto/sha512
  75  	SHA512                      // import crypto/sha512
  76  	MD5SHA1                     // no implementation; MD5+SHA1 used for TLS RSA
  77  	RIPEMD160                   // import golang.org/x/crypto/ripemd160
  78  	SHA3_224                    // import golang.org/x/crypto/sha3
  79  	SHA3_256                    // import golang.org/x/crypto/sha3
  80  	SHA3_384                    // import golang.org/x/crypto/sha3
  81  	SHA3_512                    // import golang.org/x/crypto/sha3
  82  	SHA512_224                  // import crypto/sha512
  83  	SHA512_256                  // import crypto/sha512
  84  	BLAKE2s_256                 // import golang.org/x/crypto/blake2s
  85  	BLAKE2b_256                 // import golang.org/x/crypto/blake2b
  86  	BLAKE2b_384                 // import golang.org/x/crypto/blake2b
  87  	BLAKE2b_512                 // import golang.org/x/crypto/blake2b
  88  	maxHash
  89  )
  90  
  91  var digestSizes = []uint8{
  92  	MD4:         16,
  93  	MD5:         16,
  94  	SHA1:        20,
  95  	SHA224:      28,
  96  	SHA256:      32,
  97  	SHA384:      48,
  98  	SHA512:      64,
  99  	SHA512_224:  28,
 100  	SHA512_256:  32,
 101  	SHA3_224:    28,
 102  	SHA3_256:    32,
 103  	SHA3_384:    48,
 104  	SHA3_512:    64,
 105  	MD5SHA1:     36,
 106  	RIPEMD160:   20,
 107  	BLAKE2s_256: 32,
 108  	BLAKE2b_256: 32,
 109  	BLAKE2b_384: 48,
 110  	BLAKE2b_512: 64,
 111  }
 112  
 113  // Size returns the length, in bytes, of a digest resulting from the given hash
 114  // function. It doesn't require that the hash function in question be linked
 115  // into the program.
 116  func (h Hash) Size() int {
 117  	if h > 0 && h < maxHash {
 118  		return int(digestSizes[h])
 119  	}
 120  	panic("crypto: Size of unknown hash function")
 121  }
 122  
 123  var hashes = []func() hash.Hash{:maxHash}
 124  
 125  // New returns a new hash.Hash calculating the given hash function. New panics
 126  // if the hash function is not linked into the binary.
 127  func (h Hash) New() hash.Hash {
 128  	if h > 0 && h < maxHash {
 129  		f := hashes[h]
 130  		if f != nil {
 131  			return f()
 132  		}
 133  	}
 134  	var msg []byte
 135  	msg = append(msg, "crypto: requested hash function #"...)
 136  	msg = append(msg, strconv.Itoa(int(h))...)
 137  	msg = append(msg, " is unavailable"...)
 138  	panic(msg)
 139  }
 140  
 141  // Available reports whether the given hash function is linked into the binary.
 142  func (h Hash) Available() bool {
 143  	return h < maxHash && hashes[h] != nil
 144  }
 145  
 146  // RegisterHash registers a function that returns a new instance of the given
 147  // hash function. This is intended to be called from the init function in
 148  // packages that implement hash functions.
 149  func RegisterHash(h Hash, f func() hash.Hash) {
 150  	if h >= maxHash {
 151  		panic("crypto: RegisterHash of unknown hash function")
 152  	}
 153  	hashes[h] = f
 154  }
 155  
 156  // PublicKey represents a public key using an unspecified algorithm.
 157  //
 158  // Although this type is an empty interface for backwards compatibility reasons,
 159  // all public key types in the standard library implement the following interface
 160  //
 161  //	interface{
 162  //	    Equal(x crypto.PublicKey) bool
 163  //	}
 164  //
 165  // which can be used for increased type safety within applications.
 166  type PublicKey any
 167  
 168  // PrivateKey represents a private key using an unspecified algorithm.
 169  //
 170  // Although this type is an empty interface for backwards compatibility reasons,
 171  // all private key types in the standard library implement the following interface
 172  //
 173  //	interface{
 174  //	    Public() crypto.PublicKey
 175  //	    Equal(x crypto.PrivateKey) bool
 176  //	}
 177  //
 178  // as well as purpose-specific interfaces such as [Signer] and [Decrypter], which
 179  // can be used for increased type safety within applications.
 180  type PrivateKey any
 181  
 182  // Signer is an interface for an opaque private key that can be used for
 183  // signing operations. For example, an RSA key kept in a hardware module.
 184  type Signer interface {
 185  	// Public returns the public key corresponding to the opaque,
 186  	// private key.
 187  	Public() PublicKey
 188  
 189  	// Sign signs digest with the private key, possibly using entropy from
 190  	// rand. For an RSA key, the resulting signature should be either a
 191  	// PKCS #1 v1.5 or PSS signature (as indicated by opts). For an (EC)DSA
 192  	// key, it should be a DER-serialised, ASN.1 signature structure.
 193  	//
 194  	// Hash implements the SignerOpts interface and, in most cases, one can
 195  	// simply pass in the hash function used as opts. Sign may also attempt
 196  	// to type assert opts to other types in order to obtain algorithm
 197  	// specific values. See the documentation in each package for details.
 198  	//
 199  	// Note that when a signature of a hash of a larger message is needed,
 200  	// the caller is responsible for hashing the larger message and passing
 201  	// the hash (as digest) and the hash function (as opts) to Sign.
 202  	Sign(rand io.Reader, digest []byte, opts SignerOpts) (signature []byte, err error)
 203  }
 204  
 205  // MessageSigner is an interface for an opaque private key that can be used for
 206  // signing operations where the message is not pre-hashed by the caller.
 207  // It is a superset of the Signer interface so that it can be passed to APIs
 208  // which accept Signer, which may try to do an interface upgrade.
 209  //
 210  // MessageSigner.SignMessage and MessageSigner.Sign should produce the same
 211  // result given the same opts. In particular, MessageSigner.SignMessage should
 212  // only accept a zero opts.HashFunc if the Signer would also accept messages
 213  // which are not pre-hashed.
 214  //
 215  // Implementations which do not provide the pre-hashed Sign API should implement
 216  // Signer.Sign by always returning an error.
 217  type MessageSigner interface {
 218  	Signer
 219  	SignMessage(rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error)
 220  }
 221  
 222  // SignerOpts contains options for signing with a [Signer].
 223  type SignerOpts interface {
 224  	// HashFunc returns an identifier for the hash function used to produce
 225  	// the message passed to Signer.Sign, or else zero to indicate that no
 226  	// hashing was done.
 227  	HashFunc() Hash
 228  }
 229  
 230  // Decrypter is an interface for an opaque private key that can be used for
 231  // asymmetric decryption operations. An example would be an RSA key
 232  // kept in a hardware module.
 233  type Decrypter interface {
 234  	// Public returns the public key corresponding to the opaque,
 235  	// private key.
 236  	Public() PublicKey
 237  
 238  	// Decrypt decrypts msg. The opts argument should be appropriate for
 239  	// the primitive used. See the documentation in each implementation for
 240  	// details.
 241  	Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error)
 242  }
 243  
 244  type DecrypterOpts any
 245  
 246  // Decapsulator is an interface for a KEM private key.
 247  type Decapsulator interface {
 248  	Encapsulator() Encapsulator
 249  	Decapsulate(ciphertext []byte) (sharedKey []byte, err error)
 250  }
 251  
 252  // Encapsulator is an interface for a KEM public key.
 253  type Encapsulator interface {
 254  	Bytes() []byte
 255  	Encapsulate() (sharedKey, ciphertext []byte)
 256  }
 257  
 258  // SignMessage signs msg with signer. If signer implements [MessageSigner],
 259  // [MessageSigner.SignMessage] is called directly. Otherwise, msg is hashed
 260  // with opts.HashFunc() and signed with [Signer.Sign].
 261  func SignMessage(signer Signer, rand io.Reader, msg []byte, opts SignerOpts) (signature []byte, err error) {
 262  	if ms, ok := signer.(MessageSigner); ok {
 263  		return ms.SignMessage(rand, msg, opts)
 264  	}
 265  	if opts.HashFunc() != 0 {
 266  		h := opts.HashFunc().New()
 267  		h.Write(msg)
 268  		msg = h.Sum(nil)
 269  	}
 270  	return signer.Sign(rand, msg, opts)
 271  }
 272