OLD | NEW |
| 1 # Author: Trevor Perrin |
| 2 # See the LICENSE file for legal information regarding use of this file. |
| 3 |
1 """Abstract class for RSA.""" | 4 """Abstract class for RSA.""" |
2 | 5 |
3 from cryptomath import * | 6 from .cryptomath import * |
4 | 7 |
5 | 8 |
6 class RSAKey: | 9 class RSAKey(object): |
7 """This is an abstract base class for RSA keys. | 10 """This is an abstract base class for RSA keys. |
8 | 11 |
9 Particular implementations of RSA keys, such as | 12 Particular implementations of RSA keys, such as |
10 L{OpenSSL_RSAKey.OpenSSL_RSAKey}, | 13 L{openssl_rsakey.OpenSSL_RSAKey}, |
11 L{Python_RSAKey.Python_RSAKey}, and | 14 L{python_rsakey.Python_RSAKey}, and |
12 L{PyCrypto_RSAKey.PyCrypto_RSAKey}, | 15 L{pycrypto_rsakey.PyCrypto_RSAKey}, |
13 inherit from this. | 16 inherit from this. |
14 | 17 |
15 To create or parse an RSA key, don't use one of these classes | 18 To create or parse an RSA key, don't use one of these classes |
16 directly. Instead, use the factory functions in | 19 directly. Instead, use the factory functions in |
17 L{tlslite.utils.keyfactory}. | 20 L{tlslite.utils.keyfactory}. |
18 """ | 21 """ |
19 | 22 |
20 def __init__(self, n=0, e=0): | 23 def __init__(self, n=0, e=0): |
21 """Create a new RSA key. | 24 """Create a new RSA key. |
22 | 25 |
(...skipping 14 matching lines...) Expand all Loading... |
37 """ | 40 """ |
38 return numBits(self.n) | 41 return numBits(self.n) |
39 | 42 |
40 def hasPrivateKey(self): | 43 def hasPrivateKey(self): |
41 """Return whether or not this key has a private component. | 44 """Return whether or not this key has a private component. |
42 | 45 |
43 @rtype: bool | 46 @rtype: bool |
44 """ | 47 """ |
45 raise NotImplementedError() | 48 raise NotImplementedError() |
46 | 49 |
47 def hash(self): | |
48 """Return the cryptoID <keyHash> value corresponding to this | |
49 key. | |
50 | |
51 @rtype: str | |
52 """ | |
53 raise NotImplementedError() | |
54 | |
55 def getSigningAlgorithm(self): | |
56 """Return the cryptoID sigAlgo value corresponding to this key. | |
57 | |
58 @rtype: str | |
59 """ | |
60 return "pkcs1-sha1" | |
61 | |
62 def hashAndSign(self, bytes): | 50 def hashAndSign(self, bytes): |
63 """Hash and sign the passed-in bytes. | 51 """Hash and sign the passed-in bytes. |
64 | 52 |
65 This requires the key to have a private component. It performs | 53 This requires the key to have a private component. It performs |
66 a PKCS1-SHA1 signature on the passed-in data. | 54 a PKCS1-SHA1 signature on the passed-in data. |
67 | 55 |
68 @type bytes: str or L{array.array} of unsigned bytes | 56 @type bytes: str or L{bytearray} of unsigned bytes |
69 @param bytes: The value which will be hashed and signed. | 57 @param bytes: The value which will be hashed and signed. |
70 | 58 |
71 @rtype: L{array.array} of unsigned bytes. | 59 @rtype: L{bytearray} of unsigned bytes. |
72 @return: A PKCS1-SHA1 signature on the passed-in data. | 60 @return: A PKCS1-SHA1 signature on the passed-in data. |
73 """ | 61 """ |
74 if not isinstance(bytes, type("")): | 62 hashBytes = SHA1(bytearray(bytes)) |
75 bytes = bytesToString(bytes) | |
76 hashBytes = stringToBytes(sha.sha(bytes).digest()) | |
77 prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) | 63 prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) |
78 sigBytes = self.sign(prefixedHashBytes) | 64 sigBytes = self.sign(prefixedHashBytes) |
79 return sigBytes | 65 return sigBytes |
80 | 66 |
81 def hashAndVerify(self, sigBytes, bytes): | 67 def hashAndVerify(self, sigBytes, bytes): |
82 """Hash and verify the passed-in bytes with the signature. | 68 """Hash and verify the passed-in bytes with the signature. |
83 | 69 |
84 This verifies a PKCS1-SHA1 signature on the passed-in data. | 70 This verifies a PKCS1-SHA1 signature on the passed-in data. |
85 | 71 |
86 @type sigBytes: L{array.array} of unsigned bytes | 72 @type sigBytes: L{bytearray} of unsigned bytes |
87 @param sigBytes: A PKCS1-SHA1 signature. | 73 @param sigBytes: A PKCS1-SHA1 signature. |
88 | 74 |
89 @type bytes: str or L{array.array} of unsigned bytes | 75 @type bytes: str or L{bytearray} of unsigned bytes |
90 @param bytes: The value which will be hashed and verified. | 76 @param bytes: The value which will be hashed and verified. |
91 | 77 |
92 @rtype: bool | 78 @rtype: bool |
93 @return: Whether the signature matches the passed-in data. | 79 @return: Whether the signature matches the passed-in data. |
94 """ | 80 """ |
95 if not isinstance(bytes, type("")): | 81 hashBytes = SHA1(bytearray(bytes)) |
96 bytes = bytesToString(bytes) | 82 |
97 hashBytes = stringToBytes(sha.sha(bytes).digest()) | 83 # Try it with/without the embedded NULL |
98 prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) | 84 prefixedHashBytes1 = self._addPKCS1SHA1Prefix(hashBytes, False) |
99 return self.verify(sigBytes, prefixedHashBytes) | 85 prefixedHashBytes2 = self._addPKCS1SHA1Prefix(hashBytes, True) |
| 86 result1 = self.verify(sigBytes, prefixedHashBytes1) |
| 87 result2 = self.verify(sigBytes, prefixedHashBytes2) |
| 88 return (result1 or result2) |
100 | 89 |
101 def sign(self, bytes): | 90 def sign(self, bytes): |
102 """Sign the passed-in bytes. | 91 """Sign the passed-in bytes. |
103 | 92 |
104 This requires the key to have a private component. It performs | 93 This requires the key to have a private component. It performs |
105 a PKCS1 signature on the passed-in data. | 94 a PKCS1 signature on the passed-in data. |
106 | 95 |
107 @type bytes: L{array.array} of unsigned bytes | 96 @type bytes: L{bytearray} of unsigned bytes |
108 @param bytes: The value which will be signed. | 97 @param bytes: The value which will be signed. |
109 | 98 |
110 @rtype: L{array.array} of unsigned bytes. | 99 @rtype: L{bytearray} of unsigned bytes. |
111 @return: A PKCS1 signature on the passed-in data. | 100 @return: A PKCS1 signature on the passed-in data. |
112 """ | 101 """ |
113 if not self.hasPrivateKey(): | 102 if not self.hasPrivateKey(): |
114 raise AssertionError() | 103 raise AssertionError() |
115 paddedBytes = self._addPKCS1Padding(bytes, 1) | 104 paddedBytes = self._addPKCS1Padding(bytes, 1) |
116 m = bytesToNumber(paddedBytes) | 105 m = bytesToNumber(paddedBytes) |
117 if m >= self.n: | 106 if m >= self.n: |
118 raise ValueError() | 107 raise ValueError() |
119 c = self._rawPrivateKeyOp(m) | 108 c = self._rawPrivateKeyOp(m) |
120 sigBytes = numberToBytes(c, numBytes(self.n)) | 109 sigBytes = numberToByteArray(c, numBytes(self.n)) |
121 return sigBytes | 110 return sigBytes |
122 | 111 |
123 def verify(self, sigBytes, bytes): | 112 def verify(self, sigBytes, bytes): |
124 """Verify the passed-in bytes with the signature. | 113 """Verify the passed-in bytes with the signature. |
125 | 114 |
126 This verifies a PKCS1 signature on the passed-in data. | 115 This verifies a PKCS1 signature on the passed-in data. |
127 | 116 |
128 @type sigBytes: L{array.array} of unsigned bytes | 117 @type sigBytes: L{bytearray} of unsigned bytes |
129 @param sigBytes: A PKCS1 signature. | 118 @param sigBytes: A PKCS1 signature. |
130 | 119 |
131 @type bytes: L{array.array} of unsigned bytes | 120 @type bytes: L{bytearray} of unsigned bytes |
132 @param bytes: The value which will be verified. | 121 @param bytes: The value which will be verified. |
133 | 122 |
134 @rtype: bool | 123 @rtype: bool |
135 @return: Whether the signature matches the passed-in data. | 124 @return: Whether the signature matches the passed-in data. |
136 """ | 125 """ |
| 126 if len(sigBytes) != numBytes(self.n): |
| 127 return False |
137 paddedBytes = self._addPKCS1Padding(bytes, 1) | 128 paddedBytes = self._addPKCS1Padding(bytes, 1) |
138 c = bytesToNumber(sigBytes) | 129 c = bytesToNumber(sigBytes) |
139 if c >= self.n: | 130 if c >= self.n: |
140 return False | 131 return False |
141 m = self._rawPublicKeyOp(c) | 132 m = self._rawPublicKeyOp(c) |
142 checkBytes = numberToBytes(m) | 133 checkBytes = numberToByteArray(m, numBytes(self.n)) |
143 return checkBytes == paddedBytes | 134 return checkBytes == paddedBytes |
144 | 135 |
145 def encrypt(self, bytes): | 136 def encrypt(self, bytes): |
146 """Encrypt the passed-in bytes. | 137 """Encrypt the passed-in bytes. |
147 | 138 |
148 This performs PKCS1 encryption of the passed-in data. | 139 This performs PKCS1 encryption of the passed-in data. |
149 | 140 |
150 @type bytes: L{array.array} of unsigned bytes | 141 @type bytes: L{bytearray} of unsigned bytes |
151 @param bytes: The value which will be encrypted. | 142 @param bytes: The value which will be encrypted. |
152 | 143 |
153 @rtype: L{array.array} of unsigned bytes. | 144 @rtype: L{bytearray} of unsigned bytes. |
154 @return: A PKCS1 encryption of the passed-in data. | 145 @return: A PKCS1 encryption of the passed-in data. |
155 """ | 146 """ |
156 paddedBytes = self._addPKCS1Padding(bytes, 2) | 147 paddedBytes = self._addPKCS1Padding(bytes, 2) |
157 m = bytesToNumber(paddedBytes) | 148 m = bytesToNumber(paddedBytes) |
158 if m >= self.n: | 149 if m >= self.n: |
159 raise ValueError() | 150 raise ValueError() |
160 c = self._rawPublicKeyOp(m) | 151 c = self._rawPublicKeyOp(m) |
161 encBytes = numberToBytes(c) | 152 encBytes = numberToByteArray(c, numBytes(self.n)) |
162 return encBytes | 153 return encBytes |
163 | 154 |
164 def decrypt(self, encBytes): | 155 def decrypt(self, encBytes): |
165 """Decrypt the passed-in bytes. | 156 """Decrypt the passed-in bytes. |
166 | 157 |
167 This requires the key to have a private component. It performs | 158 This requires the key to have a private component. It performs |
168 PKCS1 decryption of the passed-in data. | 159 PKCS1 decryption of the passed-in data. |
169 | 160 |
170 @type encBytes: L{array.array} of unsigned bytes | 161 @type encBytes: L{bytearray} of unsigned bytes |
171 @param encBytes: The value which will be decrypted. | 162 @param encBytes: The value which will be decrypted. |
172 | 163 |
173 @rtype: L{array.array} of unsigned bytes or None. | 164 @rtype: L{bytearray} of unsigned bytes or None. |
174 @return: A PKCS1 decryption of the passed-in data or None if | 165 @return: A PKCS1 decryption of the passed-in data or None if |
175 the data is not properly formatted. | 166 the data is not properly formatted. |
176 """ | 167 """ |
177 if not self.hasPrivateKey(): | 168 if not self.hasPrivateKey(): |
178 raise AssertionError() | 169 raise AssertionError() |
| 170 if len(encBytes) != numBytes(self.n): |
| 171 return None |
179 c = bytesToNumber(encBytes) | 172 c = bytesToNumber(encBytes) |
180 if c >= self.n: | 173 if c >= self.n: |
181 return None | 174 return None |
182 m = self._rawPrivateKeyOp(c) | 175 m = self._rawPrivateKeyOp(c) |
183 decBytes = numberToBytes(m) | 176 decBytes = numberToByteArray(m, numBytes(self.n)) |
184 if (len(decBytes) != numBytes(self.n)-1): #Check first byte | 177 #Check first two bytes |
| 178 if decBytes[0] != 0 or decBytes[1] != 2: |
185 return None | 179 return None |
186 if decBytes[0] != 2: #Check second byte | 180 #Scan through for zero separator |
187 return None | 181 for x in range(1, len(decBytes)-1): |
188 for x in range(len(decBytes)-1): #Scan through for zero separator | |
189 if decBytes[x]== 0: | 182 if decBytes[x]== 0: |
190 break | 183 break |
191 else: | 184 else: |
192 return None | 185 return None |
193 return decBytes[x+1:] #Return everything after the separator | 186 return decBytes[x+1:] #Return everything after the separator |
194 | 187 |
195 def _rawPrivateKeyOp(self, m): | 188 def _rawPrivateKeyOp(self, m): |
196 raise NotImplementedError() | 189 raise NotImplementedError() |
197 | 190 |
198 def _rawPublicKeyOp(self, c): | 191 def _rawPublicKeyOp(self, c): |
199 raise NotImplementedError() | 192 raise NotImplementedError() |
200 | 193 |
201 def acceptsPassword(self): | 194 def acceptsPassword(self): |
202 """Return True if the write() method accepts a password for use | 195 """Return True if the write() method accepts a password for use |
203 in encrypting the private key. | 196 in encrypting the private key. |
204 | 197 |
205 @rtype: bool | 198 @rtype: bool |
206 """ | 199 """ |
207 raise NotImplementedError() | 200 raise NotImplementedError() |
208 | 201 |
209 def write(self, password=None): | 202 def write(self, password=None): |
210 """Return a string containing the key. | 203 """Return a string containing the key. |
211 | 204 |
212 @rtype: str | 205 @rtype: str |
213 @return: A string describing the key, in whichever format (PEM | 206 @return: A string describing the key, in whichever format (PEM) |
214 or XML) is native to the implementation. | 207 is native to the implementation. |
215 """ | 208 """ |
216 raise NotImplementedError() | 209 raise NotImplementedError() |
217 | 210 |
218 def writeXMLPublicKey(self, indent=''): | |
219 """Return a string containing the key. | |
220 | |
221 @rtype: str | |
222 @return: A string describing the public key, in XML format. | |
223 """ | |
224 return Python_RSAKey(self.n, self.e).write(indent) | |
225 | |
226 def generate(bits): | 211 def generate(bits): |
227 """Generate a new key with the specified bit length. | 212 """Generate a new key with the specified bit length. |
228 | 213 |
229 @rtype: L{tlslite.utils.RSAKey.RSAKey} | 214 @rtype: L{tlslite.utils.RSAKey.RSAKey} |
230 """ | 215 """ |
231 raise NotImplementedError() | 216 raise NotImplementedError() |
232 generate = staticmethod(generate) | 217 generate = staticmethod(generate) |
233 | 218 |
234 | 219 |
235 # ************************************************************************** | 220 # ************************************************************************** |
236 # Helper Functions for RSA Keys | 221 # Helper Functions for RSA Keys |
237 # ************************************************************************** | 222 # ************************************************************************** |
238 | 223 |
239 def _addPKCS1SHA1Prefix(self, bytes): | 224 def _addPKCS1SHA1Prefix(self, bytes, withNULL=True): |
240 prefixBytes = createByteArraySequence(\ | 225 # There is a long history of confusion over whether the SHA1 |
241 [48,33,48,9,6,5,43,14,3,2,26,5,0,4,20]) | 226 # algorithmIdentifier should be encoded with a NULL parameter or |
| 227 # with the parameter omitted. While the original intention was |
| 228 # apparently to omit it, many toolkits went the other way. TLS 1.2 |
| 229 # specifies the NULL should be included, and this behavior is also |
| 230 # mandated in recent versions of PKCS #1, and is what tlslite has |
| 231 # always implemented. Anyways, verification code should probably |
| 232 # accept both. However, nothing uses this code yet, so this is |
| 233 # all fairly moot. |
| 234 if not withNULL: |
| 235 prefixBytes = bytearray(\ |
| 236 [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])
|
| 237 else: |
| 238 prefixBytes = bytearray(\ |
| 239 [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x
04,0x14]) |
242 prefixedBytes = prefixBytes + bytes | 240 prefixedBytes = prefixBytes + bytes |
243 return prefixedBytes | 241 return prefixedBytes |
244 | 242 |
245 def _addPKCS1Padding(self, bytes, blockType): | 243 def _addPKCS1Padding(self, bytes, blockType): |
246 padLength = (numBytes(self.n) - (len(bytes)+3)) | 244 padLength = (numBytes(self.n) - (len(bytes)+3)) |
247 if blockType == 1: #Signature padding | 245 if blockType == 1: #Signature padding |
248 pad = [0xFF] * padLength | 246 pad = [0xFF] * padLength |
249 elif blockType == 2: #Encryption padding | 247 elif blockType == 2: #Encryption padding |
250 pad = createByteArraySequence([]) | 248 pad = bytearray(0) |
251 while len(pad) < padLength: | 249 while len(pad) < padLength: |
252 padBytes = getRandomBytes(padLength * 2) | 250 padBytes = getRandomBytes(padLength * 2) |
253 pad = [b for b in padBytes if b != 0] | 251 pad = [b for b in padBytes if b != 0] |
254 pad = pad[:padLength] | 252 pad = pad[:padLength] |
255 else: | 253 else: |
256 raise AssertionError() | 254 raise AssertionError() |
257 | 255 |
258 #NOTE: To be proper, we should add [0,blockType]. However, | 256 padding = bytearray([0,blockType] + pad + [0]) |
259 #the zero is lost when the returned padding is converted | |
260 #to a number, so we don't even bother with it. Also, | |
261 #adding it would cause a misalignment in verify() | |
262 padding = createByteArraySequence([blockType] + pad + [0]) | |
263 paddedBytes = padding + bytes | 257 paddedBytes = padding + bytes |
264 return paddedBytes | 258 return paddedBytes |
OLD | NEW |