Involved Source Filesnotboring.gopkcs1v15.gopss.go 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 in this package are implemented using constant-time algorithms,
except for [GenerateKey], [PrivateKey.Precompute], and [PrivateKey.Validate].
Every other operation only leaks the bit size of the involved values, which
all depend on the selected key size.
Code Examples
{
ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460")
label := []byte("orders")
plaintext, err := rsa.DecryptOAEP(sha256.New(), nil, test2048Key, ciphertext, label)
if err != nil {
fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err)
return
}
fmt.Printf("Plaintext: %s\n", string(plaintext))
}
{
key := make([]byte, 32)
if _, err := rand.Read(key); err != nil {
panic("RNG failure")
}
rsaCiphertext, _ := hex.DecodeString("aabbccddeeff")
if err := rsa.DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, rsaCiphertext, key); err != nil {
fmt.Fprintf(os.Stderr, "Error from RSA decryption: %s\n", err)
return
}
block, err := aes.NewCipher(key)
if err != nil {
panic("aes.NewCipher failed: " + err.Error())
}
// Since the key is random, using a fixed nonce is acceptable as the
// (key, nonce) pair will still be unique, as required.
var zeroNonce [12]byte
aead, err := cipher.NewGCM(block)
if err != nil {
panic("cipher.NewGCM failed: " + err.Error())
}
ciphertext, _ := hex.DecodeString("00112233445566")
plaintext, err := aead.Open(nil, zeroNonce[:], ciphertext, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "Error decrypting: %s\n", err)
return
}
fmt.Printf("Plaintext: %s\n", string(plaintext))
}
{
secretMessage := []byte("send reinforcements, we're going to advance")
label := []byte("orders")
rng := rand.Reader
ciphertext, err := rsa.EncryptOAEP(sha256.New(), rng, &test2048Key.PublicKey, secretMessage, label)
if err != nil {
fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err)
return
}
fmt.Printf("Ciphertext: %x\n", ciphertext)
}
{
message := []byte("message to be signed")
hashed := sha256.Sum256(message)
signature, err := rsa.SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA256, hashed[:])
if err != nil {
fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err)
return
}
fmt.Printf("Signature: %x\n", signature)
}
{
message := []byte("message to be signed")
signature, _ := hex.DecodeString("ad2766728615cc7a746cc553916380ca7bfa4f8983b990913bc69eb0556539a350ff0f8fe65ddfd3ebe91fe1c299c2fac135bc8c61e26be44ee259f2f80c1530")
hashed := sha256.Sum256(message)
err := rsa.VerifyPKCS1v15(&rsaPrivateKey.PublicKey, crypto.SHA256, hashed[:], signature)
if err != nil {
fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err)
return
}
}
Package-Level Type Names (total 7, all are exported)
/* sort exporteds by: | */
CRTValue contains the precomputed Chinese remainder theorem values. // R·Coeff ≡ 1 mod Prime. // D mod (prime-1). // product of primes prior to this (inc p and q).
OAEPOptions is an interface for passing options to OAEP decryption using the
crypto.Decrypter interface. Hash is the hash function that will be used when generating the mask. Label is an arbitrary byte string that must be equal to the value
used when encrypting. MGFHash is the hash function used for MGF1.
If zero, Hash is used instead.
PKCS1v15DecryptOptions is for passing options to PKCS #1 v1.5 decryption using
the crypto.Decrypter interface. SessionKeyLen is the length of the session key that is being
decrypted. If not zero, then a padding error during decryption will
cause a random plaintext of this length to be returned rather than
an error. These alternatives happen in constant time.
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. // D mod (P-1) (or mod Q-1) // D mod (P-1) (or mod Q-1) // Q^-1 mod P // moduli for CRT with Montgomery precomputed constants // moduli for CRT with Montgomery precomputed constants // moduli for CRT with Montgomery precomputed constants
A PrivateKey represents an RSA key // private exponent Precomputed contains precomputed values that speed up RSA operations,
if available. It must be generated by calling PrivateKey.Precompute and
must not be modified. // prime factors of N, has >= 2 elements. // public part. // public exponent // modulus 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. Equal reports whether priv and x have equivalent values. It ignores
Precomputed values. Precompute performs some calculations that speed up private key operations
in the future. Public returns the public key corresponding to priv. 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. Size returns the modulus size in bytes. Raw signatures and ciphertexts
for or by this public key will have the same size. Validate performs basic sanity checks on the key.
It returns nil if the key is valid, or else an error describing a problem.
*PrivateKey : crypto.Decrypter
*PrivateKey : crypto.Signer
func GenerateKey(random io.Reader, bits int) (*PrivateKey, error)
func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error)
func crypto/x509.ParsePKCS1PrivateKey(der []byte) (*PrivateKey, error)
func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error)
func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error)
func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error
func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error)
func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error)
func crypto/x509.MarshalPKCS1PrivateKey(key *PrivateKey) []byte
func github.com/gotd/td/internal/crypto.DecodeRSAPad(data []byte, key *PrivateKey) ([]byte, error)
func github.com/gotd/td/internal/crypto.RSADecryptHashed(data []byte, key *PrivateKey) ([]byte, error)
func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyRSA, error)
func decrypt(priv *PrivateKey, ciphertext []byte, check bool) ([]byte, error)
func decryptOAEP(hash, mgfHash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext []byte, label []byte) ([]byte, error)
func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error)
func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error)
func github.com/gotd/td/internal/crypto.rsaDecrypt(data []byte, key *PrivateKey, to []byte) bool
PSSOptions contains options for creating and verifying PSS signatures. Hash is the hash function used to generate the message digest. If not
zero, it overrides the hash function passed to SignPSS. It's required
when using PrivateKey.Sign. SaltLength controls the length of the salt used in the PSS signature. It
can either be a positive number of bytes, or one of the special
PSSSaltLength constants. HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts.(*PSSOptions) saltLength() int
*PSSOptions : crypto.SignerOpts
func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error)
func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error
Package-Level Functions (total 26, in which 11 are exported)
DecryptOAEP decrypts ciphertext using RSA-OAEP.
OAEP is parameterised by a hash function that is used as a random oracle.
Encryption and decryption of a given message must use the same hash function
and sha256.New() is a reasonable choice.
The random parameter is legacy and ignored, and it can be nil.
The label parameter must match the value given when encrypting. See
EncryptOAEP for details.
DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5.
The random parameter is legacy and ignored, and it can be nil.
Note that whether this function returns an error or not discloses secret
information. If an attacker can cause this function to run repeatedly and
learn whether each instance returned an error then they can decrypt and
forge signatures as if they had the private key. See
DecryptPKCS1v15SessionKey for a way of solving this problem.
DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding
scheme from PKCS #1 v1.5. The random parameter is legacy and ignored, and it
can be nil.
DecryptPKCS1v15SessionKey returns an error if the ciphertext is the wrong
length or if the ciphertext is greater than the public modulus. Otherwise, no
error is returned. If the padding is valid, the resulting plaintext message
is copied into key. Otherwise, key is unchanged. These alternatives occur in
constant time. It is intended that the user of this function generate a
random session key beforehand and continue the protocol with the resulting
value.
Note that if the session key is too small then it may be possible for an
attacker to brute-force it. If they can do that then they can learn whether a
random value was used (because it'll be different for the same ciphertext)
and thus whether the padding was correct. This also defeats the point of this
function. Using at least a 16-byte key will protect against this attack.
This method implements protections against Bleichenbacher chosen ciphertext
attacks [0] described in RFC 3218 Section 2.3.2 [1]. While these protections
make a Bleichenbacher attack significantly more difficult, the protections
are only effective if the rest of the protocol which uses
DecryptPKCS1v15SessionKey is designed with these considerations in mind. In
particular, if any subsequent operations which use the decrypted session key
leak any information about the key (e.g. whether it is a static or random
key) then the mitigations are defeated. This method must be used extremely
carefully, and typically should only be used when absolutely necessary for
compatibility with an existing protocol (such as TLS) that is designed with
these properties in mind.
- [0] “Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption
Standard PKCS #1”, Daniel Bleichenbacher, Advances in Cryptology (Crypto '98)
- [1] RFC 3218, Preventing the Million Message Attack on CMS,
https://www.rfc-editor.org/rfc/rfc3218.html
EncryptOAEP encrypts the given message with RSA-OAEP.
OAEP is parameterised by a hash function that is used as a random oracle.
Encryption and decryption of a given message must use the same hash function
and sha256.New() is a reasonable choice.
The random parameter is used as a source of entropy to ensure that
encrypting the same message twice doesn't result in the same ciphertext.
Most applications should use [crypto/rand.Reader] as random.
The label parameter may contain arbitrary data that will not be encrypted,
but which gives important context to the message. For example, if a given
public key is used to encrypt two types of messages then distinct label
values could be used to ensure that a ciphertext for one purpose cannot be
used for another by an attacker. If not required it can be empty.
The message must be no longer than the length of the public modulus minus
twice the hash length, minus a further 2.
EncryptPKCS1v15 encrypts the given message with RSA and the padding
scheme from PKCS #1 v1.5. The message must be no longer than the
length of the public modulus minus 11 bytes.
The random parameter is used as a source of entropy to ensure that
encrypting the same message twice doesn't result in the same
ciphertext. Most applications should use [crypto/rand.Reader]
as random. Note that the returned ciphertext does not depend
deterministically on the bytes read from random, and may change
between calls and/or between versions.
WARNING: use of this function to encrypt plaintexts other than
session keys is dangerous. Use RSA OAEP in new protocols.
GenerateKey generates a random RSA private key of the given bit size.
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.
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.pdf
SignPKCS1v15 calculates the signature of hashed using
RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must
be the result of hashing the input message using the given hash
function. If hash is zero, hashed is signed directly. This isn't
advisable except for interoperability.
The random parameter is legacy and ignored, and it can be nil.
This function is deterministic. Thus, if the set of possible
messages is small, an attacker may be able to build a map from
messages to signatures and identify the signed messages. As ever,
signatures provide authenticity, not confidentiality.
SignPSS calculates the signature of digest using PSS.
digest must be the result of hashing the input message using the given hash
function. The opts argument may be nil, in which case sensible defaults are
used. If opts.Hash is set, it overrides hash.
The signature is randomized depending on the message, key, and salt size,
using bytes from rand. Most applications should use [crypto/rand.Reader] as
rand.
VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature.
hashed is the result of hashing the input message using the given hash
function and sig is the signature. A valid signature is indicated by
returning a nil error. If hash is zero then hashed is used directly. This
isn't advisable except for interoperability.
VerifyPSS verifies a PSS signature.
A valid signature is indicated by returning a nil error. digest must be the
result of hashing the input message using the given hash function. The opts
argument may be nil, in which case sensible defaults are used. opts.Hash is
ignored.
bigIntEqual reports whether a and b are equal leaking only their bit length
through timing side-channels.
checkPub sanity checks the public key before we use it.
We require pub.E to fit into a 32-bit integer so that we
do not have different behavior depending on whether
int is 32 or 64 bits. See also
https://www.imperialviolet.org/2012/03/16/rsae.html.
decrypt performs an RSA decryption of ciphertext into out. If check is true,
m^e is calculated and compared with ciphertext, in order to defend against
errors in the CRT computation.
decryptPKCS1v15 decrypts ciphertext using priv. It returns one or zero in
valid that indicates whether the plaintext was correctly structured.
In either case, the plaintext is returned in em so that it may be read
independently of whether it was valid in order to maintain constant memory
access patterns. If the plaintext was valid then index contains the index of
the original message in em, to allow constant time padding removal.
signPSSWithSalt calculates the signature of hashed using PSS with specified salt.
Note that hashed must be the result of hashing the input message using the
given hash function. salt is a random sequence of bytes whose length will be
later used to verify the signature.
Package-Level Variables (total 9, in which 3 are exported)
ErrDecryption represents a failure to decrypt a message.
It is deliberately vague to avoid adaptive attacks.
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.
ErrVerification represents a failure to verify a signature.
It is deliberately vague to avoid adaptive attacks.
These are ASN1 DER structures:
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTET STRING
}
For performance, we don't use the generic ASN1 encoder. Rather, we
precompute a prefix of the digest value that makes a valid ASN1 DER string
with the correct contents.
The pages are generated with Goldsv0.6.7. (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 @Go100and1 (reachable from the left QR code) to get the latest news of Golds.