149 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""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)
 |