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 |