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  from . import tlshashlib as hashlib 
  8  from ..errors import MaskTooLongError, MessageTooLongError, EncodingError, \ 
  9      InvalidSignature, UnknownRSAType 
10 11 12 -class RSAKey(object):
13 """This is an abstract base class for RSA keys. 14 15 Particular implementations of RSA keys, such as 16 L{openssl_rsakey.OpenSSL_RSAKey}, 17 L{python_rsakey.Python_RSAKey}, and 18 L{pycrypto_rsakey.PyCrypto_RSAKey}, 19 inherit from this. 20 21 To create or parse an RSA key, don't use one of these classes 22 directly. Instead, use the factory functions in 23 L{tlslite.utils.keyfactory}. 24 """ 25
26 - def __init__(self, n=0, e=0):
27 """Create a new RSA key. 28 29 If n and e are passed in, the new key will be initialized. 30 31 @type n: int 32 @param n: RSA modulus. 33 34 @type e: int 35 @param e: RSA public exponent. 36 """ 37 raise NotImplementedError()
38
39 - def __len__(self):
40 """Return the length of this key in bits. 41 42 @rtype: int 43 """ 44 return numBits(self.n)
45
46 - def hasPrivateKey(self):
47 """Return whether or not this key has a private component. 48 49 @rtype: bool 50 """ 51 raise NotImplementedError()
52
53 - def hashAndSign(self, bytes, rsaScheme='PKCS1', hAlg='sha1', sLen=0):
54 """Hash and sign the passed-in bytes. 55 56 This requires the key to have a private component. It performs 57 a PKCS1 or PSS signature on the passed-in data with selected hash 58 algorithm. 59 60 @type bytes: str or L{bytearray} of unsigned bytes 61 @param bytes: The value which will be hashed and signed. 62 63 @type rsaScheme: str 64 @param rsaScheme: The type of RSA scheme that will be applied, 65 "PKCS1" for RSASSA-PKCS#1 v1.5 signature and "PSS" 66 for RSASSA-PSS with MGF1 signature method 67 68 @type hAlg: str 69 @param hAlg: The hash algorithm that will be used 70 71 @type sLen: int 72 @param sLen: The length of intended salt value, applicable only 73 for RSASSA-PSS signatures 74 75 @rtype: L{bytearray} of unsigned bytes. 76 @return: A PKCS1 or PSS signature on the passed-in data. 77 """ 78 if rsaScheme == "PKCS1": 79 hashBytes = secureHash(bytearray(bytes), hAlg) 80 prefixedHashBytes = self.addPKCS1Prefix(hashBytes, hAlg) 81 sigBytes = self.sign(prefixedHashBytes) 82 elif rsaScheme == "PSS": 83 sigBytes = self.RSASSA_PSS_sign(bytearray(bytes), hAlg, sLen) 84 else: 85 raise UnknownRSAType("Unknown RSA algorithm type") 86 return sigBytes
87
88 - def hashAndVerify(self, sigBytes, bytes, rsaScheme='PKCS1', hAlg='sha1', 89 sLen=0):
90 """Hash and verify the passed-in bytes with the signature. 91 92 This verifies a PKCS1 or PSS signature on the passed-in data 93 with selected hash algorithm. 94 95 @type sigBytes: L{bytearray} of unsigned bytes 96 @param sigBytes: A PKCS1 or PSS signature. 97 98 @type bytes: str or L{bytearray} of unsigned bytes 99 @param bytes: The value which will be hashed and verified. 100 101 @type rsaScheme: str 102 @param rsaScheme: The type of RSA scheme that will be applied, 103 "PKCS1" for RSASSA-PKCS#1 v1.5 signature and "PSS" 104 for RSASSA-PSS with MGF1 signature method 105 106 @type hAlg: str 107 @param hAlg: The hash algorithm that will be used 108 109 @type sLen: int 110 @param sLen: The length of intended salt value, applicable only 111 for RSASSA-PSS signatures 112 113 @rtype: bool 114 @return: Whether the signature matches the passed-in data. 115 """ 116 117 # Try it with/without the embedded NULL 118 if rsaScheme == "PKCS1" and hAlg == 'sha1': 119 hashBytes = secureHash(bytearray(bytes), hAlg) 120 prefixedHashBytes1 = self.addPKCS1SHA1Prefix(hashBytes, False) 121 prefixedHashBytes2 = self.addPKCS1SHA1Prefix(hashBytes, True) 122 result1 = self.verify(sigBytes, prefixedHashBytes1) 123 result2 = self.verify(sigBytes, prefixedHashBytes2) 124 return (result1 or result2) 125 elif rsaScheme == 'PKCS1': 126 hashBytes = secureHash(bytearray(bytes), hAlg) 127 prefixedHashBytes = self.addPKCS1Prefix(hashBytes, hAlg) 128 r = self.verify(sigBytes, prefixedHashBytes) 129 return r 130 elif rsaScheme == "PSS": 131 r = self.RSASSA_PSS_verify(bytearray(bytes), sigBytes, hAlg, sLen) 132 return r 133 else: 134 raise UnknownRSAType("Unknown RSA algorithm type")
135
136 - def MGF1(self, mgfSeed, maskLen, hAlg):
137 """Generate mask from passed-in seed. 138 139 This generates mask based on passed-in seed and output maskLen. 140 141 @type mgfSeed: L{bytearray} 142 @param mgfSeed: Seed from which mask will be generated. 143 144 @type maskLen: int 145 @param maskLen: Wished length of the mask, in octets 146 147 @rtype: L{bytearray} 148 @return: Mask 149 """ 150 hashLen = getattr(hashlib, hAlg)().digest_size 151 if maskLen > (2 ** 32) * hashLen: 152 raise MaskTooLongError("Incorrect parameter maskLen") 153 T = bytearray() 154 end = divceil(maskLen, hashLen) 155 for x in range(0, end): 156 C = numberToByteArray(x, 4) 157 T += secureHash(mgfSeed + C, hAlg) 158 return T[:maskLen]
159
160 - def EMSA_PSS_encode(self, M, emBits, hAlg, sLen=0):
161 """Encode the passed in message 162 163 This encodes the message using selected hash algorithm 164 165 @type M: bytearray 166 @param M: Message to be encoded 167 168 @type emBits: int 169 @param emBits: maximal length of returned EM 170 171 @type hAlg: str 172 @param hAlg: hash algorithm to be used 173 174 @type sLen: int 175 @param sLen: length of salt""" 176 hashLen = getattr(hashlib, hAlg)().digest_size 177 mHash = secureHash(M, hAlg) 178 emLen = divceil(emBits, 8) 179 if emLen < hashLen + sLen + 2: 180 raise EncodingError("The ending limit too short for " + 181 "selected hash and salt length") 182 salt = getRandomBytes(sLen) 183 M2 = bytearray(8) + mHash + salt 184 H = secureHash(M2, hAlg) 185 PS = bytearray(emLen - sLen - hashLen - 2) 186 DB = PS + bytearray(b'\x01') + salt 187 dbMask = self.MGF1(H, emLen - hashLen - 1, hAlg) 188 maskedDB = bytearray(i ^ j for i, j in zip(DB, dbMask)) 189 mLen = emLen*8 - emBits 190 mask = (1 << 8 - mLen) - 1 191 maskedDB[0] &= mask 192 EM = maskedDB + H + bytearray(b'\xbc') 193 return EM
194
195 - def RSASSA_PSS_sign(self, M, hAlg, sLen=0):
196 """"Sign the passed in message 197 198 This signs the message using selected hash algorithm 199 200 @type M: bytearray 201 @param M: Message to be signed 202 203 @type hAlg: str 204 @param hAlg: hash algorithm to be used 205 206 @type sLen: int 207 @param sLen: length of salt""" 208 EM = self.EMSA_PSS_encode(M, numBits(self.n) - 1, hAlg, sLen) 209 m = bytesToNumber(EM) 210 if m >= self.n: 211 raise MessageTooLongError("Encode output too long") 212 s = self._rawPrivateKeyOp(m) 213 S = numberToByteArray(s, numBytes(self.n)) 214 return S
215
216 - def EMSA_PSS_verify(self, M, EM, emBits, hAlg, sLen=0):
217 """Verify signature in passed in encoded message 218 219 This verifies the signature in encoded message 220 221 @type M: bytearray 222 @param M: Original not signed message 223 224 @type EM: bytearray 225 @param EM: Encoded message 226 227 @type emBits: int 228 @param emBits: Length of the encoded message in bits 229 230 @type hAlg: str 231 @param hAlg: hash algorithm to be used 232 233 @type sLen: int 234 @param sLen: Length of salt 235 """ 236 hashLen = getattr(hashlib, hAlg)().digest_size 237 mHash = secureHash(M, hAlg) 238 emLen = divceil(emBits, 8) 239 if emLen < hashLen + sLen + 2: 240 raise InvalidSignature("Invalid signature") 241 if EM[-1] != 0xbc: 242 raise InvalidSignature("Invalid signature") 243 maskedDB = EM[0:emLen - hashLen - 1] 244 H = EM[emLen - hashLen - 1:emLen - hashLen - 1 + hashLen] 245 DBHelpMask = 1 << 8 - (8*emLen - emBits) 246 DBHelpMask -= 1 247 DBHelpMask = (~DBHelpMask) & 0xff 248 if maskedDB[0] & DBHelpMask != 0: 249 raise InvalidSignature("Invalid signature") 250 dbMask = self.MGF1(H, emLen - hashLen - 1, hAlg) 251 DB = bytearray(i ^ j for i, j in zip(maskedDB, dbMask)) 252 mLen = emLen*8 - emBits 253 mask = (1 << 8 - mLen) - 1 254 DB[0] &= mask 255 if any(x != 0 for x in DB[0:emLen - hashLen - sLen - 2 - 1]): 256 raise InvalidSignature("Invalid signature") 257 if DB[emLen - hashLen - sLen - 2] != 0x01: 258 raise InvalidSignature("Invalid signature") 259 if sLen != 0: 260 salt = DB[-sLen:] 261 else: 262 salt = bytearray() 263 newM = bytearray(8) + mHash + salt 264 newH = secureHash(newM, hAlg) 265 if H == newH: 266 return True 267 else: 268 raise InvalidSignature("Invalid signature")
269
270 - def RSASSA_PSS_verify(self, M, S, hAlg, sLen=0):
271 """Verify the signature in passed in message 272 273 This verifies the signature in the signed message 274 275 @type M: bytearray 276 @param M: Original message 277 278 @type S: bytearray 279 @param S: Signed message 280 281 @type hAlg: str 282 @param hAlg: Hash algorithm to be used 283 284 @type sLen: int 285 @param sLen: Length of salt 286 """ 287 if len(bytearray(S)) != len(numberToByteArray(self.n)): 288 raise InvalidSignature 289 s = bytesToNumber(S) 290 m = self._rawPublicKeyOp(s) 291 EM = numberToByteArray(m, divceil(numBits(self.n) - 1, 8)) 292 result = self.EMSA_PSS_verify(M, EM, numBits(self.n) - 1, hAlg, sLen) 293 if result: 294 return True 295 else: 296 raise InvalidSignature("Invalid signature")
297
298 - def sign(self, bytes):
299 """Sign the passed-in bytes. 300 301 This requires the key to have a private component. It performs 302 a PKCS1 signature on the passed-in data. 303 304 @type bytes: L{bytearray} of unsigned bytes 305 @param bytes: The value which will be signed. 306 307 @rtype: L{bytearray} of unsigned bytes. 308 @return: A PKCS1 signature on the passed-in data. 309 """ 310 if not self.hasPrivateKey(): 311 raise AssertionError() 312 paddedBytes = self._addPKCS1Padding(bytes, 1) 313 m = bytesToNumber(paddedBytes) 314 if m >= self.n: 315 raise ValueError() 316 c = self._rawPrivateKeyOp(m) 317 sigBytes = numberToByteArray(c, numBytes(self.n)) 318 return sigBytes
319
320 - def verify(self, sigBytes, bytes):
321 """Verify the passed-in bytes with the signature. 322 323 This verifies a PKCS1 signature on the passed-in data. 324 325 @type sigBytes: L{bytearray} of unsigned bytes 326 @param sigBytes: A PKCS1 signature. 327 328 @type bytes: L{bytearray} of unsigned bytes 329 @param bytes: The value which will be verified. 330 331 @rtype: bool 332 @return: Whether the signature matches the passed-in data. 333 """ 334 if len(sigBytes) != numBytes(self.n): 335 return False 336 paddedBytes = self._addPKCS1Padding(bytes, 1) 337 c = bytesToNumber(sigBytes) 338 if c >= self.n: 339 return False 340 m = self._rawPublicKeyOp(c) 341 checkBytes = numberToByteArray(m, numBytes(self.n)) 342 return checkBytes == paddedBytes
343
344 - def encrypt(self, bytes):
345 """Encrypt the passed-in bytes. 346 347 This performs PKCS1 encryption of the passed-in data. 348 349 @type bytes: L{bytearray} of unsigned bytes 350 @param bytes: The value which will be encrypted. 351 352 @rtype: L{bytearray} of unsigned bytes. 353 @return: A PKCS1 encryption of the passed-in data. 354 """ 355 paddedBytes = self._addPKCS1Padding(bytes, 2) 356 m = bytesToNumber(paddedBytes) 357 if m >= self.n: 358 raise ValueError() 359 c = self._rawPublicKeyOp(m) 360 encBytes = numberToByteArray(c, numBytes(self.n)) 361 return encBytes
362
363 - def decrypt(self, encBytes):
364 """Decrypt the passed-in bytes. 365 366 This requires the key to have a private component. It performs 367 PKCS1 decryption of the passed-in data. 368 369 @type encBytes: L{bytearray} of unsigned bytes 370 @param encBytes: The value which will be decrypted. 371 372 @rtype: L{bytearray} of unsigned bytes or None. 373 @return: A PKCS1 decryption of the passed-in data or None if 374 the data is not properly formatted. 375 """ 376 if not self.hasPrivateKey(): 377 raise AssertionError() 378 if len(encBytes) != numBytes(self.n): 379 return None 380 c = bytesToNumber(encBytes) 381 if c >= self.n: 382 return None 383 m = self._rawPrivateKeyOp(c) 384 decBytes = numberToByteArray(m, numBytes(self.n)) 385 #Check first two bytes 386 if decBytes[0] != 0 or decBytes[1] != 2: 387 return None 388 #Scan through for zero separator 389 for x in range(1, len(decBytes)-1): 390 if decBytes[x]== 0: 391 break 392 else: 393 return None 394 return decBytes[x+1:] #Return everything after the separator
395
396 - def _rawPrivateKeyOp(self, m):
397 raise NotImplementedError()
398
399 - def _rawPublicKeyOp(self, c):
400 raise NotImplementedError()
401
402 - def acceptsPassword(self):
403 """Return True if the write() method accepts a password for use 404 in encrypting the private key. 405 406 @rtype: bool 407 """ 408 raise NotImplementedError()
409
410 - def write(self, password=None):
411 """Return a string containing the key. 412 413 @rtype: str 414 @return: A string describing the key, in whichever format (PEM) 415 is native to the implementation. 416 """ 417 raise NotImplementedError()
418
419 - def generate(bits):
420 """Generate a new key with the specified bit length. 421 422 @rtype: L{tlslite.utils.RSAKey.RSAKey} 423 """ 424 raise NotImplementedError()
425 generate = staticmethod(generate) 426 427 428 # ************************************************************************** 429 # Helper Functions for RSA Keys 430 # ************************************************************************** 431 432 @classmethod
433 - def addPKCS1SHA1Prefix(cls, hashBytes, withNULL=True):
434 """Add PKCS#1 v1.5 algorithm identifier prefix to SHA1 hash bytes""" 435 # There is a long history of confusion over whether the SHA1 436 # algorithmIdentifier should be encoded with a NULL parameter or 437 # with the parameter omitted. While the original intention was 438 # apparently to omit it, many toolkits went the other way. TLS 1.2 439 # specifies the NULL should be included, and this behavior is also 440 # mandated in recent versions of PKCS #1, and is what tlslite has 441 # always implemented. Anyways, verification code should probably 442 # accept both. 443 if not withNULL: 444 prefixBytes = bytearray([0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 445 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14]) 446 else: 447 prefixBytes = cls._pkcs1Prefixes['sha1'] 448 prefixedBytes = prefixBytes + hashBytes 449 return prefixedBytes
450 451 _pkcs1Prefixes = {'md5' : bytearray([0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 452 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 453 0x02, 0x05, 0x05, 0x00, 0x04, 0x10]), 454 'sha1' : bytearray([0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 455 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 456 0x00, 0x04, 0x14]), 457 'sha224' : bytearray([0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 458 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 459 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 460 0x1c]), 461 'sha256' : bytearray([0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 462 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 463 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 464 0x20]), 465 'sha384' : bytearray([0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 466 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 467 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 468 0x30]), 469 'sha512' : bytearray([0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 470 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 471 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 472 0x40])} 473 474 @classmethod
475 - def addPKCS1Prefix(cls, data, hashName):
476 """Add the PKCS#1 v1.5 algorithm identifier prefix to hash bytes""" 477 hashName = hashName.lower() 478 assert hashName in cls._pkcs1Prefixes 479 prefixBytes = cls._pkcs1Prefixes[hashName] 480 return prefixBytes + data
481
482 - def _addPKCS1Padding(self, bytes, blockType):
483 padLength = (numBytes(self.n) - (len(bytes)+3)) 484 if blockType == 1: #Signature padding 485 pad = [0xFF] * padLength 486 elif blockType == 2: #Encryption padding 487 pad = bytearray(0) 488 while len(pad) < padLength: 489 padBytes = getRandomBytes(padLength * 2) 490 pad = [b for b in padBytes if b != 0] 491 pad = pad[:padLength] 492 else: 493 raise AssertionError() 494 495 padding = bytearray([0,blockType] + pad + [0]) 496 paddedBytes = padding + bytes 497 return paddedBytes
498