1
2
3
4 """Abstract class for RSA."""
5
6 from .cryptomath import *
10 """This is an abstract base class for RSA keys.
11
12 Particular implementations of RSA keys, such as
13 L{openssl_rsakey.OpenSSL_RSAKey},
14 L{python_rsakey.Python_RSAKey}, and
15 L{pycrypto_rsakey.PyCrypto_RSAKey},
16 inherit from this.
17
18 To create or parse an RSA key, don't use one of these classes
19 directly. Instead, use the factory functions in
20 L{tlslite.utils.keyfactory}.
21 """
22
24 """Create a new RSA key.
25
26 If n and e are passed in, the new key will be initialized.
27
28 @type n: int
29 @param n: RSA modulus.
30
31 @type e: int
32 @param e: RSA public exponent.
33 """
34 raise NotImplementedError()
35
37 """Return the length of this key in bits.
38
39 @rtype: int
40 """
41 return numBits(self.n)
42
44 """Return whether or not this key has a private component.
45
46 @rtype: bool
47 """
48 raise NotImplementedError()
49
51 """Hash and sign the passed-in bytes.
52
53 This requires the key to have a private component. It performs
54 a PKCS1-SHA1 signature on the passed-in data.
55
56 @type bytes: str or L{bytearray} of unsigned bytes
57 @param bytes: The value which will be hashed and signed.
58
59 @rtype: L{bytearray} of unsigned bytes.
60 @return: A PKCS1-SHA1 signature on the passed-in data.
61 """
62 hashBytes = SHA1(bytearray(bytes))
63 prefixedHashBytes = self.addPKCS1SHA1Prefix(hashBytes)
64 sigBytes = self.sign(prefixedHashBytes)
65 return sigBytes
66
68 """Hash and verify the passed-in bytes with the signature.
69
70 This verifies a PKCS1-SHA1 signature on the passed-in data.
71
72 @type sigBytes: L{bytearray} of unsigned bytes
73 @param sigBytes: A PKCS1-SHA1 signature.
74
75 @type bytes: str or L{bytearray} of unsigned bytes
76 @param bytes: The value which will be hashed and verified.
77
78 @rtype: bool
79 @return: Whether the signature matches the passed-in data.
80 """
81 hashBytes = SHA1(bytearray(bytes))
82
83
84 prefixedHashBytes1 = self.addPKCS1SHA1Prefix(hashBytes, False)
85 prefixedHashBytes2 = self.addPKCS1SHA1Prefix(hashBytes, True)
86 result1 = self.verify(sigBytes, prefixedHashBytes1)
87 result2 = self.verify(sigBytes, prefixedHashBytes2)
88 return (result1 or result2)
89
90 - def sign(self, bytes):
91 """Sign the passed-in bytes.
92
93 This requires the key to have a private component. It performs
94 a PKCS1 signature on the passed-in data.
95
96 @type bytes: L{bytearray} of unsigned bytes
97 @param bytes: The value which will be signed.
98
99 @rtype: L{bytearray} of unsigned bytes.
100 @return: A PKCS1 signature on the passed-in data.
101 """
102 if not self.hasPrivateKey():
103 raise AssertionError()
104 paddedBytes = self._addPKCS1Padding(bytes, 1)
105 m = bytesToNumber(paddedBytes)
106 if m >= self.n:
107 raise ValueError()
108 c = self._rawPrivateKeyOp(m)
109 sigBytes = numberToByteArray(c, numBytes(self.n))
110 return sigBytes
111
112 - def verify(self, sigBytes, bytes):
113 """Verify the passed-in bytes with the signature.
114
115 This verifies a PKCS1 signature on the passed-in data.
116
117 @type sigBytes: L{bytearray} of unsigned bytes
118 @param sigBytes: A PKCS1 signature.
119
120 @type bytes: L{bytearray} of unsigned bytes
121 @param bytes: The value which will be verified.
122
123 @rtype: bool
124 @return: Whether the signature matches the passed-in data.
125 """
126 if len(sigBytes) != numBytes(self.n):
127 return False
128 paddedBytes = self._addPKCS1Padding(bytes, 1)
129 c = bytesToNumber(sigBytes)
130 if c >= self.n:
131 return False
132 m = self._rawPublicKeyOp(c)
133 checkBytes = numberToByteArray(m, numBytes(self.n))
134 return checkBytes == paddedBytes
135
137 """Encrypt the passed-in bytes.
138
139 This performs PKCS1 encryption of the passed-in data.
140
141 @type bytes: L{bytearray} of unsigned bytes
142 @param bytes: The value which will be encrypted.
143
144 @rtype: L{bytearray} of unsigned bytes.
145 @return: A PKCS1 encryption of the passed-in data.
146 """
147 paddedBytes = self._addPKCS1Padding(bytes, 2)
148 m = bytesToNumber(paddedBytes)
149 if m >= self.n:
150 raise ValueError()
151 c = self._rawPublicKeyOp(m)
152 encBytes = numberToByteArray(c, numBytes(self.n))
153 return encBytes
154
156 """Decrypt the passed-in bytes.
157
158 This requires the key to have a private component. It performs
159 PKCS1 decryption of the passed-in data.
160
161 @type encBytes: L{bytearray} of unsigned bytes
162 @param encBytes: The value which will be decrypted.
163
164 @rtype: L{bytearray} of unsigned bytes or None.
165 @return: A PKCS1 decryption of the passed-in data or None if
166 the data is not properly formatted.
167 """
168 if not self.hasPrivateKey():
169 raise AssertionError()
170 if len(encBytes) != numBytes(self.n):
171 return None
172 c = bytesToNumber(encBytes)
173 if c >= self.n:
174 return None
175 m = self._rawPrivateKeyOp(c)
176 decBytes = numberToByteArray(m, numBytes(self.n))
177
178 if decBytes[0] != 0 or decBytes[1] != 2:
179 return None
180
181 for x in range(1, len(decBytes)-1):
182 if decBytes[x]== 0:
183 break
184 else:
185 return None
186 return decBytes[x+1:]
187
189 raise NotImplementedError()
190
192 raise NotImplementedError()
193
195 """Return True if the write() method accepts a password for use
196 in encrypting the private key.
197
198 @rtype: bool
199 """
200 raise NotImplementedError()
201
202 - def write(self, password=None):
203 """Return a string containing the key.
204
205 @rtype: str
206 @return: A string describing the key, in whichever format (PEM)
207 is native to the implementation.
208 """
209 raise NotImplementedError()
210
212 """Generate a new key with the specified bit length.
213
214 @rtype: L{tlslite.utils.RSAKey.RSAKey}
215 """
216 raise NotImplementedError()
217 generate = staticmethod(generate)
218
219
220
221
222
223
224 @classmethod
226 """Add PKCS#1 v1.5 algorithm identifier prefix to SHA1 hash bytes"""
227
228
229
230
231
232
233
234
235 if not withNULL:
236 prefixBytes = bytearray([0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b,
237 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14])
238 else:
239 prefixBytes = cls._pkcs1Prefixes['sha1']
240 prefixedBytes = prefixBytes + hashBytes
241 return prefixedBytes
242
243 _pkcs1Prefixes = {'md5' : bytearray([0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
244 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
245 0x02, 0x05, 0x05, 0x00, 0x04, 0x10]),
246 'sha1' : bytearray([0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
247 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
248 0x00, 0x04, 0x14]),
249 'sha224' : bytearray([0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
250 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
251 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
252 0x1c]),
253 'sha256' : bytearray([0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
254 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
255 0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
256 0x20]),
257 'sha384' : bytearray([0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
258 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
259 0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
260 0x30]),
261 'sha512' : bytearray([0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
262 0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
263 0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
264 0x40])}
265
266 @classmethod
268 """Add the PKCS#1 v1.5 algorithm identifier prefix to hash bytes"""
269 hashName = hashName.lower()
270 assert hashName in cls._pkcs1Prefixes
271 prefixBytes = cls._pkcs1Prefixes[hashName]
272 return prefixBytes + data
273
275 padLength = (numBytes(self.n) - (len(bytes)+3))
276 if blockType == 1:
277 pad = [0xFF] * padLength
278 elif blockType == 2:
279 pad = bytearray(0)
280 while len(pad) < padLength:
281 padBytes = getRandomBytes(padLength * 2)
282 pad = [b for b in padBytes if b != 0]
283 pad = pad[:padLength]
284 else:
285 raise AssertionError()
286
287 padding = bytearray([0,blockType] + pad + [0])
288 paddedBytes = padding + bytes
289 return paddedBytes
290