1 # Author: Trevor Perrin
2 # See the LICENSE file for legal information regarding use of this file.
4 """Abstract class for RSA."""
6 from .cryptomath import *
10 """This is an abstract base class for RSA keys.
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},
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}.
23 def __init__(self, n=0, e=0):
24 """Create a new RSA key.
26 If n and e are passed in, the new key will be initialized.
29 @param n: RSA modulus.
32 @param e: RSA public exponent.
34 raise NotImplementedError()
37 """Return the length of this key in bits.
41 return numBits(self.n)
43 def hasPrivateKey(self):
44 """Return whether or not this key has a private component.
48 raise NotImplementedError()
50 def hashAndSign(self, bytes):
51 """Hash and sign the passed-in bytes.
53 This requires the key to have a private component. It performs
54 a PKCS1-SHA1 signature on the passed-in data.
56 @type bytes: str or L{bytearray} of unsigned bytes
57 @param bytes: The value which will be hashed and signed.
59 @rtype: L{bytearray} of unsigned bytes.
60 @return: A PKCS1-SHA1 signature on the passed-in data.
62 hashBytes = SHA1(bytearray(bytes))
63 prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes)
64 sigBytes = self.sign(prefixedHashBytes)
67 def hashAndVerify(self, sigBytes, bytes):
68 """Hash and verify the passed-in bytes with the signature.
70 This verifies a PKCS1-SHA1 signature on the passed-in data.
72 @type sigBytes: L{bytearray} of unsigned bytes
73 @param sigBytes: A PKCS1-SHA1 signature.
75 @type bytes: str or L{bytearray} of unsigned bytes
76 @param bytes: The value which will be hashed and verified.
79 @return: Whether the signature matches the passed-in data.
81 hashBytes = SHA1(bytearray(bytes))
83 # Try it with/without the embedded NULL
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)
90 def sign(self, bytes):
91 """Sign the passed-in bytes.
93 This requires the key to have a private component. It performs
94 a PKCS1 signature on the passed-in data.
96 @type bytes: L{bytearray} of unsigned bytes
97 @param bytes: The value which will be signed.
99 @rtype: L{bytearray} of unsigned bytes.
100 @return: A PKCS1 signature on the passed-in data.
102 if not self.hasPrivateKey():
103 raise AssertionError()
104 paddedBytes = self._addPKCS1Padding(bytes, 1)
105 m = bytesToNumber(paddedBytes)
108 c = self._rawPrivateKeyOp(m)
109 sigBytes = numberToByteArray(c, numBytes(self.n))
112 def verify(self, sigBytes, bytes):
113 """Verify the passed-in bytes with the signature.
115 This verifies a PKCS1 signature on the passed-in data.
117 @type sigBytes: L{bytearray} of unsigned bytes
118 @param sigBytes: A PKCS1 signature.
120 @type bytes: L{bytearray} of unsigned bytes
121 @param bytes: The value which will be verified.
124 @return: Whether the signature matches the passed-in data.
126 if len(sigBytes) != numBytes(self.n):
128 paddedBytes = self._addPKCS1Padding(bytes, 1)
129 c = bytesToNumber(sigBytes)
132 m = self._rawPublicKeyOp(c)
133 checkBytes = numberToByteArray(m, numBytes(self.n))
134 return checkBytes == paddedBytes
136 def encrypt(self, bytes):
137 """Encrypt the passed-in bytes.
139 This performs PKCS1 encryption of the passed-in data.
141 @type bytes: L{bytearray} of unsigned bytes
142 @param bytes: The value which will be encrypted.
144 @rtype: L{bytearray} of unsigned bytes.
145 @return: A PKCS1 encryption of the passed-in data.
147 paddedBytes = self._addPKCS1Padding(bytes, 2)
148 m = bytesToNumber(paddedBytes)
151 c = self._rawPublicKeyOp(m)
152 encBytes = numberToByteArray(c, numBytes(self.n))
155 def decrypt(self, encBytes):
156 """Decrypt the passed-in bytes.
158 This requires the key to have a private component. It performs
159 PKCS1 decryption of the passed-in data.
161 @type encBytes: L{bytearray} of unsigned bytes
162 @param encBytes: The value which will be decrypted.
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.
168 if not self.hasPrivateKey():
169 raise AssertionError()
170 if len(encBytes) != numBytes(self.n):
172 c = bytesToNumber(encBytes)
175 m = self._rawPrivateKeyOp(c)
176 decBytes = numberToByteArray(m, numBytes(self.n))
177 #Check first two bytes
178 if decBytes[0] != 0 or decBytes[1] != 2:
180 #Scan through for zero separator
181 for x in range(1, len(decBytes)-1):
186 return decBytes[x+1:] #Return everything after the separator
188 def _rawPrivateKeyOp(self, m):
189 raise NotImplementedError()
191 def _rawPublicKeyOp(self, c):
192 raise NotImplementedError()
194 def acceptsPassword(self):
195 """Return True if the write() method accepts a password for use
196 in encrypting the private key.
200 raise NotImplementedError()
202 def write(self, password=None):
203 """Return a string containing the key.
206 @return: A string describing the key, in whichever format (PEM)
207 is native to the implementation.
209 raise NotImplementedError()
212 """Generate a new key with the specified bit length.
214 @rtype: L{tlslite.utils.RSAKey.RSAKey}
216 raise NotImplementedError()
217 generate = staticmethod(generate)
220 # **************************************************************************
221 # Helper Functions for RSA Keys
222 # **************************************************************************
224 def _addPKCS1SHA1Prefix(self, bytes, withNULL=True):
225 # There is a long history of confusion over whether the SHA1
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
235 prefixBytes = bytearray(\
236 [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])
238 prefixBytes = bytearray(\
239 [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14])
240 prefixedBytes = prefixBytes + bytes
243 def _addPKCS1Padding(self, bytes, blockType):
244 padLength = (numBytes(self.n) - (len(bytes)+3))
245 if blockType == 1: #Signature padding
246 pad = [0xFF] * padLength
247 elif blockType == 2: #Encryption padding
249 while len(pad) < padLength:
250 padBytes = getRandomBytes(padLength * 2)
251 pad = [b for b in padBytes if b != 0]
252 pad = pad[:padLength]
254 raise AssertionError()
256 padding = bytearray([0,blockType] + pad + [0])
257 paddedBytes = padding + bytes