tlslite.utils.rsakey

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, numBytes(self.n))
    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          if len(sigBytes) != numBytes(self.n):
    126              return False
    127          paddedBytes = self._addPKCS1Padding(bytes, 1)
    128          c = bytesToNumber(sigBytes)
    129          if c >= self.n:
    130              return False
    131          m = self._rawPublicKeyOp(c)
    132          checkBytes = numberToBytes(m, numBytes(self.n))
    133          return checkBytes == paddedBytes
    134
    135 -    def encrypt(self, bytes):
    136          """Encrypt the passed-in bytes.
    137
    138          This performs PKCS1 encryption of the passed-in data.
    139
    140          @type bytes: L{bytearray} of unsigned bytes
    141          @param bytes: The value which will be encrypted.
    142
    143          @rtype: L{bytearray} of unsigned bytes.
    144          @return: A PKCS1 encryption of the passed-in data.
    145          """
    146          paddedBytes = self._addPKCS1Padding(bytes, 2)
    147          m = bytesToNumber(paddedBytes)
    148          if m >= self.n:
    149              raise ValueError()
    150          c = self._rawPublicKeyOp(m)
    151          encBytes = numberToBytes(c, numBytes(self.n))
    152          return encBytes
    153
    154 -    def decrypt(self, encBytes):
    155          """Decrypt the passed-in bytes.
    156
    157          This requires the key to have a private component.  It performs
    158          PKCS1 decryption of the passed-in data.
    159
    160          @type encBytes: L{bytearray} of unsigned bytes
    161          @param encBytes: The value which will be decrypted.
    162
    163          @rtype: L{bytearray} of unsigned bytes or None.
    164          @return: A PKCS1 decryption of the passed-in data or None if
    165          the data is not properly formatted.
    166          """
    167          if not self.hasPrivateKey():
    168              raise AssertionError()
    169          if len(encBytes) != numBytes(self.n):
    170              return None
    171          c = bytesToNumber(encBytes)
    172          if c >= self.n:
    173              return None
    174          m = self._rawPrivateKeyOp(c)
    175          decBytes = numberToBytes(m, numBytes(self.n))
    176          if decBytes[0] != 0 or decBytes[1] != 2: #Check first two bytes
    177              return None
    178          for x in range(1, len(decBytes)-1): #Scan through for zero separator
    179              if decBytes[x]== 0:
    180                  break
    181          else:
    182              return None
    183          return decBytes[x+1:] #Return everything after the separator
    184
    185 -    def _rawPrivateKeyOp(self, m):
    186          raise NotImplementedError()
    187
    188 -    def _rawPublicKeyOp(self, c):
    189          raise NotImplementedError()
    190
    191 -    def acceptsPassword(self):
    192          """Return True if the write() method accepts a password for use
    193          in encrypting the private key.
    194
    195          @rtype: bool
    196          """
    197          raise NotImplementedError()
    198
    199 -    def write(self, password=None):
    200          """Return a string containing the key.
    201
    202          @rtype: str
    203          @return: A string describing the key, in whichever format (PEM)
    204          is native to the implementation.
    205          """
    206          raise NotImplementedError()
    207
    208 -    def generate(bits):
    209          """Generate a new key with the specified bit length.
    210
    211          @rtype: L{tlslite.utils.RSAKey.RSAKey}
    212          """
    213          raise NotImplementedError()
    214      generate = staticmethod(generate)
    215
    216
    217      # **************************************************************************
    218      # Helper Functions for RSA Keys
    219      # **************************************************************************
    220
    221 -    def _addPKCS1SHA1Prefix(self, bytes, withNULL=False):
    222          # There is a long history of confusion over whether the SHA1
    223          # algorithmIdentifier should be encoded with a NULL parameter or
    224          # with the parameter omitted.  While the original intention was
    225          # apparently to omit it, many toolkits went the other way.  TLS 1.2
    226          # specifies the NULL should be omitted, so maybe the pendulum is
    227          # swinging back towards the original intention.  Anyways, verification
    228          # code should accept both, so the above hashAndVerify() is not
    229          # yet correct.  However, nothing uses this code yet - an eventual
    230          # TLS 1.2 implementation will have to fix that.
    231          if not withNULL:
    232              prefixBytes = createByteArraySequence(\
    233              [0x30,0x1f,0x30,0x07,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x04,0x14])
    234          else:
    235              prefixBytes = createByteArraySequence(\
    236              [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14])
    237          prefixedBytes = prefixBytes + bytes
    238          return prefixedBytes
    239
    240 -    def _addPKCS1Padding(self, bytes, blockType):
    241          padLength = (numBytes(self.n) - (len(bytes)+3))
    242          if blockType == 1: #Signature padding
    243              pad = [0xFF] * padLength
    244          elif blockType == 2: #Encryption padding
    245              pad = createByteArraySequence([])
    246              while len(pad) < padLength:
    247                  padBytes = getRandomBytes(padLength * 2)
    248                  pad = [b for b in padBytes if b != 0]
    249                  pad = pad[:padLength]
    250          else:
    251              raise AssertionError()
    252
    253          padding = createByteArraySequence([0,blockType] + pad + [0])
    254          paddedBytes = padding + bytes
    255          return paddedBytes
    256