1 // Copyright 2013 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.
7 // This file implementes the PSS signature scheme [1].
9 // [1] http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptography-standard.pdf
20 func emsaPSSEncode(mHash
[]byte, emBits
int, salt
[]byte, hash hash
.Hash
) ([]byte, error
) {
21 // See [1], section 9.1.1
24 emLen
:= (emBits
+ 7) / 8
26 // 1. If the length of M is greater than the input limitation for the
27 // hash function (2^61 - 1 octets for SHA-1), output "message too
30 // 2. Let mHash = Hash(M), an octet string of length hLen.
32 if len(mHash
) != hLen
{
33 return nil, errors
.New("crypto/rsa: input must be hashed message")
36 // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop.
38 if emLen
< hLen
+sLen
+2 {
39 return nil, errors
.New("crypto/rsa: encoding error")
42 em
:= make([]byte, emLen
)
43 db
:= em
[:emLen
-sLen
-hLen
-2+1+sLen
]
44 h
:= em
[emLen
-sLen
-hLen
-2+1+sLen
: emLen
-1]
46 // 4. Generate a random octet string salt of length sLen; if sLen = 0,
47 // then salt is the empty string.
50 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt;
52 // M' is an octet string of length 8 + hLen + sLen with eight
53 // initial zero octets.
55 // 6. Let H = Hash(M'), an octet string of length hLen.
66 // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2
67 // zero octets. The length of PS may be 0.
69 // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
72 db
[emLen
-sLen
-hLen
-2] = 0x01
73 copy(db
[emLen
-sLen
-hLen
-1:], salt
)
75 // 9. Let dbMask = MGF(H, emLen - hLen - 1).
77 // 10. Let maskedDB = DB \xor dbMask.
81 // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
84 db
[0] &= (0xFF >> uint(8*emLen
-emBits
))
86 // 12. Let EM = maskedDB || H || 0xbc.
93 func emsaPSSVerify(mHash
, em
[]byte, emBits
, sLen
int, hash hash
.Hash
) error
{
94 // 1. If the length of M is greater than the input limitation for the
95 // hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
98 // 2. Let mHash = Hash(M), an octet string of length hLen.
100 if hLen
!= len(mHash
) {
101 return ErrVerification
104 // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop.
105 emLen
:= (emBits
+ 7) / 8
106 if emLen
< hLen
+sLen
+2 {
107 return ErrVerification
110 // 4. If the rightmost octet of EM does not have hexadecimal value
111 // 0xbc, output "inconsistent" and stop.
112 if em
[len(em
)-1] != 0xBC {
113 return ErrVerification
116 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
117 // let H be the next hLen octets.
118 db
:= em
[:emLen
-hLen
-1]
119 h
:= em
[emLen
-hLen
-1 : len(em
)-1]
121 // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in
122 // maskedDB are not all equal to zero, output "inconsistent" and
124 if em
[0]&(0xFF<<uint(8-(8*emLen
-emBits
))) != 0 {
125 return ErrVerification
128 // 7. Let dbMask = MGF(H, emLen - hLen - 1).
130 // 8. Let DB = maskedDB \xor dbMask.
133 // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
135 db
[0] &= (0xFF >> uint(8*emLen
-emBits
))
137 if sLen
== PSSSaltLengthAuto
{
139 for sLen
= emLen
- (hLen
+ 2); sLen
>= 0; sLen
-- {
140 switch db
[emLen
-hLen
-sLen
-2] {
146 return ErrVerification
150 return ErrVerification
153 // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
154 // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
155 // position is "position 1") does not have hexadecimal value 0x01,
156 // output "inconsistent" and stop.
157 for _
, e
:= range db
[:emLen
-hLen
-sLen
-2] {
159 return ErrVerification
162 if db
[emLen
-hLen
-sLen
-2] != 0x01 {
163 return ErrVerification
167 // 11. Let salt be the last sLen octets of DB.
168 salt
:= db
[len(db
)-sLen
:]
171 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ;
172 // M' is an octet string of length 8 + hLen + sLen with eight
173 // initial zero octets.
175 // 13. Let H' = Hash(M'), an octet string of length hLen.
177 hash
.Write(prefix
[:])
183 // 14. If H = H', output "consistent." Otherwise, output "inconsistent."
184 if !bytes
.Equal(h0
, h
) {
185 return ErrVerification
190 // signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
191 // Note that hashed must be the result of hashing the input message using the
192 // given hash funcion. salt is a random sequence of bytes whose length will be
193 // later used to verify the signature.
194 func signPSSWithSalt(rand io
.Reader
, priv
*PrivateKey
, hash crypto
.Hash
, hashed
, salt
[]byte) (s
[]byte, err error
) {
195 nBits
:= priv
.N
.BitLen()
196 em
, err
:= emsaPSSEncode(hashed
, nBits
-1, salt
, hash
.New())
200 m
:= new(big
.Int
).SetBytes(em
)
201 c
, err
:= decrypt(rand
, priv
, m
)
205 s
= make([]byte, (nBits
+7)/8)
206 copyWithLeftPad(s
, c
.Bytes())
211 // PSSSaltLengthAuto causes the salt in a PSS signature to be as large
212 // as possible when signing, and to be auto-detected when verifying.
213 PSSSaltLengthAuto
= 0
214 // PSSSaltLengthEqualsHash causes the salt length to equal the length
215 // of the hash used in the signature.
216 PSSSaltLengthEqualsHash
= -1
219 // PSSOptions contains options for creating and verifying PSS signatures.
220 type PSSOptions
struct {
221 // SaltLength controls the length of the salt used in the PSS
222 // signature. It can either be a number of bytes, or one of the special
223 // PSSSaltLength constants.
227 func (opts
*PSSOptions
) saltLength() int {
229 return PSSSaltLengthAuto
231 return opts
.SaltLength
234 // SignPSS calculates the signature of hashed using RSASSA-PSS [1].
235 // Note that hashed must be the result of hashing the input message using the
236 // given hash funcion. The opts argument may be nil, in which case sensible
237 // defaults are used.
238 func SignPSS(rand io
.Reader
, priv
*PrivateKey
, hash crypto
.Hash
, hashed
[]byte, opts
*PSSOptions
) (s
[]byte, err error
) {
239 saltLength
:= opts
.saltLength()
241 case PSSSaltLengthAuto
:
242 saltLength
= (priv
.N
.BitLen()+7)/8 - 2 - hash
.Size()
243 case PSSSaltLengthEqualsHash
:
244 saltLength
= hash
.Size()
247 salt
:= make([]byte, saltLength
)
248 if _
, err
= io
.ReadFull(rand
, salt
); err
!= nil {
251 return signPSSWithSalt(rand
, priv
, hash
, hashed
, salt
)
254 // VerifyPSS verifies a PSS signature.
255 // hashed is the result of hashing the input message using the given hash
256 // function and sig is the signature. A valid signature is indicated by
257 // returning a nil error. The opts argument may be nil, in which case sensible
258 // defaults are used.
259 func VerifyPSS(pub
*PublicKey
, hash crypto
.Hash
, hashed
[]byte, sig
[]byte, opts
*PSSOptions
) error
{
260 return verifyPSS(pub
, hash
, hashed
, sig
, opts
.saltLength())
263 // verifyPSS verifies a PSS signature with the given salt length.
264 func verifyPSS(pub
*PublicKey
, hash crypto
.Hash
, hashed
[]byte, sig
[]byte, saltLen
int) error
{
265 nBits
:= pub
.N
.BitLen()
266 if len(sig
) != (nBits
+7)/8 {
267 return ErrVerification
269 s
:= new(big
.Int
).SetBytes(sig
)
270 m
:= encrypt(new(big
.Int
), pub
, s
)
272 emLen
:= (emBits
+ 7) / 8
273 if emLen
< len(m
.Bytes()) {
274 return ErrVerification
276 em
:= make([]byte, emLen
)
277 copyWithLeftPad(em
, m
.Bytes())
278 if saltLen
== PSSSaltLengthEqualsHash
{
279 saltLen
= hash
.Size()
281 return emsaPSSVerify(hashed
, em
, emBits
, saltLen
, hash
.New())