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

# Source Code for Module tlslite.utils.python_rsakey

      1  # Author: Trevor Perrin
      2  # See the LICENSE file for legal information regarding use of this file.
      3
      4  """Pure-Python RSA implementation."""
      5
      6  from .cryptomath import *
      7  from .asn1parser import ASN1Parser
      8  from .rsakey import *
      9  from .pem import *
     10
     11 -class Python_RSAKey(RSAKey):
     12 -    def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0):
     13          if (n and not e) or (e and not n):
     14              raise AssertionError()
     15          self.n = n
     16          self.e = e
     17          self.d = d
     18          self.p = p
     19          self.q = q
     20          self.dP = dP
     21          self.dQ = dQ
     22          self.qInv = qInv
     23          self.blinder = 0
     24          self.unblinder = 0
     25
     26 -    def hasPrivateKey(self):
     27          return self.d != 0
     28
     29 -    def _rawPrivateKeyOp(self, m):
     30          #Create blinding values, on the first pass:
     31          if not self.blinder:
     32              self.unblinder = getRandomNumber(2, self.n)
     33              self.blinder = powMod(invMod(self.unblinder, self.n), self.e,
     34                                    self.n)
     35
     36          #Blind the input
     37          m = (m * self.blinder) % self.n
     38
     39          #Perform the RSA operation
     40          c = self._rawPrivateKeyOpHelper(m)
     41
     42          #Unblind the output
     43          c = (c * self.unblinder) % self.n
     44
     45          #Update blinding values
     46          self.blinder = (self.blinder * self.blinder) % self.n
     47          self.unblinder = (self.unblinder * self.unblinder) % self.n
     48
     49          #Return the output
     50          return c
     51
     52
     53 -    def _rawPrivateKeyOpHelper(self, m):
     54          #Non-CRT version
     55          #c = powMod(m, self.d, self.n)
     56
     57          #CRT version  (~3x faster)
     58          s1 = powMod(m, self.dP, self.p)
     59          s2 = powMod(m, self.dQ, self.q)
     60          h = ((s1 - s2) * self.qInv) % self.p
     61          c = s2 + self.q * h
     62          return c
     63
     64 -    def _rawPublicKeyOp(self, c):
     65          m = powMod(c, self.e, self.n)
     66          return m
     67
     68 -    def acceptsPassword(self): return False
     69
     70 -    def generate(bits):
     71          key = Python_RSAKey()
     72          p = getRandomPrime(bits//2, False)
     73          q = getRandomPrime(bits//2, False)
     74          t = lcm(p-1, q-1)
     75          key.n = p * q
     76          key.e = 65537
     77          key.d = invMod(key.e, t)
     78          key.p = p
     79          key.q = q
     80          key.dP = key.d % (p-1)
     81          key.dQ = key.d % (q-1)
     82          key.qInv = invMod(q, p)
     83          return key
     84      generate = staticmethod(generate)
     85
     86 -    def parsePEM(s, passwordCallback=None):
     87          """Parse a string containing a <privateKey> or <publicKey>, or
     88          PEM-encoded key."""
     89
     90          if pemSniff(s, "PRIVATE KEY"):
     91              bytes = dePem(s, "PRIVATE KEY")
     92              return Python_RSAKey._parsePKCS8(bytes)
     93          elif pemSniff(s, "RSA PRIVATE KEY"):
     94              bytes = dePem(s, "RSA PRIVATE KEY")
     95              return Python_RSAKey._parseSSLeay(bytes)
     96          else:
     97              raise SyntaxError("Not a PEM private key file")
     98      parsePEM = staticmethod(parsePEM)
     99
    100 -    def _parsePKCS8(bytes):
    101          p = ASN1Parser(bytes)
    102
    103          version = p.getChild(0).value[0]
    104          if version != 0:
    105              raise SyntaxError("Unrecognized PKCS8 version")
    106
    107          rsaOID = p.getChild(1).value
    108          if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]:
    109              raise SyntaxError("Unrecognized AlgorithmIdentifier")
    110
    111          #Get the privateKey
    112          privateKeyP = p.getChild(2)
    113
    114          #Adjust for OCTET STRING encapsulation
    115          privateKeyP = ASN1Parser(privateKeyP.value)
    116
    117          return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
    118      _parsePKCS8 = staticmethod(_parsePKCS8)
    119
    120 -    def _parseSSLeay(bytes):
    121          privateKeyP = ASN1Parser(bytes)
    122          return Python_RSAKey._parseASN1PrivateKey(privateKeyP)
    123      _parseSSLeay = staticmethod(_parseSSLeay)
    124
    125 -    def _parseASN1PrivateKey(privateKeyP):
    126          version = privateKeyP.getChild(0).value[0]
    127          if version != 0:
    128              raise SyntaxError("Unrecognized RSAPrivateKey version")
    129          n = bytesToNumber(privateKeyP.getChild(1).value)
    130          e = bytesToNumber(privateKeyP.getChild(2).value)
    131          d = bytesToNumber(privateKeyP.getChild(3).value)
    132          p = bytesToNumber(privateKeyP.getChild(4).value)
    133          q = bytesToNumber(privateKeyP.getChild(5).value)
    134          dP = bytesToNumber(privateKeyP.getChild(6).value)
    135          dQ = bytesToNumber(privateKeyP.getChild(7).value)
    136          qInv = bytesToNumber(privateKeyP.getChild(8).value)
    137          return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv)
    138      _parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey)
    139