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:
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 if not isinstance(bytes, type("")): 63 bytes = bytesToString(bytes) 64 hashBytes = stringToBytes(sha1(bytes).digest()) 65 prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) 66 sigBytes = self.sign(prefixedHashBytes) 67 return sigBytes
68
69 - def hashAndVerify(self, sigBytes, bytes):
70 """Hash and verify the passed-in bytes with the signature. 71 72 This verifies a PKCS1-SHA1 signature on the passed-in data. 73 74 @type sigBytes: L{bytearray} of unsigned bytes 75 @param sigBytes: A PKCS1-SHA1 signature. 76 77 @type bytes: str or L{bytearray} of unsigned bytes 78 @param bytes: The value which will be hashed and verified. 79 80 @rtype: bool 81 @return: Whether the signature matches the passed-in data. 82 """ 83 if not isinstance(bytes, type("")): 84 bytes = bytesToString(bytes) 85 hashBytes = stringToBytes(sha1(bytes).digest()) 86 prefixedHashBytes = self._addPKCS1SHA1Prefix(hashBytes) 87 return self.verify(sigBytes, prefixedHashBytes)
88
89 - def sign(self, bytes):
90 """Sign the passed-in bytes. 91 92 This requires the key to have a private component. It performs 93 a PKCS1 signature on the passed-in data. 94 95 @type bytes: L{bytearray} of unsigned bytes 96 @param bytes: The value which will be signed. 97 98 @rtype: L{bytearray} of unsigned bytes. 99 @return: A PKCS1 signature on the passed-in data. 100 """ 101 if not self.hasPrivateKey(): 102 raise AssertionError() 103 paddedBytes = self._addPKCS1Padding(bytes, 1) 104 m = bytesToNumber(paddedBytes) 105 if m >= self.n: 106 raise ValueError() 107 c = self._rawPrivateKeyOp(m) 108 sigBytes = numberToBytes(c) 109 return sigBytes
110
111 - def verify(self, sigBytes, bytes):
112 """Verify the passed-in bytes with the signature. 113 114 This verifies a PKCS1 signature on the passed-in data. 115 116 @type sigBytes: L{bytearray} of unsigned bytes 117 @param sigBytes: A PKCS1 signature. 118 119 @type bytes: L{bytearray} of unsigned bytes 120 @param bytes: The value which will be verified. 121 122 @rtype: bool 123 @return: Whether the signature matches the passed-in data. 124 """ 125 paddedBytes = self._addPKCS1Padding(bytes, 1) 126 c = bytesToNumber(sigBytes) 127 if c >= self.n: 128 return False 129 m = self._rawPublicKeyOp(c) 130 checkBytes = numberToBytes(m) 131 return checkBytes == paddedBytes
132
133 - def encrypt(self, bytes):
134 """Encrypt the passed-in bytes. 135 136 This performs PKCS1 encryption of the passed-in data. 137 138 @type bytes: L{bytearray} of unsigned bytes 139 @param bytes: The value which will be encrypted. 140 141 @rtype: L{bytearray} of unsigned bytes. 142 @return: A PKCS1 encryption of the passed-in data. 143 """ 144 paddedBytes = self._addPKCS1Padding(bytes, 2) 145 m = bytesToNumber(paddedBytes) 146 if m >= self.n: 147 raise ValueError() 148 c = self._rawPublicKeyOp(m) 149 encBytes = numberToBytes(c) 150 return encBytes
151
152 - def decrypt(self, encBytes):
153 """Decrypt the passed-in bytes. 154 155 This requires the key to have a private component. It performs 156 PKCS1 decryption of the passed-in data. 157 158 @type encBytes: L{bytearray} of unsigned bytes 159 @param encBytes: The value which will be decrypted. 160 161 @rtype: L{bytearray} of unsigned bytes or None. 162 @return: A PKCS1 decryption of the passed-in data or None if 163 the data is not properly formatted. 164 """ 165 if not self.hasPrivateKey(): 166 raise AssertionError() 167 c = bytesToNumber(encBytes) 168 if c >= self.n: 169 return None 170 m = self._rawPrivateKeyOp(c) 171 decBytes = numberToBytes(m) 172 if (len(decBytes) != numBytes(self.n)-1): #Check first byte 173 return None 174 if decBytes[0] != 2: #Check second byte 175 return None 176 for x in range(len(decBytes)-1): #Scan through for zero separator 177 if decBytes[x]== 0: 178 break 179 else: 180 return None 181 return decBytes[x+1:] #Return everything after the separator
182
183 - def _rawPrivateKeyOp(self, m):
184 raise NotImplementedError()
185
186 - def _rawPublicKeyOp(self, c):
187 raise NotImplementedError()
188
189 - def acceptsPassword(self):
190 """Return True if the write() method accepts a password for use 191 in encrypting the private key. 192 193 @rtype: bool 194 """ 195 raise NotImplementedError()
196
197 - def write(self, password=None):
198 """Return a string containing the key. 199 200 @rtype: str 201 @return: A string describing the key, in whichever format (PEM) 202 is native to the implementation. 203 """ 204 raise NotImplementedError()
205
206 - def generate(bits):
207 """Generate a new key with the specified bit length. 208 209 @rtype: L{tlslite.utils.RSAKey.RSAKey} 210 """ 211 raise NotImplementedError()
212 generate = staticmethod(generate) 213 214 215 # ************************************************************************** 216 # Helper Functions for RSA Keys 217 # ************************************************************************** 218
219 - def _addPKCS1SHA1Prefix(self, bytes, withNULL=False):
220 # There is a long history of confusion over whether the SHA1 221 # algorithmIdentifier should be encoded with a NULL parameter or 222 # with the parameter omitted. While the original intention was 223 # apparently to omit it, many toolkits went the other way. TLS 1.2 224 # specifies the NULL should be omitted, so maybe the pendulum is 225 # swinging back towards the original intention. Anyways, verification 226 # code should accept both, so the above hashAndVerify() is not 227 # yet correct. However, nothing uses this code yet - an eventual 228 # TLS 1.2 implementation will have to fix that. 229 if not withNULL: 230 prefixBytes = createByteArraySequence(\ 231 [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14]) 232 else: 233 prefixBytes = createByteArraySequence(\ 234 [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14]) 235 prefixedBytes = prefixBytes + bytes 236 return prefixedBytes
237
238 - def _addPKCS1Padding(self, bytes, blockType):
239 padLength = (numBytes(self.n) - (len(bytes)+3)) 240 if blockType == 1: #Signature padding 241 pad = [0xFF] * padLength 242 elif blockType == 2: #Encryption padding 243 pad = createByteArraySequence([]) 244 while len(pad) < padLength: 245 padBytes = getRandomBytes(padLength * 2) 246 pad = [b for b in padBytes if b != 0] 247 pad = pad[:padLength] 248 else: 249 raise AssertionError() 250 251 #NOTE: To be proper, we should add [0,blockType]. However, 252 #the zero is lost when the returned padding is converted 253 #to a number, so we don't even bother with it. Also, 254 #adding it would cause a misalignment in verify() 255 padding = createByteArraySequence([blockType] + pad + [0]) 256 paddedBytes = padding + bytes 257 return paddedBytes
258