Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 package rsa | |
2 | |
3 // This file implemented the RSASSA-PSS signature algorithms [1]. | |
4 // | |
5 // 1. http://www.rsa.com/rsalabs/pkcs/files/h11300-wp-pkcs-1v2-2-rsa-cryptograph y-standard.pdf | |
6 import ( | |
7 "bytes" | |
8 "crypto" | |
9 "errors" | |
10 "hash" | |
11 "io" | |
12 "math/big" | |
13 ) | |
14 | |
15 func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt e, error) { | |
16 // See [1], section 9.1.1 | |
17 hLen := hash.Size() | |
18 sLen := len(salt) | |
19 emLen := (emBits + 7) / 8 | |
20 | |
21 // 1. If the length of M is greater than the input limitation for the | |
22 // hash function (2^61 - 1 octets for SHA-1), output "message too | |
23 // long" and stop. | |
24 // | |
25 // 2. Let mHash = Hash(M), an octet string of length hLen. | |
26 | |
27 if len(mHash) != hLen { | |
28 return nil, errors.New("crypto/rsa: input must be hashed message ") | |
29 } | |
30 | |
31 // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. | |
32 | |
33 if emLen < hLen+sLen+2 { | |
34 return nil, errors.New("crypto/rsa: encoding error") | |
35 } | |
36 | |
37 em := make([]byte, emLen) | |
38 db := em[:emLen-sLen-hLen-2+1+sLen] | |
39 h := em[emLen-sLen-hLen-2+1+sLen : emLen-1] | |
40 | |
41 // 4. Generate a random octet string salt of length sLen; if sLen = 0, | |
42 // then salt is the empty string. | |
43 // | |
44 // 5. Let | |
45 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt; | |
46 // | |
47 // M' is an octet string of length 8 + hLen + sLen with eight | |
48 // initial zero octets. | |
49 // | |
50 // 6. Let H = Hash(M'), an octet string of length hLen. | |
51 | |
52 var prefix [8]byte | |
53 | |
54 hash.Write(prefix[:]) | |
55 hash.Write(mHash) | |
56 hash.Write(salt) | |
57 | |
58 h = hash.Sum(h[:0]) | |
59 hash.Reset() | |
60 | |
61 // 7. Generate an octet string PS consisting of emLen - sLen - hLen - 2 | |
62 // zero octets. The length of PS may be 0. | |
63 // | |
64 // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length | |
65 // emLen - hLen - 1. | |
66 | |
67 db[emLen-sLen-hLen-2] = 0x01 | |
68 copy(db[emLen-sLen-hLen-1:], salt) | |
69 | |
70 // 9. Let dbMask = MGF(H, emLen - hLen - 1). | |
71 // | |
72 // 10. Let maskedDB = DB \xor dbMask. | |
73 | |
74 mgf1XOR(db, hash, h) | |
75 | |
76 // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in | |
77 // maskedDB to zero. | |
78 | |
79 db[0] &= (0xFF >> uint(8*emLen-emBits)) | |
80 | |
81 // 12. Let EM = maskedDB || H || 0xbc. | |
82 em[emLen-1] = 0xBC | |
83 | |
84 // 13. Output EM. | |
85 return em, nil | |
86 } | |
87 | |
88 func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { | |
89 // 1. If the length of M is greater than the input limitation for the | |
90 // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" | |
91 // and stop. | |
92 // | |
93 // 2. Let mHash = Hash(M), an octet string of length hLen. | |
94 hLen := hash.Size() | |
95 if hLen != len(mHash) { | |
96 return ErrVerification | |
97 } | |
98 | |
99 // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. | |
100 emLen := (emBits + 7) / 8 | |
101 if emLen < hLen+sLen+2 { | |
102 return ErrVerification | |
103 } | |
104 | |
105 // 4. If the rightmost octet of EM does not have hexadecimal value | |
106 // 0xbc, output "inconsistent" and stop. | |
107 if em[len(em)-1] != 0xBC { | |
108 return ErrVerification | |
109 } | |
110 | |
111 // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and | |
112 // let H be the next hLen octets. | |
113 db := em[:emLen-hLen-1] | |
114 h := em[emLen-hLen-1 : len(em)-1] | |
115 | |
116 // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in | |
117 // maskedDB are not all equal to zero, output "inconsistent" and | |
118 // stop. | |
119 if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 { | |
120 return ErrVerification | |
121 } | |
122 | |
123 // 7. Let dbMask = MGF(H, emLen - hLen - 1). | |
124 // | |
125 // 8. Let DB = maskedDB \xor dbMask. | |
126 mgf1XOR(db, hash, h) | |
127 | |
128 // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB | |
129 // to zero. | |
130 db[0] &= (0xFF >> uint(8*emLen-emBits)) | |
131 | |
132 // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero | |
133 // or if the octet at position emLen - hLen - sLen - 1 (the leftmost | |
134 // position is "position 1") does not have hexadecimal value 0x01, | |
135 // output "inconsistent" and stop. | |
136 for _, e := range db[:emLen-hLen-sLen-2] { | |
137 if e != 0x00 { | |
138 return ErrVerification | |
139 } | |
140 } | |
141 if db[emLen-hLen-sLen-2] != 0x01 { | |
142 return ErrVerification | |
143 } | |
144 | |
145 // 11. Let salt be the last sLen octets of DB. | |
146 salt := db[len(db)-sLen:] | |
147 | |
148 // 12. Let | |
149 // M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; | |
150 // M' is an octet string of length 8 + hLen + sLen with eight | |
151 // initial zero octets. | |
152 // | |
153 // 13. Let H' = Hash(M'), an octet string of length hLen. | |
154 var prefix [8]byte | |
155 hash.Write(prefix[:]) | |
156 hash.Write(mHash) | |
157 hash.Write(salt) | |
158 | |
159 h0 := hash.Sum(nil) | |
160 | |
161 // 14. If H = H', output "consistent." Otherwise, output "inconsistent." | |
162 if !bytes.Equal(h0, h) { | |
163 return ErrVerification | |
164 } | |
165 return nil | |
166 } | |
167 | |
168 // signPSSWithSalt calculates the signature of hashed using RSASSA-PSS [1] with specified salt. | |
169 // Note that hashed must be the result of hashing the input message using the gi ven hash funcion. | |
170 // salt is a random sequence of bytes whose length will be later used to verify the signature. | |
171 func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, salt []byte) (s []byte, err error) { | |
172 nBits := priv.N.BitLen() | |
173 em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New()) | |
174 if err != nil { | |
175 return | |
176 } | |
177 m := new(big.Int).SetBytes(em) | |
178 c, err := decrypt(rand, priv, m) | |
179 if err != nil { | |
180 return | |
181 } | |
182 s = make([]byte, (nBits+7)/8) | |
183 copyWithLeftPad(s, c.Bytes()) | |
184 return | |
185 } | |
186 | |
187 // SignPSS calculates the signature of hashed using RSASSA-PSS [1]. | |
188 // Note that hashed must be the result of hashing the input message using the gi ven hash funcion. | |
189 // saltLen is size of the salt. Usually it is the same size as the digest genera ted by the hash. | |
190 func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, saltLen int) (s []byte, err error) { | |
agl1
2013/05/20 19:56:23
Some reorganisation is probably needed before land
Nan Deng
2013/05/20 20:19:58
I agree. After a reading of more details, I would
| |
191 salt := make([]byte, saltLen) | |
192 _, err = io.ReadFull(rand, salt) | |
193 if err != nil { | |
194 return | |
195 } | |
196 s, err = signPSSWithSalt(rand, priv, hash, hashed, salt) | |
197 return | |
198 } | |
199 | |
200 // VerifyPSS verifies an RSASSA-PSS signature. | |
201 // hashed is the result of hashing the input message using the given hash functi on and sig is the signature. | |
202 // A valid signature is indicated by returning a nil error. | |
203 // saltLen is number of bytes of the salt used to sign the message. | |
204 func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, salt Len int) error { | |
205 nBits := pub.N.BitLen() | |
206 if len(sig) != (nBits+7)/8 { | |
207 return ErrVerification | |
208 } | |
209 s := new(big.Int).SetBytes(sig) | |
210 m := encrypt(new(big.Int), pub, s) | |
211 emBits := nBits - 1 | |
212 emLen := (emBits + 7) / 8 | |
213 if emLen < len(m.Bytes()) { | |
214 return ErrVerification | |
215 } | |
216 em := make([]byte, emLen) | |
217 copyWithLeftPad(em, m.Bytes()) | |
218 if err := emsaPSSVerify(hashed, em, emBits, saltLen, hash.New()); err != nil { | |
219 return err | |
220 } | |
221 return nil | |
222 } | |
OLD | NEW |