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 -    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
    233          # all fairly moot.
    234          if not withNULL:
    235              prefixBytes = bytearray(\
    236              [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])
    237          else:
    238              prefixBytes = bytearray(\
    239              [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14])
    240          prefixedBytes = prefixBytes + bytes
    241          return prefixedBytes
    242
    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
    248              pad = bytearray(0)
    249              while len(pad) < padLength:
    250                  padBytes = getRandomBytes(padLength * 2)
    251                  pad = [b for b in padBytes if b != 0]
    252                  pad = pad[:padLength]
    253          else:
    254              raise AssertionError()
    255
    256          padding = bytearray([0,blockType] + pad + [0])
    257          paddedBytes = padding + bytes
    258          return paddedBytes
    259