Package tlslite :: Package utils :: Module rsakey
[hide private]
[frames] | no frames]

Source Code for Module tlslite.utils.rsakey

  1  # Author: Trevor Perrin 
  2  # See the LICENSE file for legal information regarding use of this file. 
  3   
  4  """Abstract class for RSA.""" 
  5   
  6  from .cryptomath import * 
7 8 9 -class RSAKey(object):
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
23 - def __init__(self, n=0, e=0):
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
36 - def __len__(self):
37 """Return the length of this key in bits. 38 39 @rtype: int 40 """ 41 return numBits(self.n)
42
43 - def hasPrivateKey(self):
44 """Return whether or not this key has a private component. 45 46 @rtype: bool 47 """ 48 raise NotImplementedError()
49
50 - def hashAndSign(self, bytes):
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
67 - def hashAndVerify(self, sigBytes, bytes):
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 # 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)
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
136 - def encrypt(self, bytes):
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
155 - def decrypt(self, encBytes):
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 #Check first two bytes 178 if decBytes[0] != 0 or decBytes[1] != 2: 179 return None 180 #Scan through for zero separator 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:] #Return everything after the separator
187
188 - def _rawPrivateKeyOp(self, m):
189 raise NotImplementedError()
190
191 - def _rawPublicKeyOp(self, c):
192 raise NotImplementedError()
193
194 - def acceptsPassword(self):
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
211 - def generate(bits):
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 # Helper Functions for RSA Keys 222 # ************************************************************************** 223 224 @classmethod
225 - def addPKCS1SHA1Prefix(cls, hashBytes, withNULL=True):
226 """Add PKCS#1 v1.5 algorithm identifier prefix to SHA1 hash bytes""" 227 # There is a long history of confusion over whether the SHA1 228 # algorithmIdentifier should be encoded with a NULL parameter or 229 # with the parameter omitted. While the original intention was 230 # apparently to omit it, many toolkits went the other way. TLS 1.2 231 # specifies the NULL should be included, and this behavior is also 232 # mandated in recent versions of PKCS #1, and is what tlslite has 233 # always implemented. Anyways, verification code should probably 234 # accept both. 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
267 - def addPKCS1Prefix(cls, data, hashName):
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
274 - def _addPKCS1Padding(self, bytes, blockType):
275 padLength = (numBytes(self.n) - (len(bytes)+3)) 276 if blockType == 1: #Signature padding 277 pad = [0xFF] * padLength 278 elif blockType == 2: #Encryption padding 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