"""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)