Exemplo n.º 1
0
 def __init__(self, privPEM = None, pubPEM = None, certPEM = None, force_tlsv1 = False):
     priv = None
     pub = None
     cert = None
     if privPEM and (pubPEM or certPEM):
         priv = POW.pemRead(POW.RSA_PRIVATE_KEY, privPEM)
         if pubPEM:
             pub = POW.pemRead(POW.RSA_PUBLIC_KEY, pubPEM)
     else:
         rk = POW.Asymmetric(POW.RSA_CIPHER, 1536)
         priv = POW.pemRead(POW.RSA_PRIVATE_KEY, rk.pemWrite(POW.RSA_PRIVATE_KEY))
         pub = POW.pemRead(POW.RSA_PUBLIC_KEY, rk.pemWrite(POW.RSA_PUBLIC_KEY))
     cert = None
     if certPEM:
         cert = POW.pemRead(POW.X509_CERTIFICATE, certPEM)
     else:
         name = [['CN', 'dropbox-client']]
         cert = POW.X509()
         cert.setVersion(3)
         cert.setSerial(1)
         cert.setSubject(name)
         cert.setIssuer(name)
         cert.setPublicKey(pub)
         cert.setNotBefore(time2utc(0))
         cert.setNotAfter(time2utc(time.time() + 31536000))
         cert.sign(priv, POW.SHA256_DIGEST)
     assert priv, 'Private Key was not set in core/p2p/crypto.py'
     assert cert, 'Certificate was not set in core/p2p/crypto.py'
     if not (privPEM and certPEM and not pubPEM):
         assert pub, 'Public Key was not set in core/p2p/crypto.py'
     self.cert = cert
     self.priv = priv
     self.pub = pub
     self.force_tlsv1 = force_tlsv1
Exemplo n.º 2
0
    def readKeys(self):
        """Loads the 411 shared and master RSA keys"""

        pub_file = open(self.pub_filename, 'r')
        self.pub = POW.pemRead(POW.RSA_PUBLIC_KEY, pub_file.read())
        pub_file.close()

        shared_file = open(self.shared_filename, 'r')
        self.shared = self.readSharedKey(shared_file.read())
        shared_file.close()

        if os.path.exists(self.priv_filename):
            priv_file = open(self.priv_filename, 'r')
            self.priv = POW.pemRead(POW.RSA_PRIVATE_KEY, priv_file.read())
            priv_file.close()
Exemplo n.º 3
0
	def readKeys(self):
		"""Loads the 411 shared and master RSA keys"""


		pub_file = open(self.pub_filename, 'r')
		self.pub = POW.pemRead(POW.RSA_PUBLIC_KEY, pub_file.read())
		pub_file.close()
		
		shared_file = open(self.shared_filename, 'r')
		self.shared = self.readSharedKey(shared_file.read())
		shared_file.close()

		if os.path.exists(self.priv_filename):
			priv_file = open(self.priv_filename, 'r')
			self.priv = POW.pemRead(POW.RSA_PRIVATE_KEY, priv_file.read())
			priv_file.close()
Exemplo n.º 4
0
def generateSessionKeyV1(password, lmhash, nthash):
    if POW:
        hash = POW.Digest(POW.MD4_DIGEST)
    else:
        hash = MD4.new()
    hash.update(NTOWFv1(password, lmhash, nthash))
    return hash.digest()
Exemplo n.º 5
0
def __DES_block(key, msg):
    if POW:
        cipher = POW.Symmetric(POW.DES_ECB)
        cipher.encryptInit(__expand_DES_key(key))
        return cipher.update(msg)
    else:
        cipher = DES.new(__expand_DES_key(key), DES.MODE_ECB)
        return cipher.encrypt(msg)
Exemplo n.º 6
0
 def generate_session_key(self):
     bytes = self.get_random_bytes(32)
     _k = POW.rsaFromBN(self.K[0], self.K[1])
     log_key = md5(bytes).digest()
     header = _k.publicEncrypt(log_key)
     with self._klock:
         self.header = header
         self.log_key = log_key
Exemplo n.º 7
0
def compute_nthash(password):
    # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
    password = unicode(password).encode('utf_16le')
    if POW:
        hash = POW.Digest(POW.MD4_DIGEST)
    else:        
        hash = MD4.new()
    hash.update(password)
    return hash.digest()
Exemplo n.º 8
0
def hmac_md5(key, data):
    if POW:
        h = POW.Hmac(POW.MD5_DIGEST, key)
        h.update(data)
        result = h.mac()
    else:
        import hmac
        h = hmac.new(key)
        h.update(data)
        result = h.digest()
    return result
Exemplo n.º 9
0
def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
    if POW:
        cipher = POW.Symmetric(POW.RC4)
        cipher.encryptInit(keyExchangeKey)
        cipher_encrypt = cipher.update
    else:
        cipher = ARC4.new(keyExchangeKey)
        cipher_encrypt = cipher.encrypt

    sessionKey = cipher_encrypt(exportedSessionKey)
    return sessionKey
Exemplo n.º 10
0
    def sign(self, plaintext):
        """Sign the message with our private key. Returns the 
		base64 encoded signature."""

        if not self.priv: self.readKeys()

        digest = POW.Digest(POW.MD5_DIGEST)
        digest.update(plaintext)

        return base64.encodestring(
            self.priv.sign(digest.digest(), POW.MD5_DIGEST))
Exemplo n.º 11
0
def write_host_dbx(host_int, dropbox_location, appdata_path):
    try:
        _k = POW.rsaFromBN(DropboxLog.K[0], DropboxLog.K[1])
        enc_host_int = base64.b64encode(_k.publicEncrypt(str(host_int)))
        assert len(enc_host_int) == 172
        lines = [enc_host_int, base64.b64encode(dropbox_location.encode('utf8'))]
        host_db_path = os.path.join(appdata_path, _HOSTDBX_NAME)
        with open(host_db_path, 'wb') as f:
            f.write('\n'.join(lines))
    except Exception:
        unhandled_exc_handler()
Exemplo n.º 12
0
def compute_nthash(password):
    # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
    try:
        password = unicode(password).encode('utf_16le')
    except UnicodeDecodeError:
        import sys
        password = password.decode(sys.getfilesystemencoding()).encode('utf_16le')

    if POW:
        hash = POW.Digest(POW.MD4_DIGEST)
    else:        
        hash = MD4.new()
    hash.update(password)
    return hash.digest()
def verify_signature(info):
    pub_key = POW.pemRead(POW.RSA_PUBLIC_KEY, PUBLICKEY)
    d = info['digest'].digest()
    signed = False
    for sig in info['sigs']:
        try:
            pub_key.verify(sig, d, POW.SHA256_DIGEST)
            signed = True
            break
        except Exception as e:
            error = e

    if signed:
        return True
    raise error
Exemplo n.º 14
0
    def __init__(self):
        self.priv_filename = '/etc/411-security/master.key'
        self.pub_filename = '/etc/411-security/master.pub'
        self.shared_filename = '/etc/411-security/shared.key'

        self.masters = []
        # Our current favorite
        self.master = None
        self.disable = 0
        self.verbose = 0
        # The directory from which we place our 411 files. Used
        # when translating 411 file paths.
        self.rootdir = "/"
        self.sym = None
        self.pool = None
        # Master keys
        self.priv = None
        self.pub = None
        # Shared key, 256bit + 64bit IV
        self.shared = None

        self.conn = None
        # Default URL base path to find files.
        self.urldir = '411.d'
        # Groups we are interested in
        self.groups = ['']

        # Store attributes which we can use to filter on.
        self.attrs = {}

        self.config = Conf(self)
        self.config.parse()

        self.plugin = None

        # A regex for our header search.
        pattern = "\n*(?P<comment>.*?)\$411id\$"
        self.header_pattern = re.compile(pattern)

        pattern = "<a href=.+>(?P<filename>.+)</a> +(?P<date>\d+.*) +(?P<size>\d+.*)"
        # Make the pattern matching engine case-insensitive.
        self.dir_pattern = re.compile(pattern, re.I)

        # Use Blowfish with fast Cipher Block Chaining.
        self.sym = POW.Symmetric(POW.BF_CBC)
Exemplo n.º 15
0
#Embedded file name: dropbox/sync_engine/p2p/crypto.py
from __future__ import absolute_import
import time
import POW
from dropbox.trace import TRACE, unhandled_exc_handler
dhParams_data = '\n-----BEGIN DH PARAMETERS-----\nMIHHAoHBAK7J14riM20k2t9Ahup6rjr70ST8HgVhR+4hm908rgBpB5GIhlbrIAS2\nNdLsXcwpnYvf3xiT0zHQyITVv8/9pKCjR2pkkdpRCse72StyLpOq9DGB6oVc+Jst\npiU0hROT+if77uMe9IYlhozfubkbsAAPvRUtElT5IP4GRyYh1rMxqnvD3HeEBePE\n5A0Xg4aKJeuVFaYDjSpm+zuAlXlT5M4mC5dlu6MULUZUOxtimmxk2eWGkYa44zB3\nV7J9o/EZ+wIBAg==\n-----END DH PARAMETERS-----\n'
dhParams = POW.pemRead(POW.DH_PARAMS, dhParams_data)

def time2utc(val):
    return time.strftime('%y%m%d%H%M%SZ', time.gmtime(int(val)))


class CryptoData(object):

    def __init__(self, privPEM = None, pubPEM = None, certPEM = None, force_tlsv1 = False):
        priv = None
        pub = None
        cert = None
        if privPEM and (pubPEM or certPEM):
            priv = POW.pemRead(POW.RSA_PRIVATE_KEY, privPEM)
            if pubPEM:
                pub = POW.pemRead(POW.RSA_PUBLIC_KEY, pubPEM)
        else:
            rk = POW.Asymmetric(POW.RSA_CIPHER, 1536)
            priv = POW.pemRead(POW.RSA_PRIVATE_KEY, rk.pemWrite(POW.RSA_PRIVATE_KEY))
            pub = POW.pemRead(POW.RSA_PUBLIC_KEY, rk.pemWrite(POW.RSA_PUBLIC_KEY))
        cert = None
        if certPEM:
            cert = POW.pemRead(POW.X509_CERTIFICATE, certPEM)
        else:
            name = [['CN', 'dropbox-client']]
Exemplo n.º 16
0
    def bind(self, uuid, alter=0, bogus_binds=0):
        bind = MSRPCBind(endianness=self.endianness)

        syntax = '\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60'

        if self.endianness == '>':
            syntax = unpack('<LHHBB6s', syntax)
            syntax = pack('>LHHBB6s', *syntax)

            uuid = list(unpack('<LHHBB6sHH', uuid))

            uuid[-1] ^= uuid[-2]
            uuid[-2] ^= uuid[-1]
            uuid[-1] ^= uuid[-2]

            uuid = pack('>LHHBB6sHH', *uuid)

        ctx = 0
        for i in range(bogus_binds):
            bind.set_ctx_id(self._ctx, index=ctx)
            bind.set_trans_num(1, index=ctx)
            bind.set_if_binuuid('A' * 20, index=ctx)
            bind.set_xfer_syntax_binuuid(syntax, index=ctx)
            bind.set_xfer_syntax_ver(2, index=ctx)

            self._ctx += 1
            ctx += 1

        bind.set_ctx_id(self._ctx, index=ctx)
        bind.set_trans_num(1, index=ctx)
        bind.set_if_binuuid(uuid, index=ctx)
        bind.set_xfer_syntax_binuuid(syntax, index=ctx)
        bind.set_xfer_syntax_ver(2, index=ctx)

        bind.set_ctx_num(ctx + 1)

        if alter:
            bind.set_type(MSRPC_ALTERCTX)

        if (self.__auth_level != ntlm.NTLM_AUTH_NONE):
            if (self.__username is None) or (self.__password is None):
                self.__username, self.__password, nth, lmh = self._transport.get_credentials(
                )
            auth = ntlm.NTLMAuthNegotiate()
            auth['auth_level'] = self.__auth_level
            auth['auth_ctx_id'] = self._ctx + 79231
            bind.set_auth_data(str(auth))

        self._transport.send(bind.get_packet())

        s = self._transport.recv()
        if s != 0:
            resp = MSRPCBindAck(s)
        else:
            return 0  #mmm why not None?

        if resp.get_type() == MSRPC_BINDNAK:
            resp = MSRPCBindNak(s)
            status_code = resp.get_reason()
            if rpc_status_codes.has_key(status_code):
                raise Exception(rpc_status_codes[status_code], resp)
            else:
                raise Exception(
                    'Unknown DCE RPC fault status code: %.8x' % status_code,
                    resp)

        self.__max_xmit_size = resp.get_max_tfrag()

        if self.__auth_level != ntlm.NTLM_AUTH_NONE:
            authResp = ntlm.NTLMAuthChallenge(
                data=resp.get_auth_data().tostring())
            self._ntlm_challenge = authResp['challenge']
            response = ntlm.NTLMAuthChallengeResponse(self.__username,
                                                      self.__password,
                                                      self._ntlm_challenge)
            response['auth_ctx_id'] = self._ctx + 79231
            response['auth_level'] = self.__auth_level

            if self.__auth_level in (ntlm.NTLM_AUTH_CONNECT,
                                     ntlm.NTLM_AUTH_PKT_INTEGRITY,
                                     ntlm.NTLM_AUTH_PKT_PRIVACY):
                if self.__password:
                    key = ntlm.compute_nthash(self.__password)
                    if POW:
                        hash = POW.Digest(POW.MD4_DIGEST)
                    else:
                        hash = MD4.new()
                    hash.update(key)
                    key = hash.digest()
                else:
                    key = '\x00' * 16

            if POW:
                cipher = POW.Symmetric(POW.RC4)
                cipher.encryptInit(key)
                self.cipher_encrypt = cipher.update
            else:
                cipher = ARC4.new(key)
                self.cipher_encrypt = cipher.encrypt

            if response['flags'] & ntlm.NTLMSSP_KEY_EXCHANGE:
                session_key = 'A' * 16  # XXX Generate random session key
                response['session_key'] = self.cipher_encrypt(session_key)
                if POW:
                    cipher = POW.Symmetric(POW.RC4)
                    cipher.encryptInit(session_key)
                    self.cipher_encrypt = cipher.update
                else:
                    cipher = ARC4.new(session_key)
                    self.cipher_encrypt = cipher.encrypt

            self.sequence = 0

            auth3 = MSRPCHeader()
            auth3.set_type(MSRPC_AUTH3)
            auth3.set_auth_data(str(response))
            self._transport.send(auth3.get_packet(), forceWriteAndx=1)

        return resp  # means packet is signed, if verifier is wrong it fails
Exemplo n.º 17
0
    ['ST', 'Victoria'],
    ['O', 'eigenmagic'],
    ['CU', 'Justin Warren'],
    ]

if powmode:
    import POW
    import POW.pkix
    import time

    passphrase = 'TeSt'
    md5 = POW.Digest( POW.MD5_DIGEST )
    md5.update( passphrase )
    password = md5.digest()
    
    publicKey = POW.pemRead(POW.RSA_PUBLIC_KEY, publicFile.read())
    privateKey = POW.pemRead(POW.RSA_PRIVATE_KEY, privateFile.read(), password)

    c = POW.X509()

    #c.setIssuer( name )
    #c.setSubject( name )
    c.setSerial(0)

    # Expiry information
    t1 = POW.pkix.time2utc( time.time() )
    t2 = POW.pkix.time2utc( time.time() + 60*60*24*365 )
    c.setNotBefore(t1)
    c.setNotAfter(t2)

    c.setPublicKey(publicKey)
Exemplo n.º 18
0
class Service411:
    """Can retrieve a 411 file from a set of master servers.  Has the
	ability to encrypt, and decrypt files using a hybrid RSA-Symmetric
	cryptographic technique. Only as safe as your sysadmin."""
    def __init__(self):
        self.priv_filename = '/etc/411-security/master.key'
        self.pub_filename = '/etc/411-security/master.pub'
        self.shared_filename = '/etc/411-security/shared.key'

        self.masters = []
        # Our current favorite
        self.master = None
        self.disable = 0
        self.verbose = 0
        # The directory from which we place our 411 files. Used
        # when translating 411 file paths.
        self.rootdir = "/"
        self.sym = None
        self.pool = None
        # Master keys
        self.priv = None
        self.pub = None
        # Shared key, 256bit + 64bit IV
        self.shared = None

        self.conn = None
        # Default URL base path to find files.
        self.urldir = '411.d'
        # Groups we are interested in
        self.groups = ['']

        # Store attributes which we can use to filter on.
        self.attrs = {}

        self.config = Conf(self)
        self.config.parse()

        self.plugin = None

        # A regex for our header search.
        pattern = "\n*(?P<comment>.*?)\$411id\$"
        self.header_pattern = re.compile(pattern)

        pattern = "<a href=.+>(?P<filename>.+)</a> +(?P<date>\d+.*) +(?P<size>\d+.*)"
        # Make the pattern matching engine case-insensitive.
        self.dir_pattern = re.compile(pattern, re.I)

        # Use Blowfish with fast Cipher Block Chaining.
        self.sym = POW.Symmetric(POW.BF_CBC)

    def fillPool(self):
        """Starts the random pool. Dont do in constructor since this
		is computationally intensive."""

        # A cryptographically safe source of random data.
        self.pool = RandomPool(384)

    def setConf(self, conf):
        self.config = conf(self)

    def setConfHandler(self, handler):
        self.config.setHandler(handler)
        self.config.parse()

    def four11Path(self, filename411):
        """Translates 411 file names into UNIX absolute filenames."""

        # Warning this is UNIX dependant
        n = string.replace(filename411, ".", "/")
        n = string.replace(n, "//", ".")
        return os.path.normpath(os.path.join(self.rootdir, n))

    def path411(self, filename):
        """Turns an absolute UNIX path into a 411 filename. Every
		period ('.') is a filesystem delimeter (like /), and all
		filenames are assumed to be absolute, to start with a /. A
		literal period is coded as a double period ('..'). """

        # Warning, this is UNIX dependant.
        n = string.replace(filename[1:], ".", "..")
        n = string.replace(n, "/", ".")
        return n

    def connect(self, master=None):
        """Opens a HTTP 1.1 connection to the first live master server.
		Will use the master argument if specified, otherwise consults
		internal master server list.  This connection can service
		multiple requests."""

        if self.conn:
            self.disconnect()

        if master:
            masters = [master]
        else:
            masters = self.getMasters()
            if not masters:
                raise ValueError, \
                "We have no master servers to connect to."

        conn = None
        for master in masters:
            # Split address into host & port
            m = master.getAddress().split(':')
            if len(m) == 2:
                conn = HTTPConnection(m[0], int(m[1]))
            else:
                conn = HTTPConnection(m[0])

            # Test the connection.
            try:
                # Set variable so that connection originates
                # from privileged port only. This way, only
                # root can initialize this connection
                conn.privileged_port = True
                conn.connect()
            except:
                # If we cannot connect, devalue this server.
                master.decScore()
                conn = None
                continue
            else:
                # We pick the first master that accepts a
                # connection.
                self.master = master
                master.incScore()
                break

        if conn:
            self.conn = conn
        else:
            raise Error411, \
             "Could not reach a master server. Masters: %s" \
             % masters

    def disconnect(self):
        """Closes the master HTTP connection. """

        if self.conn:
            self.conn.close()
        self.conn = None

    def get(self, file):
        """ Retrives a 411 file. If arg is empty, a directory listing
		dictionary is returned. If file is valid, returns the decrypted
		contents and its associated meta data.  """

        if not file:
            raise Error411, "I need a file to get"

        # Allow you to get a full URL.
        if file.count("http://"):
            m = Master(file)
            self.connect(m)
            file = os.path.basename(file)
        else:
            # We use our internal configuration.
            self.connect()

        path = self.master.getDir() + file
        self.conn.request('GET', urllib.quote(path))
        headers = self.conn.getresponse()
        status = headers['status']
        reason = headers['reason']

        if status != 200:
            raise Error411, "Could not get file '%s%s': %s %s" % \
             (self.master.getUrl(), file, status, reason)

        contents = self.conn.read()
        self.disconnect()

        if file[-1] == '/':  # A directory
            return contents
        else:
            return self.decrypt(contents)

    def find(self, path="/"):
        """Finds all relevant files to retrieve on a master server.
		Returns dict indexed by file path containing mtime and size."""

        self.files = {}
        self.findHelper(path)
        return self.files

    def findHelper(self, path, depth=0):

        listing = self.get(path)
        lines = listing.split("\n")
        for line in lines:
            m = self.dir_pattern.search(line)
            if not m:
                continue
            #print line
            filename = m.group('filename')
            if filename == "Parent Directory":
                continue
            if filename[-1] == '/':
                if self.verbose:
                    print "Found directory %s (%s)" \
                     % (path+filename, depth)
                if self.isInteresting(path + filename, depth):
                    self.findHelper(path + filename, depth + 1)
                continue
            date = m.group('date').strip()
            size = m.group('size').strip()
            self.files[path + filename] = {
                "Name": filename,
                "Modified": date,
                "Size": size
            }

    def isInteresting(self, path, level):
        """Matches an offered group our registered groups. Slow,
		search time is squared with the number of registered groups.
		"""

        offered = path[1:-1].split('/')
        elements = len(offered)
        for r in self.groups:
            if not r:
                continue
            if self.verbose:
                print "Matching %s to %s level %s" \
                 % (offered, r[:len(offered)], level)
            try:
                # Shorten the registered group to match
                # the offerred one, then compare. Allows
                # group inheritance.
                if offered == r[:len(offered)]:
                    return 1
            except:
                continue
        return 0

    def readKeys(self):
        """Loads the 411 shared and master RSA keys"""

        pub_file = open(self.pub_filename, 'r')
        self.pub = POW.pemRead(POW.RSA_PUBLIC_KEY, pub_file.read())
        pub_file.close()

        shared_file = open(self.shared_filename, 'r')
        self.shared = self.readSharedKey(shared_file.read())
        shared_file.close()

        if os.path.exists(self.priv_filename):
            priv_file = open(self.priv_filename, 'r')
            self.priv = POW.pemRead(POW.RSA_PRIVATE_KEY, priv_file.read())
            priv_file.close()

    def makeSharedKey(self):
        """Uses our cryptographically safe random number generator to 
		give us a 256bit session key and 64bit Init Vector, in 411 format."""

        if not self.pool:
            self.fillPool()

        while 1:
            self.pool.stir()
            randomkey = self.pool.get_bytes(40)
            # First 256 bits are for the session key
            sessionkey = randomkey[:32]
            # Last 64 bits are for the CBC initial value.
            initialvalue = randomkey[-8:]
            try:
                self.sym.encryptInit(sessionkey, initialvalue)
            except TypeError:
                # Need a new session key (null chars in our key)
                continue
            else:
                break

        key = "-----BEGIN 411 SHARED KEY-----\n"
        key += base64.encodestring(randomkey)
        key += "-----END 411 SHARED KEY-----\n"
        return key

    def readSharedKey(self, key64):
        """Read a 411 shared key in base64 encoding and return the
		binary bits"""

        header = "-----BEGIN 411 SHARED KEY-----\n"
        footer = "-----END 411 SHARED KEY-----\n"
        try:
            a = key64.index(header) + len(header)
            b = key64.index(footer)
            key = base64.decodestring(key64[a:b])
        except:
            raise Error411, \
             "This does not appear to be a 411 shared key."
        return key

    def encrypt(self,
                plaintext,
                header="-----BEGIN 411 MESSAGE-----\n",
                footer="-----END 411 MESSAGE-----\n",
                sign=1):
        """Encrypts the plain text message using a hybrid cryptography
		technique: a 256-bit random session key is encrypted with the
		cluster shared key. The session key is used to quickly encrypt
		the message with the Blowfish symmetrical algorithm."""

        if not self.shared:
            self.readKeys()

        # First 256 bits are for the session key,
        # Last 64 bits are for the CBC initial value.
        try:
            self.sym.encryptInit(self.shared[:32], self.shared[-8:])
        except TypeError:
            raise Error411, "Invalid Shared Key"

        # Sign the text with the master private key
        if sign:
            if not self.priv:
                raise Error411, "I need the master private key to sign messages"
            sig = self.sign(plaintext)
        else:
            sig = "Not Signed"

        # Encrypt the text with Blowfish for speed.
        ciphertext = self.sym.update(plaintext) + self.sym.final()
        ciphertext_base64 = base64.encodestring(ciphertext)

        # Message format (v2.0):
        # digital signature
        # <blank line>
        # symmetrically-encrypted message
        msg = header
        msg += sig + "\n"
        msg += ciphertext_base64
        msg += footer
        return msg

    def decrypt(self,
                contents,
                header="-----BEGIN 411 MESSAGE-----\n",
                footer="-----END 411 MESSAGE-----\n",
                type411=1):
        """Uses the shared key to read 411 messages. For 411
		type messages, returns the tuple (contents, meta) where meta is
		a dictionary containing the 411 headers. If not type 411,
		returns a (plaintext, sig_base64). No verification of signature
		is performed."""

        if not self.sym:
            self.fillPool()

        ciphersig_base64 = ''
        try:
            a = string.index(contents, header) + len(header)
            b = string.index(contents, footer)
            msg = contents[a:b]

            ciphersig_base64, ciphertext_base64 = msg.split('\n\n')
            ciphertext = base64.decodestring(ciphertext_base64)
        except:
            raise Error411, \
             "This file does not appear to be in 411 format."

        if not self.shared:
            self.readKeys()

        sessionkey = self.shared[:32]
        initialvalue = self.shared[-8:]

        self.sym.decryptInit(sessionkey, initialvalue)
        try:
            text = self.sym.update(ciphertext) + self.sym.final()
        except POW.SSLError:
            raise Error411, "Could not decrypt file, wrong key?"

        if type411:
            if not self.verify(text, ciphersig_base64):
                raise Error411, "Signature does not verify."
            return self.decode(text)
        else:
            return (text, ciphersig_base64)

    def decode(self, plaintext):
        meta = {}
        p = Parser(plaintext, self.attrs)
        meta = p.get_filtered_content()
        self.plugin = p.get_plugin()
        return meta['content'], meta

    def verify(self, msg, sig_base64):
        """Verifies that the plaintext message was signed with the
		(base64 encoded) signature, and has not been altered since
		signing. Returns true if message verifies."""

        if not self.pub:
            try:
                self.readKeys()
            except IOError, e:
                syslog.syslog(syslog.LOG_ERR, '411-error: ' \
                 + str(e))
                return 0

        digest = POW.Digest(POW.MD5_DIGEST)
        digest.update(msg)

        try:
            sig = base64.decodestring(sig_base64)
        except:
            return 0

        return self.pub.verify(sig, digest.digest(), POW.MD5_DIGEST)
Exemplo n.º 19
0
 def generate_session_key(self):
     bytes = self.get_random_bytes(32)
     _k = POW.rsaFromBN(DropboxLog.K[0], DropboxLog.K[1])
     self.log_key = md5(bytes).digest()
     self.header = _k.publicEncrypt(self.log_key)
     self.iv = md5(self.log_key).digest()[:16]