summaryrefslogtreecommitdiffstats
path: root/src/lib/tlslite/utils/OpenSSL_RSAKey.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tlslite/utils/OpenSSL_RSAKey.py')
-rwxr-xr-xsrc/lib/tlslite/utils/OpenSSL_RSAKey.py148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/lib/tlslite/utils/OpenSSL_RSAKey.py b/src/lib/tlslite/utils/OpenSSL_RSAKey.py
new file mode 100755
index 000000000..fe1a3cd74
--- /dev/null
+++ b/src/lib/tlslite/utils/OpenSSL_RSAKey.py
@@ -0,0 +1,148 @@
+"""OpenSSL/M2Crypto RSA implementation."""
+
+from cryptomath import *
+
+from RSAKey import *
+from Python_RSAKey import Python_RSAKey
+
+#copied from M2Crypto.util.py, so when we load the local copy of m2
+#we can still use it
+def password_callback(v, prompt1='Enter private key passphrase:',
+ prompt2='Verify passphrase:'):
+ from getpass import getpass
+ while 1:
+ try:
+ p1=getpass(prompt1)
+ if v:
+ p2=getpass(prompt2)
+ if p1==p2:
+ break
+ else:
+ break
+ except KeyboardInterrupt:
+ return None
+ return p1
+
+
+if m2cryptoLoaded:
+ class OpenSSL_RSAKey(RSAKey):
+ def __init__(self, n=0, e=0):
+ self.rsa = None
+ self._hasPrivateKey = False
+ if (n and not e) or (e and not n):
+ raise AssertionError()
+ if n and e:
+ self.rsa = m2.rsa_new()
+ m2.rsa_set_n(self.rsa, numberToMPI(n))
+ m2.rsa_set_e(self.rsa, numberToMPI(e))
+
+ def __del__(self):
+ if self.rsa:
+ m2.rsa_free(self.rsa)
+
+ def __getattr__(self, name):
+ if name == 'e':
+ if not self.rsa:
+ return 0
+ return mpiToNumber(m2.rsa_get_e(self.rsa))
+ elif name == 'n':
+ if not self.rsa:
+ return 0
+ return mpiToNumber(m2.rsa_get_n(self.rsa))
+ else:
+ raise AttributeError
+
+ def hasPrivateKey(self):
+ return self._hasPrivateKey
+
+ def hash(self):
+ return Python_RSAKey(self.n, self.e).hash()
+
+ def _rawPrivateKeyOp(self, m):
+ s = numberToString(m)
+ byteLength = numBytes(self.n)
+ if len(s)== byteLength:
+ pass
+ elif len(s) == byteLength-1:
+ s = '\0' + s
+ else:
+ raise AssertionError()
+ c = stringToNumber(m2.rsa_private_encrypt(self.rsa, s,
+ m2.no_padding))
+ return c
+
+ def _rawPublicKeyOp(self, c):
+ s = numberToString(c)
+ byteLength = numBytes(self.n)
+ if len(s)== byteLength:
+ pass
+ elif len(s) == byteLength-1:
+ s = '\0' + s
+ else:
+ raise AssertionError()
+ m = stringToNumber(m2.rsa_public_decrypt(self.rsa, s,
+ m2.no_padding))
+ return m
+
+ def acceptsPassword(self): return True
+
+ def write(self, password=None):
+ bio = m2.bio_new(m2.bio_s_mem())
+ if self._hasPrivateKey:
+ if password:
+ def f(v): return password
+ m2.rsa_write_key(self.rsa, bio, m2.des_ede_cbc(), f)
+ else:
+ def f(): pass
+ m2.rsa_write_key_no_cipher(self.rsa, bio, f)
+ else:
+ if password:
+ raise AssertionError()
+ m2.rsa_write_pub_key(self.rsa, bio)
+ s = m2.bio_read(bio, m2.bio_ctrl_pending(bio))
+ m2.bio_free(bio)
+ return s
+
+ def writeXMLPublicKey(self, indent=''):
+ return Python_RSAKey(self.n, self.e).write(indent)
+
+ def generate(bits):
+ key = OpenSSL_RSAKey()
+ def f():pass
+ key.rsa = m2.rsa_generate_key(bits, 3, f)
+ key._hasPrivateKey = True
+ return key
+ generate = staticmethod(generate)
+
+ def parse(s, passwordCallback=None):
+ if s.startswith("-----BEGIN "):
+ if passwordCallback==None:
+ callback = password_callback
+ else:
+ def f(v, prompt1=None, prompt2=None):
+ return passwordCallback()
+ callback = f
+ bio = m2.bio_new(m2.bio_s_mem())
+ try:
+ m2.bio_write(bio, s)
+ key = OpenSSL_RSAKey()
+ if s.startswith("-----BEGIN RSA PRIVATE KEY-----"):
+ def f():pass
+ key.rsa = m2.rsa_read_key(bio, callback)
+ if key.rsa == None:
+ raise SyntaxError()
+ key._hasPrivateKey = True
+ elif s.startswith("-----BEGIN PUBLIC KEY-----"):
+ key.rsa = m2.rsa_read_pub_key(bio)
+ if key.rsa == None:
+ raise SyntaxError()
+ key._hasPrivateKey = False
+ else:
+ raise SyntaxError()
+ return key
+ finally:
+ m2.bio_free(bio)
+ else:
+ raise SyntaxError()
+
+ parse = staticmethod(parse)