// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.
// Package rsa implements RSA encryption as specified in PKCS #1 and RFC 8017.//// RSA is a single, fundamental operation that is used in this package to// implement either public-key encryption or public-key signatures.//// The original specification for encryption and signatures with RSA is PKCS #1// and the terms "RSA encryption" and "RSA signatures" by default refer to// PKCS #1 version 1.5. However, that specification has flaws and new designs// should use version 2, usually called by just OAEP and PSS, where// possible.//// Two sets of interfaces are included in this package. When a more abstract// interface isn't necessary, there are functions for encrypting/decrypting// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract// over the public key primitive, the PrivateKey type implements the// Decrypter and Signer interfaces from the crypto package.//// Operations involving private keys are implemented using constant-time// algorithms, except for [GenerateKey] and for some operations involving// deprecated multi-prime keys.//// # Minimum key size//// [GenerateKey] returns an error if a key of less than 1024 bits is requested,// and all Sign, Verify, Encrypt, and Decrypt methods return an error if used// with a key smaller than 1024 bits. Such keys are insecure and should not be// used.//// The `rsa1024min=0` GODEBUG setting suppresses this error, but we recommend// doing so only in tests, if necessary. Tests can use [testing.T.Setenv] or// include `//go:debug rsa1024min=0` in a `_test.go` source file to set it.//// Alternatively, see the [GenerateKey (TestKey)] example for a pregenerated// test-only 2048-bit key.//// [GenerateKey (TestKey)]: #example-GenerateKey-TestKey
package rsaimport ()var bigOne = big.NewInt(1)// A PublicKey represents the public part of an RSA key.//// The value of the modulus N is considered secret by this library and protected// from leaking through timing side-channels. However, neither the value of the// exponent E nor the precise bit size of N are similarly protected.typePublicKeystruct { N *big.Int// modulus E int// public exponent}// Any methods implemented on PublicKey might need to also be implemented on// PrivateKey, as the latter embeds the former and will expose its methods.// Size returns the modulus size in bytes. Raw signatures and ciphertexts// for or by this public key will have the same size.func ( *PublicKey) () int {return (.N.BitLen() + 7) / 8}// Equal reports whether pub and x have the same value.func ( *PublicKey) ( crypto.PublicKey) bool { , := .(*PublicKey)if ! {returnfalse }returnbigIntEqual(.N, .N) && .E == .E}// OAEPOptions is an interface for passing options to OAEP decryption using the// crypto.Decrypter interface.typeOAEPOptionsstruct {// Hash is the hash function that will be used when generating the mask. Hash crypto.Hash// MGFHash is the hash function used for MGF1. // If zero, Hash is used instead. MGFHash crypto.Hash// Label is an arbitrary byte string that must be equal to the value // used when encrypting. Label []byte}// A PrivateKey represents an RSA keytypePrivateKeystruct {PublicKey// public part. D *big.Int// private exponent Primes []*big.Int// prime factors of N, has >= 2 elements.// Precomputed contains precomputed values that speed up RSA operations, // if available. It must be generated by calling PrivateKey.Precompute and // must not be modified. Precomputed PrecomputedValues}// Public returns the public key corresponding to priv.func ( *PrivateKey) () crypto.PublicKey {return &.PublicKey}// Equal reports whether priv and x have equivalent values. It ignores// Precomputed values.func ( *PrivateKey) ( crypto.PrivateKey) bool { , := .(*PrivateKey)if ! {returnfalse }if !.PublicKey.Equal(&.PublicKey) || !bigIntEqual(.D, .D) {returnfalse }iflen(.Primes) != len(.Primes) {returnfalse }for := range .Primes {if !bigIntEqual(.Primes[], .Primes[]) {returnfalse } }returntrue}// bigIntEqual reports whether a and b are equal leaking only their bit length// through timing side-channels.func bigIntEqual(, *big.Int) bool {returnsubtle.ConstantTimeCompare(.Bytes(), .Bytes()) == 1}// Sign signs digest with priv, reading randomness from rand. If opts is a// *[PSSOptions] then the PSS algorithm will be used, otherwise PKCS #1 v1.5 will// be used. digest must be the result of hashing the input message using// opts.HashFunc().//// This method implements [crypto.Signer], which is an interface to support keys// where the private part is kept in, for example, a hardware module. Common// uses should use the Sign* functions in this package directly.func ( *PrivateKey) ( io.Reader, []byte, crypto.SignerOpts) ([]byte, error) {if , := .(*PSSOptions); {returnSignPSS(, , .Hash, , ) }returnSignPKCS1v15(, , .HashFunc(), )}// Decrypt decrypts ciphertext with priv. If opts is nil or of type// *[PKCS1v15DecryptOptions] then PKCS #1 v1.5 decryption is performed. Otherwise// opts must have type *[OAEPOptions] and OAEP decryption is done.func ( *PrivateKey) ( io.Reader, []byte, crypto.DecrypterOpts) ( []byte, error) {if == nil {returnDecryptPKCS1v15(, , ) }switch opts := .(type) {case *OAEPOptions:if .MGFHash == 0 {returndecryptOAEP(.Hash.New(), .Hash.New(), , , .Label) } else {returndecryptOAEP(.Hash.New(), .MGFHash.New(), , , .Label) }case *PKCS1v15DecryptOptions:if := .SessionKeyLen; > 0 { = make([]byte, )if , := io.ReadFull(, ); != nil {returnnil, }if := DecryptPKCS1v15SessionKey(, , , ); != nil {returnnil, }return , nil } else {returnDecryptPKCS1v15(, , ) }default:returnnil, errors.New("crypto/rsa: invalid options for Decrypt") }}typePrecomputedValuesstruct { Dp, Dq *big.Int// D mod (P-1) (or mod Q-1) Qinv *big.Int// Q^-1 mod P// CRTValues is used for the 3rd and subsequent primes. Due to a // historical accident, the CRT for the first two primes is handled // differently in PKCS #1 and interoperability is sufficiently // important that we mirror this. // // Deprecated: These values are still filled in by Precompute for // backwards compatibility but are not used. Multi-prime RSA is very rare, // and is implemented by this package without CRT optimizations to limit // complexity. CRTValues []CRTValue fips *rsa.PrivateKey}// CRTValue contains the precomputed Chinese remainder theorem values.typeCRTValuestruct { Exp *big.Int// D mod (prime-1). Coeff *big.Int// R·Coeff ≡ 1 mod Prime. R *big.Int// product of primes prior to this (inc p and q).}// Validate performs basic sanity checks on the key.// It returns nil if the key is valid, or else an error describing a problem.//// It runs faster on valid keys if run after [Precompute].func ( *PrivateKey) () error {// We can operate on keys based on d alone, but it isn't possible to encode // with [crypto/x509.MarshalPKCS1PrivateKey], which unfortunately doesn't // return an error.iflen(.Primes) < 2 {returnerrors.New("crypto/rsa: missing primes") }// If Precomputed.fips is set, then the key has been validated by // [rsa.NewPrivateKey] or [rsa.NewPrivateKeyWithoutCRT].if .Precomputed.fips != nil {returnnil } , := .precompute()return}// rsa1024min is a GODEBUG that re-enables weak RSA keys if set to "0".// See https://go.dev/issue/68762.var rsa1024min = godebug.New("rsa1024min")func checkKeySize( int) error {if >= 1024 {returnnil }ifrsa1024min.Value() == "0" {rsa1024min.IncNonDefault()returnnil }returnfmt.Errorf("crypto/rsa: %d-bit keys are insecure (see https://go.dev/pkg/crypto/rsa#hdr-Minimum_key_size)", )}func checkPublicKeySize( *PublicKey) error {if .N == nil {returnerrors.New("crypto/rsa: missing public modulus") }returncheckKeySize(.N.BitLen())}// GenerateKey generates a random RSA private key of the given bit size.//// If bits is less than 1024, [GenerateKey] returns an error. See the "[Minimum// key size]" section for further details.//// Most applications should use [crypto/rand.Reader] as rand. Note that the// returned key does not depend deterministically on the bytes read from rand,// and may change between calls and/or between versions.//// [Minimum key size]: #hdr-Minimum_key_sizefunc ( io.Reader, int) (*PrivateKey, error) {if := checkKeySize(); != nil {returnnil, }ifboring.Enabled && == boring.RandReader && ( == 2048 || == 3072 || == 4096) { , , , , , , , , := boring.GenerateKeyRSA()if != nil {returnnil, } := bbig.Dec() := bbig.Dec() := bbig.Dec() := bbig.Dec() := bbig.Dec() := bbig.Dec() := bbig.Dec() := bbig.Dec() := .Int64()if !.IsInt64() || int64(int()) != {returnnil, errors.New("crypto/rsa: generated key exponent too large") } := &PrivateKey{PublicKey: PublicKey{N: ,E: int(), },D: ,Primes: []*big.Int{, },Precomputed: PrecomputedValues{Dp: ,Dq: ,Qinv: ,CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute }, }return , nil }iffips140only.Enabled && < 2048 {returnnil, errors.New("crypto/rsa: use of keys smaller than 2048 bits is not allowed in FIPS 140-only mode") }iffips140only.Enabled && %2 == 1 {returnnil, errors.New("crypto/rsa: use of keys with odd size is not allowed in FIPS 140-only mode") }iffips140only.Enabled && !fips140only.ApprovedRandomReader() {returnnil, errors.New("crypto/rsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") } , := rsa.GenerateKey(, )if != nil {returnnil, } , , , , , , , := .Export() := &PrivateKey{PublicKey: PublicKey{N: new(big.Int).SetBytes(),E: , },D: new(big.Int).SetBytes(),Primes: []*big.Int{new(big.Int).SetBytes(),new(big.Int).SetBytes(), },Precomputed: PrecomputedValues{fips: ,Dp: new(big.Int).SetBytes(),Dq: new(big.Int).SetBytes(),Qinv: new(big.Int).SetBytes(),CRTValues: make([]CRTValue, 0), // non-nil, to match Precompute }, }return , nil}// GenerateMultiPrimeKey generates a multi-prime RSA keypair of the given bit// size and the given random source.//// Table 1 in "[On the Security of Multi-prime RSA]" suggests maximum numbers of// primes for a given bit size.//// Although the public keys are compatible (actually, indistinguishable) from// the 2-prime case, the private keys are not. Thus it may not be possible to// export multi-prime private keys in certain formats or to subsequently import// them into other code.//// This package does not implement CRT optimizations for multi-prime RSA, so the// keys with more than two primes will have worse performance.//// Deprecated: The use of this function with a number of primes different from// two is not recommended for the above security, compatibility, and performance// reasons. Use [GenerateKey] instead.//// [On the Security of Multi-prime RSA]: http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdffunc ( io.Reader, int, int) (*PrivateKey, error) {if == 2 {returnGenerateKey(, ) }iffips140only.Enabled {returnnil, errors.New("crypto/rsa: multi-prime RSA is not allowed in FIPS 140-only mode") }randutil.MaybeReadByte() := new(PrivateKey) .E = 65537if < 2 {returnnil, errors.New("crypto/rsa: GenerateMultiPrimeKey: nprimes must be >= 2") }if < 64 { := float64(uint64(1) << uint(/))// pi approximates the number of primes less than primeLimit := / (math.Log() - 1)// Generated primes start with 11 (in binary) so we can only // use a quarter of them. /= 4// Use a factor of two to ensure that key generation terminates // in a reasonable amount of time. /= 2if <= float64() {returnnil, errors.New("crypto/rsa: too few primes of given length to generate an RSA key") } } := make([]*big.Int, ):for { := // crypto/rand should set the top two bits in each prime. // Thus each prime has the form // p_i = 2^bitlen(p_i) × 0.11... (in base 2). // And the product is: // P = 2^todo × α // where α is the product of nprimes numbers of the form 0.11... // // If α < 1/2 (which can happen for nprimes > 2), we need to // shift todo to compensate for lost bits: the mean value of 0.11... // is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2 // will give good results.if >= 7 { += ( - 2) / 5 }for := 0; < ; ++ {varerror [], = rand.Prime(, /(-))if != nil {returnnil, } -= [].BitLen() }// Make sure that primes is pairwise unequal.for , := range {for := 0; < ; ++ {if .Cmp([]) == 0 {continue } } } := new(big.Int).Set(bigOne) := new(big.Int).Set(bigOne) := new(big.Int)for , := range { .Mul(, ) .Sub(, bigOne) .Mul(, ) }if .BitLen() != {// This should never happen for nprimes == 2 because // crypto/rand should set the top two bits in each prime. // For nprimes > 2 we hope it does not happen often.continue } .D = new(big.Int) := big.NewInt(int64(.E)) := .D.ModInverse(, )if != nil { .Primes = .N = break } } .Precompute()if := .Validate(); != nil {returnnil, }return , nil}// ErrMessageTooLong is returned when attempting to encrypt or sign a message// which is too large for the size of the key. When using [SignPSS], this can also// be returned if the size of the salt is too large.varErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA key size")// ErrDecryption represents a failure to decrypt a message.// It is deliberately vague to avoid adaptive attacks.varErrDecryption = errors.New("crypto/rsa: decryption error")// ErrVerification represents a failure to verify a signature.// It is deliberately vague to avoid adaptive attacks.varErrVerification = errors.New("crypto/rsa: verification error")// Precompute performs some calculations that speed up private key operations// in the future. It is safe to run on non-validated private keys.func ( *PrivateKey) () {if .Precomputed.fips != nil {return } , := .precompute()if != nil {// We don't have a way to report errors, so just leave the key // unmodified. Validate will re-run precompute.return } .Precomputed = }func ( *PrivateKey) () (PrecomputedValues, error) {varPrecomputedValuesif .N == nil {return , errors.New("crypto/rsa: missing public modulus") }if .D == nil {return , errors.New("crypto/rsa: missing private exponent") }iflen(.Primes) != 2 {return .precomputeLegacy() }if .Primes[0] == nil {return , errors.New("crypto/rsa: prime P is nil") }if .Primes[1] == nil {return , errors.New("crypto/rsa: prime Q is nil") }// If the CRT values are already set, use them.if .Precomputed.Dp != nil && .Precomputed.Dq != nil && .Precomputed.Qinv != nil { , := rsa.NewPrivateKeyWithPrecomputation(.N.Bytes(), .E, .D.Bytes(), .Primes[0].Bytes(), .Primes[1].Bytes(), .Precomputed.Dp.Bytes(), .Precomputed.Dq.Bytes(), .Precomputed.Qinv.Bytes())if != nil {return , } = .Precomputed .fips = .CRTValues = make([]CRTValue, 0)return , nil } , := rsa.NewPrivateKey(.N.Bytes(), .E, .D.Bytes(), .Primes[0].Bytes(), .Primes[1].Bytes())if != nil {return , } .fips = , , , , , , , := .Export() .Dp = new(big.Int).SetBytes() .Dq = new(big.Int).SetBytes() .Qinv = new(big.Int).SetBytes() .CRTValues = make([]CRTValue, 0)return , nil}func ( *PrivateKey) () (PrecomputedValues, error) {varPrecomputedValues , := rsa.NewPrivateKeyWithoutCRT(.N.Bytes(), .E, .D.Bytes())if != nil {return , } .fips = iflen(.Primes) < 2 {return , nil }// Ensure the Mod and ModInverse calls below don't panic.for , := range .Primes {if == nil {return , errors.New("crypto/rsa: prime factor is nil") }if .Cmp(bigOne) <= 0 {return , errors.New("crypto/rsa: prime factor is <= 1") } } .Dp = new(big.Int).Sub(.Primes[0], bigOne) .Dp.Mod(.D, .Dp) .Dq = new(big.Int).Sub(.Primes[1], bigOne) .Dq.Mod(.D, .Dq) .Qinv = new(big.Int).ModInverse(.Primes[1], .Primes[0])if .Qinv == nil {return , errors.New("crypto/rsa: prime factors are not relatively prime") } := new(big.Int).Mul(.Primes[0], .Primes[1]) .CRTValues = make([]CRTValue, len(.Primes)-2)for := 2; < len(.Primes); ++ { := .Primes[] := &.CRTValues[-2] .Exp = new(big.Int).Sub(, bigOne) .Exp.Mod(.D, .Exp) .R = new(big.Int).Set() .Coeff = new(big.Int).ModInverse(, )if .Coeff == nil {return , errors.New("crypto/rsa: prime factors are not relatively prime") } .Mul(, ) }return , nil}func fipsPublicKey( *PublicKey) (*rsa.PublicKey, error) { , := bigmod.NewModulus(.N.Bytes())if != nil {returnnil, }return &rsa.PublicKey{N: , E: .E}, nil}func fipsPrivateKey( *PrivateKey) (*rsa.PrivateKey, error) {if .Precomputed.fips != nil {return .Precomputed.fips, nil } , := .precompute()if != nil {returnnil, }return .fips, nil}
The pages are generated with Goldsv0.7.3. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.