1 // Copyright 2009 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.
15 // This file implements encryption and decryption using PKCS#1 v1.5 padding.
17 // EncryptPKCS1v15 encrypts the given message with RSA and the padding scheme from PKCS#1 v1.5.
18 // The message must be no longer than the length of the public modulus minus 11 bytes.
19 // WARNING: use of this function to encrypt plaintexts other than session keys
20 // is dangerous. Use RSA OAEP in new protocols.
21 func EncryptPKCS1v15(rand io
.Reader
, pub
*PublicKey
, msg
[]byte) (out
[]byte, err error
) {
22 if err
:= checkPub(pub
); err
!= nil {
25 k
:= (pub
.N
.BitLen() + 7) / 8
27 err
= ErrMessageTooLong
31 // EM = 0x00 || 0x02 || PS || 0x00 || M
34 ps
, mm
:= em
[2:len(em
)-len(msg
)-1], em
[len(em
)-len(msg
):]
35 err
= nonZeroRandomBytes(ps
, rand
)
39 em
[len(em
)-len(msg
)-1] = 0
42 m
:= new(big
.Int
).SetBytes(em
)
43 c
:= encrypt(new(big
.Int
), pub
, m
)
45 copyWithLeftPad(em
, c
.Bytes())
50 // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
51 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
52 func DecryptPKCS1v15(rand io
.Reader
, priv
*PrivateKey
, ciphertext
[]byte) (out
[]byte, err error
) {
53 if err
:= checkPub(&priv
.PublicKey
); err
!= nil {
56 valid
, out
, err
:= decryptPKCS1v15(rand
, priv
, ciphertext
)
57 if err
== nil && valid
== 0 {
64 // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5.
65 // If rand != nil, it uses RSA blinding to avoid timing side-channel attacks.
66 // It returns an error if the ciphertext is the wrong length or if the
67 // ciphertext is greater than the public modulus. Otherwise, no error is
68 // returned. If the padding is valid, the resulting plaintext message is copied
69 // into key. Otherwise, key is unchanged. These alternatives occur in constant
70 // time. It is intended that the user of this function generate a random
71 // session key beforehand and continue the protocol with the resulting value.
72 // This will remove any possibility that an attacker can learn any information
73 // about the plaintext.
74 // See ``Chosen Ciphertext Attacks Against Protocols Based on the RSA
75 // Encryption Standard PKCS #1'', Daniel Bleichenbacher, Advances in Cryptology
77 func DecryptPKCS1v15SessionKey(rand io
.Reader
, priv
*PrivateKey
, ciphertext
[]byte, key
[]byte) (err error
) {
78 if err
:= checkPub(&priv
.PublicKey
); err
!= nil {
81 k
:= (priv
.N
.BitLen() + 7) / 8
82 if k
-(len(key
)+3+8) < 0 {
87 valid
, msg
, err
:= decryptPKCS1v15(rand
, priv
, ciphertext
)
92 valid
&= subtle
.ConstantTimeEq(int32(len(msg
)), int32(len(key
)))
93 subtle
.ConstantTimeCopy(valid
, key
, msg
)
97 func decryptPKCS1v15(rand io
.Reader
, priv
*PrivateKey
, ciphertext
[]byte) (valid
int, msg
[]byte, err error
) {
98 k
:= (priv
.N
.BitLen() + 7) / 8
104 c
:= new(big
.Int
).SetBytes(ciphertext
)
105 m
, err
:= decrypt(rand
, priv
, c
)
110 em
:= leftPad(m
.Bytes(), k
)
111 firstByteIsZero
:= subtle
.ConstantTimeByteEq(em
[0], 0)
112 secondByteIsTwo
:= subtle
.ConstantTimeByteEq(em
[1], 2)
114 // The remainder of the plaintext must be a string of non-zero random
115 // octets, followed by a 0, followed by the message.
116 // lookingForIndex: 1 iff we are still looking for the zero.
117 // index: the offset of the first zero byte.
118 var lookingForIndex
, index
int
121 for i
:= 2; i
< len(em
); i
++ {
122 equals0
:= subtle
.ConstantTimeByteEq(em
[i
], 0)
123 index
= subtle
.ConstantTimeSelect(lookingForIndex
&equals0
, i
, index
)
124 lookingForIndex
= subtle
.ConstantTimeSelect(equals0
, 0, lookingForIndex
)
127 // The PS padding must be at least 8 bytes long, and it starts two
129 validPS
:= subtle
.ConstantTimeLessOrEq(2+8, index
)
131 valid
= firstByteIsZero
& secondByteIsTwo
& (^lookingForIndex
& 1) & validPS
136 // nonZeroRandomBytes fills the given slice with non-zero random octets.
137 func nonZeroRandomBytes(s
[]byte, rand io
.Reader
) (err error
) {
138 _
, err
= io
.ReadFull(rand
, s
)
143 for i
:= 0; i
< len(s
); i
++ {
145 _
, err
= io
.ReadFull(rand
, s
[i
:i
+1])
149 // In tests, the PRNG may return all zeros so we do
150 // this to break the loop.
158 // These are ASN1 DER structures:
159 // DigestInfo ::= SEQUENCE {
160 // digestAlgorithm AlgorithmIdentifier,
161 // digest OCTET STRING
163 // For performance, we don't use the generic ASN1 encoder. Rather, we
164 // precompute a prefix of the digest value that makes a valid ASN1 DER string
165 // with the correct contents.
166 var hashPrefixes
= map[crypto
.Hash
][]byte{
167 crypto
.MD5
: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10},
168 crypto
.SHA1
: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14},
169 crypto
.SHA224
: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c},
170 crypto
.SHA256
: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20},
171 crypto
.SHA384
: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30},
172 crypto
.SHA512
: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40},
173 crypto
.MD5SHA1
: {}, // A special TLS case which doesn't use an ASN1 prefix.
174 crypto
.RIPEMD160
: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14},
177 // SignPKCS1v15 calculates the signature of hashed using RSASSA-PKCS1-V1_5-SIGN from RSA PKCS#1 v1.5.
178 // Note that hashed must be the result of hashing the input message using the
179 // given hash function. If hash is zero, hashed is signed directly. This isn't
180 // advisable except for interoperability.
181 func SignPKCS1v15(rand io
.Reader
, priv
*PrivateKey
, hash crypto
.Hash
, hashed
[]byte) (s
[]byte, err error
) {
182 hashLen
, prefix
, err
:= pkcs1v15HashInfo(hash
, len(hashed
))
187 tLen
:= len(prefix
) + hashLen
188 k
:= (priv
.N
.BitLen() + 7) / 8
190 return nil, ErrMessageTooLong
193 // EM = 0x00 || 0x01 || PS || 0x00 || T
194 em
:= make([]byte, k
)
196 for i
:= 2; i
< k
-tLen
-1; i
++ {
199 copy(em
[k
-tLen
:k
-hashLen
], prefix
)
200 copy(em
[k
-hashLen
:k
], hashed
)
202 m
:= new(big
.Int
).SetBytes(em
)
203 c
, err
:= decrypt(rand
, priv
, m
)
208 copyWithLeftPad(em
, c
.Bytes())
213 // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
214 // hashed is the result of hashing the input message using the given hash
215 // function and sig is the signature. A valid signature is indicated by
216 // returning a nil error. If hash is zero then hashed is used directly. This
217 // isn't advisable except for interoperability.
218 func VerifyPKCS1v15(pub
*PublicKey
, hash crypto
.Hash
, hashed
[]byte, sig
[]byte) (err error
) {
219 hashLen
, prefix
, err
:= pkcs1v15HashInfo(hash
, len(hashed
))
224 tLen
:= len(prefix
) + hashLen
225 k
:= (pub
.N
.BitLen() + 7) / 8
227 err
= ErrVerification
231 c
:= new(big
.Int
).SetBytes(sig
)
232 m
:= encrypt(new(big
.Int
), pub
, c
)
233 em
:= leftPad(m
.Bytes(), k
)
234 // EM = 0x00 || 0x01 || PS || 0x00 || T
236 ok
:= subtle
.ConstantTimeByteEq(em
[0], 0)
237 ok
&= subtle
.ConstantTimeByteEq(em
[1], 1)
238 ok
&= subtle
.ConstantTimeCompare(em
[k
-hashLen
:k
], hashed
)
239 ok
&= subtle
.ConstantTimeCompare(em
[k
-tLen
:k
-hashLen
], prefix
)
240 ok
&= subtle
.ConstantTimeByteEq(em
[k
-tLen
-1], 0)
242 for i
:= 2; i
< k
-tLen
-1; i
++ {
243 ok
&= subtle
.ConstantTimeByteEq(em
[i
], 0xff)
247 return ErrVerification
253 func pkcs1v15HashInfo(hash crypto
.Hash
, inLen
int) (hashLen
int, prefix
[]byte, err error
) {
254 // Special case: crypto.Hash(0) is used to indicate that the data is
257 return inLen
, nil, nil
260 hashLen
= hash
.Size()
261 if inLen
!= hashLen
{
262 return 0, nil, errors
.New("crypto/rsa: input must be hashed message")
264 prefix
, ok
:= hashPrefixes
[hash
]
266 return 0, nil, errors
.New("crypto/rsa: unsupported hash function")
271 // copyWithLeftPad copies src to the end of dest, padding with zero bytes as
273 func copyWithLeftPad(dest
, src
[]byte) {
274 numPaddingBytes
:= len(dest
) - len(src
)
275 for i
:= 0; i
< numPaddingBytes
; i
++ {
278 copy(dest
[numPaddingBytes
:], src
)