Example #1
0
def parseTextReplyBlocks(s):
    """Given a string holding one or more text-encoded reply blocks,
       return a list containing the reply blocks.  Raise ParseError on
       failure."""

    try:
        res = unarmorText(s, (RB_ARMOR_NAME,), base64=1)
    except ValueError, e:
        raise ParseError(str(e))
Example #2
0
def parseTextReplyBlocks(s):
    """Given a string holding one or more text-encoded reply blocks,
       return a list containing the reply blocks.  Raise ParseError on
       failure."""

    try:
        res = unarmorText(s, (RB_ARMOR_NAME, ), base64=1)
    except ValueError, e:
        raise ParseError(str(e))
Example #3
0
def parseTextEncodedMessages(msg,force=0):
    """Given a text-encoded Type III packet, return a list of
       TextEncodedMessage objects or raise ParseError.

          force -- uncompress the message even if it's overcompressed.
    """

    def isBase64(t,f):
        for k,v in f:
            if k == "Message-type":
                if v != 'plaintext':
                    return 1
        return 0

    unarmored = unarmorText(msg, (MESSAGE_ARMOR_NAME,), base64fn=isBase64)
    res = []
    for tp,fields,val in unarmored:
        d = {}
        for k,v in fields:
            d[k] = v
        if d.get("Message-type", "plaintext") == "plaintext":
            msgType = 'TXT'
        elif d['Message-type'] == 'overcompressed':
            msgType = "LONG"
        elif d['Message-type'] == 'binary':
            msgType = "BIN"
        elif d['Message-type'] == 'encrypted':
            msgType = "ENC"
        elif d['Message-type'] == 'fragment':
            msgType = "FRAG"
        else:
            raise ParseError("Unknown message type: %r"%d["Message-type"])

        ascTag = d.get("Decoding-handle")
        if ascTag:
            msgType = "ENC"

        if msgType == 'LONG' and force:
            val = uncompressData(val)

        if msgType in ('TXT','BIN','LONG','FRAG'):
            res.append(TextEncodedMessage(val, msgType))
        else:
            assert msgType == 'ENC'
            try:
                tag = binascii.a2b_base64(ascTag)
            except (TypeError, binascii.Incomplete, binascii.Error), e:
                raise ParseError("Error in base64 encoding: %s"%e)
            if len(tag) != TAG_LEN:
                raise ParseError("Impossible tag length: %s"%len(tag))
            res.append(TextEncodedMessage(val, 'ENC', tag))
Example #4
0
def parseTextEncodedMessages(msg, force=0):
    """Given a text-encoded Type III packet, return a list of
       TextEncodedMessage objects or raise ParseError.

          force -- uncompress the message even if it's overcompressed.
    """
    def isBase64(t, f):
        for k, v in f:
            if k == "Message-type":
                if v != 'plaintext':
                    return 1
        return 0

    unarmored = unarmorText(msg, (MESSAGE_ARMOR_NAME, ), base64fn=isBase64)
    res = []
    for tp, fields, val in unarmored:
        d = {}
        for k, v in fields:
            d[k] = v
        if d.get("Message-type", "plaintext") == "plaintext":
            msgType = 'TXT'
        elif d['Message-type'] == 'overcompressed':
            msgType = "LONG"
        elif d['Message-type'] == 'binary':
            msgType = "BIN"
        elif d['Message-type'] == 'encrypted':
            msgType = "ENC"
        elif d['Message-type'] == 'fragment':
            msgType = "FRAG"
        else:
            raise ParseError("Unknown message type: %r" % d["Message-type"])

        ascTag = d.get("Decoding-handle")
        if ascTag:
            msgType = "ENC"

        if msgType == 'LONG' and force:
            val = uncompressData(val)

        if msgType in ('TXT', 'BIN', 'LONG', 'FRAG'):
            res.append(TextEncodedMessage(val, msgType))
        else:
            assert msgType == 'ENC'
            try:
                tag = binascii.a2b_base64(ascTag)
            except (TypeError, binascii.Incomplete, binascii.Error), e:
                raise ParseError("Error in base64 encoding: %s" % e)
            if len(tag) != TAG_LEN:
                raise ParseError("Impossible tag length: %s" % len(tag))
            res.append(TextEncodedMessage(val, 'ENC', tag))
Example #5
0
def _readEncryptedFile(fname, password, magicList):
    """Read encrypted data from the file named 'fname', using the password
       'password' and checking for a magic string contained in 'magicList'.
       Returns the magic string and the plaintext file contents on success.

       If the file is corrupt or the password is wrong, raises BadPassword.
       If the magic is incorrect, raises ValueError.
    """
    assert list(map(len, magicList)) == [8]*len(magicList)

    text = readFile(fname)
    r = unarmorText(text, ["TYPE III KEYRING"])
    if len(r) != 1:
        raise ValueError("Bad ascii armor on keyring")
    tp, headers, s = r[0]
    assert tp == "TYPE III KEYRING"
    vers = [ v for k,v in headers if k == 'Version' ]
    if not vers or vers[0] != '0.1':
        raise ValueError("Unrecognized version on keyring")

    if len(s) < MAGIC_LEN+1 or s[MAGIC_LEN] != '\x00':
        raise ValueError("Unrecognized encryption format on %s"%fname)
    if s[:MAGIC_LEN] not in magicList:
        raise ValueError("Invalid versioning on %s"%fname)
    magic = s[:8]
    s = s[MAGIC_LEN+1:]
    if len(s) < 28:
        raise MixError("File %s is too short."%fname)
    salt = s[:SALT_LEN]
    s = s[SALT_LEN:]
    key = sha1(salt+password+salt)[:AES_KEY_LEN]
    s = ctr_crypt(s, key)
    data = s[:-DIGEST_LEN]
    digest = s[-DIGEST_LEN:]
    if digest != sha1(data+salt+magic):
        raise BadPassword()

    # We've decrypted it; now let's extract the data from the padding.
    if len(data) < 4:
        raise MixError("File %s is too short"%fname)
    length, = struct.unpack("!L", data[:4])
    if len(data) < length+4:
        raise MixError("File %s is too short"%fname)

    return magic, data[4:4+length]
Example #6
0
def _readEncryptedFile(fname, password, magicList):
    """Read encrypted data from the file named 'fname', using the password
       'password' and checking for a magic string contained in 'magicList'.
       Returns the magic string and the plaintext file contents on success.

       If the file is corrupt or the password is wrong, raises BadPassword.
       If the magic is incorrect, raises ValueError.
    """
    assert list(map(len, magicList)) == [8] * len(magicList)

    text = readFile(fname)
    r = unarmorText(text, ["TYPE III KEYRING"])
    if len(r) != 1:
        raise ValueError("Bad ascii armor on keyring")
    tp, headers, s = r[0]
    assert tp == "TYPE III KEYRING"
    vers = [v for k, v in headers if k == 'Version']
    if not vers or vers[0] != '0.1':
        raise ValueError("Unrecognized version on keyring")

    if len(s) < MAGIC_LEN + 1 or s[MAGIC_LEN] != '\x00':
        raise ValueError("Unrecognized encryption format on %s" % fname)
    if s[:MAGIC_LEN] not in magicList:
        raise ValueError("Invalid versioning on %s" % fname)
    magic = s[:8]
    s = s[MAGIC_LEN + 1:]
    if len(s) < 28:
        raise MixError("File %s is too short." % fname)
    salt = s[:SALT_LEN]
    s = s[SALT_LEN:]
    key = sha1(salt + password + salt)[:AES_KEY_LEN]
    s = ctr_crypt(s, key)
    data = s[:-DIGEST_LEN]
    digest = s[-DIGEST_LEN:]
    if digest != sha1(data + salt + magic):
        raise BadPassword()

    # We've decrypted it; now let's extract the data from the padding.
    if len(data) < 4:
        raise MixError("File %s is too short" % fname)
    length, = struct.unpack("!L", data[:4])
    if len(data) < length + 4:
        raise MixError("File %s is too short" % fname)

    return magic, data[4:4 + length]