| OLD | NEW |
| 1 # Author: Trevor Perrin |
| 2 # See the LICENSE file for legal information regarding use of this file. |
| 3 |
| 1 """Pure-Python RSA implementation.""" | 4 """Pure-Python RSA implementation.""" |
| 2 | 5 |
| 3 from cryptomath import * | 6 from .cryptomath import * |
| 4 import xmltools | 7 from .asn1parser import ASN1Parser |
| 5 from asn1parser import ASN1Parser | 8 from .rsakey import * |
| 6 from rsakey import * | 9 from .pem import * |
| 7 | 10 |
| 8 class Python_RSAKey(RSAKey): | 11 class Python_RSAKey(RSAKey): |
| 9 def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0): | 12 def __init__(self, n=0, e=0, d=0, p=0, q=0, dP=0, dQ=0, qInv=0): |
| 10 if (n and not e) or (e and not n): | 13 if (n and not e) or (e and not n): |
| 11 raise AssertionError() | 14 raise AssertionError() |
| 12 self.n = n | 15 self.n = n |
| 13 self.e = e | 16 self.e = e |
| 14 self.d = d | 17 self.d = d |
| 15 self.p = p | 18 self.p = p |
| 16 self.q = q | 19 self.q = q |
| 17 self.dP = dP | 20 self.dP = dP |
| 18 self.dQ = dQ | 21 self.dQ = dQ |
| 19 self.qInv = qInv | 22 self.qInv = qInv |
| 20 self.blinder = 0 | 23 self.blinder = 0 |
| 21 self.unblinder = 0 | 24 self.unblinder = 0 |
| 22 | 25 |
| 23 def hasPrivateKey(self): | 26 def hasPrivateKey(self): |
| 24 return self.d != 0 | 27 return self.d != 0 |
| 25 | 28 |
| 26 def hash(self): | |
| 27 s = self.writeXMLPublicKey('\t\t') | |
| 28 return hashAndBase64(s.strip()) | |
| 29 | |
| 30 def _rawPrivateKeyOp(self, m): | 29 def _rawPrivateKeyOp(self, m): |
| 31 #Create blinding values, on the first pass: | 30 #Create blinding values, on the first pass: |
| 32 if not self.blinder: | 31 if not self.blinder: |
| 33 self.unblinder = getRandomNumber(2, self.n) | 32 self.unblinder = getRandomNumber(2, self.n) |
| 34 self.blinder = powMod(invMod(self.unblinder, self.n), self.e, | 33 self.blinder = powMod(invMod(self.unblinder, self.n), self.e, |
| 35 self.n) | 34 self.n) |
| 36 | 35 |
| 37 #Blind the input | 36 #Blind the input |
| 38 m = (m * self.blinder) % self.n | 37 m = (m * self.blinder) % self.n |
| 39 | 38 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 61 h = ((s1 - s2) * self.qInv) % self.p | 60 h = ((s1 - s2) * self.qInv) % self.p |
| 62 c = s2 + self.q * h | 61 c = s2 + self.q * h |
| 63 return c | 62 return c |
| 64 | 63 |
| 65 def _rawPublicKeyOp(self, c): | 64 def _rawPublicKeyOp(self, c): |
| 66 m = powMod(c, self.e, self.n) | 65 m = powMod(c, self.e, self.n) |
| 67 return m | 66 return m |
| 68 | 67 |
| 69 def acceptsPassword(self): return False | 68 def acceptsPassword(self): return False |
| 70 | 69 |
| 71 def write(self, indent=''): | |
| 72 if self.d: | |
| 73 s = indent+'<privateKey xmlns="http://trevp.net/rsa">\n' | |
| 74 else: | |
| 75 s = indent+'<publicKey xmlns="http://trevp.net/rsa">\n' | |
| 76 s += indent+'\t<n>%s</n>\n' % numberToBase64(self.n) | |
| 77 s += indent+'\t<e>%s</e>\n' % numberToBase64(self.e) | |
| 78 if self.d: | |
| 79 s += indent+'\t<d>%s</d>\n' % numberToBase64(self.d) | |
| 80 s += indent+'\t<p>%s</p>\n' % numberToBase64(self.p) | |
| 81 s += indent+'\t<q>%s</q>\n' % numberToBase64(self.q) | |
| 82 s += indent+'\t<dP>%s</dP>\n' % numberToBase64(self.dP) | |
| 83 s += indent+'\t<dQ>%s</dQ>\n' % numberToBase64(self.dQ) | |
| 84 s += indent+'\t<qInv>%s</qInv>\n' % numberToBase64(self.qInv) | |
| 85 s += indent+'</privateKey>' | |
| 86 else: | |
| 87 s += indent+'</publicKey>' | |
| 88 #Only add \n if part of a larger structure | |
| 89 if indent != '': | |
| 90 s += '\n' | |
| 91 return s | |
| 92 | |
| 93 def writeXMLPublicKey(self, indent=''): | |
| 94 return Python_RSAKey(self.n, self.e).write(indent) | |
| 95 | |
| 96 def generate(bits): | 70 def generate(bits): |
| 97 key = Python_RSAKey() | 71 key = Python_RSAKey() |
| 98 p = getRandomPrime(bits/2, False) | 72 p = getRandomPrime(bits//2, False) |
| 99 q = getRandomPrime(bits/2, False) | 73 q = getRandomPrime(bits//2, False) |
| 100 t = lcm(p-1, q-1) | 74 t = lcm(p-1, q-1) |
| 101 key.n = p * q | 75 key.n = p * q |
| 102 key.e = 3L #Needed to be long, for Java | 76 key.e = 65537 |
| 103 key.d = invMod(key.e, t) | 77 key.d = invMod(key.e, t) |
| 104 key.p = p | 78 key.p = p |
| 105 key.q = q | 79 key.q = q |
| 106 key.dP = key.d % (p-1) | 80 key.dP = key.d % (p-1) |
| 107 key.dQ = key.d % (q-1) | 81 key.dQ = key.d % (q-1) |
| 108 key.qInv = invMod(q, p) | 82 key.qInv = invMod(q, p) |
| 109 return key | 83 return key |
| 110 generate = staticmethod(generate) | 84 generate = staticmethod(generate) |
| 111 | 85 |
| 112 def parsePEM(s, passwordCallback=None): | 86 def parsePEM(s, passwordCallback=None): |
| 113 """Parse a string containing a <privateKey> or <publicKey>, or | 87 """Parse a string containing a <privateKey> or <publicKey>, or |
| 114 PEM-encoded key.""" | 88 PEM-encoded key.""" |
| 115 | 89 |
| 116 start = s.find("-----BEGIN PRIVATE KEY-----") | 90 if pemSniff(s, "PRIVATE KEY"): |
| 117 if start != -1: | 91 bytes = dePem(s, "PRIVATE KEY") |
| 118 end = s.find("-----END PRIVATE KEY-----") | |
| 119 if end == -1: | |
| 120 raise SyntaxError("Missing PEM Postfix") | |
| 121 s = s[start+len("-----BEGIN PRIVATE KEY -----") : end] | |
| 122 bytes = base64ToBytes(s) | |
| 123 return Python_RSAKey._parsePKCS8(bytes) | 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) |
| 124 else: | 96 else: |
| 125 start = s.find("-----BEGIN RSA PRIVATE KEY-----") | 97 raise SyntaxError("Not a PEM private key file") |
| 126 if start != -1: | |
| 127 end = s.find("-----END RSA PRIVATE KEY-----") | |
| 128 if end == -1: | |
| 129 raise SyntaxError("Missing PEM Postfix") | |
| 130 s = s[start+len("-----BEGIN RSA PRIVATE KEY -----") : end] | |
| 131 bytes = base64ToBytes(s) | |
| 132 return Python_RSAKey._parseSSLeay(bytes) | |
| 133 raise SyntaxError("Missing PEM Prefix") | |
| 134 parsePEM = staticmethod(parsePEM) | 98 parsePEM = staticmethod(parsePEM) |
| 135 | 99 |
| 136 def parseXML(s): | |
| 137 element = xmltools.parseAndStripWhitespace(s) | |
| 138 return Python_RSAKey._parseXML(element) | |
| 139 parseXML = staticmethod(parseXML) | |
| 140 | |
| 141 def _parsePKCS8(bytes): | 100 def _parsePKCS8(bytes): |
| 142 p = ASN1Parser(bytes) | 101 p = ASN1Parser(bytes) |
| 143 | 102 |
| 144 version = p.getChild(0).value[0] | 103 version = p.getChild(0).value[0] |
| 145 if version != 0: | 104 if version != 0: |
| 146 raise SyntaxError("Unrecognized PKCS8 version") | 105 raise SyntaxError("Unrecognized PKCS8 version") |
| 147 | 106 |
| 148 rsaOID = p.getChild(1).value | 107 rsaOID = p.getChild(1).value |
| 149 if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]: | 108 if list(rsaOID) != [6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0]: |
| 150 raise SyntaxError("Unrecognized AlgorithmIdentifier") | 109 raise SyntaxError("Unrecognized AlgorithmIdentifier") |
| (...skipping 19 matching lines...) Expand all Loading... |
| 170 n = bytesToNumber(privateKeyP.getChild(1).value) | 129 n = bytesToNumber(privateKeyP.getChild(1).value) |
| 171 e = bytesToNumber(privateKeyP.getChild(2).value) | 130 e = bytesToNumber(privateKeyP.getChild(2).value) |
| 172 d = bytesToNumber(privateKeyP.getChild(3).value) | 131 d = bytesToNumber(privateKeyP.getChild(3).value) |
| 173 p = bytesToNumber(privateKeyP.getChild(4).value) | 132 p = bytesToNumber(privateKeyP.getChild(4).value) |
| 174 q = bytesToNumber(privateKeyP.getChild(5).value) | 133 q = bytesToNumber(privateKeyP.getChild(5).value) |
| 175 dP = bytesToNumber(privateKeyP.getChild(6).value) | 134 dP = bytesToNumber(privateKeyP.getChild(6).value) |
| 176 dQ = bytesToNumber(privateKeyP.getChild(7).value) | 135 dQ = bytesToNumber(privateKeyP.getChild(7).value) |
| 177 qInv = bytesToNumber(privateKeyP.getChild(8).value) | 136 qInv = bytesToNumber(privateKeyP.getChild(8).value) |
| 178 return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv) | 137 return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv) |
| 179 _parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey) | 138 _parseASN1PrivateKey = staticmethod(_parseASN1PrivateKey) |
| 180 | |
| 181 def _parseXML(element): | |
| 182 try: | |
| 183 xmltools.checkName(element, "privateKey") | |
| 184 except SyntaxError: | |
| 185 xmltools.checkName(element, "publicKey") | |
| 186 | |
| 187 #Parse attributes | |
| 188 xmltools.getReqAttribute(element, "xmlns", "http://trevp.net/rsa\Z") | |
| 189 xmltools.checkNoMoreAttributes(element) | |
| 190 | |
| 191 #Parse public values (<n> and <e>) | |
| 192 n = base64ToNumber(xmltools.getText(xmltools.getChild(element, 0, "n"),
xmltools.base64RegEx)) | |
| 193 e = base64ToNumber(xmltools.getText(xmltools.getChild(element, 1, "e"),
xmltools.base64RegEx)) | |
| 194 d = 0 | |
| 195 p = 0 | |
| 196 q = 0 | |
| 197 dP = 0 | |
| 198 dQ = 0 | |
| 199 qInv = 0 | |
| 200 #Parse private values, if present | |
| 201 if element.childNodes.length>=3: | |
| 202 d = base64ToNumber(xmltools.getText(xmltools.getChild(element, 2, "d
"), xmltools.base64RegEx)) | |
| 203 p = base64ToNumber(xmltools.getText(xmltools.getChild(element, 3, "p
"), xmltools.base64RegEx)) | |
| 204 q = base64ToNumber(xmltools.getText(xmltools.getChild(element, 4, "q
"), xmltools.base64RegEx)) | |
| 205 dP = base64ToNumber(xmltools.getText(xmltools.getChild(element, 5, "
dP"), xmltools.base64RegEx)) | |
| 206 dQ = base64ToNumber(xmltools.getText(xmltools.getChild(element, 6, "
dQ"), xmltools.base64RegEx)) | |
| 207 qInv = base64ToNumber(xmltools.getText(xmltools.getLastChild(element
, 7, "qInv"), xmltools.base64RegEx)) | |
| 208 return Python_RSAKey(n, e, d, p, q, dP, dQ, qInv) | |
| 209 _parseXML = staticmethod(_parseXML) | |
| OLD | NEW |