예제 #1
0
 def fill(self, d):
     self._d = d
     self.version = STN.str2int(d[0:1])
     self.type = STN.str2int(d[1:2])
     self.alg_hash = STN.str2int(d[2:3])
     self.alg_pubkey = STN.str2int(d[3:4])
     self.keyid = STN.str2hex(d[4:12])
     self.nest = STN.str2int(d[12:13])
예제 #2
0
 def testB0BadTypesS2N(self):
     "strnum: str2int bad types"
     for b in self.bad_types:
         try:
             str2int(b)
         except:  # make sure any old exception is raised
             pass
         else:
             raise
예제 #3
0
 def testB0BadTypesS2N(self):
     "strnum: str2int bad types"
     for b in self.bad_types:
         try:
             str2int(b)
         except: # make sure any old exception is raised
             pass
         else:
             raise
예제 #4
0
 def testF01ElGamal(self):
     """crypto.cipher: decrypt_public() ElGamal-encrypted session key"""
     #encmsg_d = read_test_file(['pgpfiles','enc','pub.elg.aes256.clrtxt.gpg'])
     encmsg_d = read_test_file(
         ['pgpfiles', 'enc', 'pub.elg.cast.clrtxt.gpg'])
     encmsg = list_msgs(list_pkts(encmsg_d))[0]
     seskeypkt = encmsg.targets[0]  # target = session key
     # get target secret key (in this case, a subkey)
     keymsg_d = read_test_file(
         ['pgpfiles', 'key', 'DSAELG1.sec.nopass.gpg'])
     keymsg = list_msgs(list_pkts(keymsg_d))[0]
     for block in keymsg._b_subkeys.list():
         subkey = block.leader
         if seskeypkt.body.keyid == subkey.body.id:
             break  # leave with the appropriate subkey
     # I know the target in question is an ElGamal key
     key_tuple = (subkey.body.ELGAMAL_p.value, subkey.body.ELGAMAL_x.value)
     cipher_tuple = (seskeypkt.body.ELGAMAL_gk_modp.value,
                     seskeypkt.body.ELGAMAL_myk_modp.value)
     # retrieving the PKCS, etc., padded session key
     padded_message = decrypt_public(seskeypkt.body.alg_pubkey, key_tuple,
                                     cipher_tuple)
     # Rules from rfc 2437 9.1.2.2:
     # 1. Padding starts with 0x02.
     # 2. Padding continues with >= 8 octets non-zero gibberish.
     # 3. Gibberish concludes with 0x00.
     # 4. Remaining data is the message.
     if '\x02' == padded_message[0]:
         idx = padded_message.find('\x00')
         if -1 != idx and 8 <= idx:
             message = padded_message[idx + 1:]
             chksum = str2int(message[-2:])
             ciphertype = str2int(message[0])
             key = message[1:len(message) - 2]
             i = 0
             for e in key:
                 i += str2int(e)
             # TODO check chksum
             cleartext = decrypt_symmetric(ciphertype, key,
                                           encmsg.encrypted.body.data)
         else:
             errmsg = "Misplaced \\x00 in session key padding, located at index->(%s)" % idx
     else:
         errmsg = "Session key padding must start with \\x02, received->()" % hex(
             ord(padded_message[0]))
     cleartext = cleartext[10:]  # ditching the prefix + 2
     # result is a compressed message..
     compressedmsg = list_msgs(list_pkts(cleartext))[0]
     newmsgs = list_msgs(list_pkts(compressedmsg.compressed.body.data))
     # ..with only one literal data packet
     literal_data = newmsgs[0].literals[0].body.data
     # compare against original file
     clrtxt = read_test_file(['pgpfiles', 'cleartext.txt'])
     self.assertEqual(literal_data, clrtxt)
예제 #5
0
 def testF01ElGamal(self):
     """crypto.cipher: decrypt_public() ElGamal-encrypted session key"""
     #encmsg_d = read_test_file(['pgpfiles','enc','pub.elg.aes256.clrtxt.gpg'])
     encmsg_d = read_test_file(['pgpfiles','enc','pub.elg.cast.clrtxt.gpg'])
     encmsg = list_msgs(list_pkts(encmsg_d))[0]
     seskeypkt = encmsg.targets[0] # target = session key 
     # get target secret key (in this case, a subkey)
     keymsg_d = read_test_file(['pgpfiles','key','DSAELG1.sec.nopass.gpg'])
     keymsg = list_msgs(list_pkts(keymsg_d))[0]
     for block in keymsg._b_subkeys.list():
         subkey = block.leader
         if seskeypkt.body.keyid == subkey.body.id:
             break # leave with the appropriate subkey
     # I know the target in question is an ElGamal key
     key_tuple = (subkey.body.ELGAMAL_p.value, subkey.body.ELGAMAL_x.value)
     cipher_tuple = (seskeypkt.body.ELGAMAL_gk_modp.value, seskeypkt.body.ELGAMAL_myk_modp.value)
     # retrieving the PKCS, etc., padded session key
     padded_message = decrypt_public(seskeypkt.body.alg_pubkey, key_tuple, cipher_tuple)
     # Rules from rfc 2437 9.1.2.2:
     # 1. Padding starts with 0x02.
     # 2. Padding continues with >= 8 octets non-zero gibberish.
     # 3. Gibberish concludes with 0x00.
     # 4. Remaining data is the message.
     if '\x02' == padded_message[0]:
         idx = padded_message.find('\x00')
         if -1 != idx and 8 <= idx:
             message = padded_message[idx+1:]
             chksum = str2int(message[-2:])
             ciphertype = str2int(message[0])
             key = message[1:len(message)-2]
             i = 0
             for e in key:
                 i += str2int(e)
             # TODO check chksum
             cleartext = decrypt_symmetric(ciphertype, key, encmsg.encrypted.body.data)
         else:
             errmsg = "Misplaced \\x00 in session key padding, located at index->(%s)" % idx
     else:
         errmsg = "Session key padding must start with \\x02, received->()" % hex(ord(padded_message[0]))
     cleartext = cleartext[10:] # ditching the prefix + 2
     # result is a compressed message..
     compressedmsg = list_msgs(list_pkts(cleartext))[0]
     newmsgs = list_msgs(list_pkts(compressedmsg.compressed.body.data))
     # ..with only one literal data packet
     literal_data = newmsgs[0].literals[0].body.data
     # compare against original file
     clrtxt = read_test_file(['pgpfiles','cleartext.txt'])
     self.assertEqual(literal_data, clrtxt)
예제 #6
0
파일: Packet.py 프로젝트: Zaryob/wubi
    def fill(self, d):
        """oldlength.fill(d)

        Set the OldLength object's data, filling its attributes.
        Tag data (d) must be either 1, 2, or 4 octets containing
        the length (integer count) of the packet body
        (see rfc2004 4.2.1).

        :Parameters:
            - `d`: character (StringType, length == 1)

        :Returns: Nothing

        Example:

            >>> oldlength_octets = [0x88, 0x88]
            >>> oldlength_data_string = ''.join(map(chr, oldlength_octets))
            >>> oldlength = OldLength()
            >>> oldlength.fill(oldlength_data_string)
            >>> oldlength.size
            34952
        """
        if len(d) in [1, 2, 4]:
            self._d, self.size = d, STN.str2int(d)
        elif 0 == len(d):
            self._d, self.size = '', "UNDEFINED"
        else:
            raise PGPFormatError, "Old packet length data must come in 0, 1, 2, or 4 octets. Received->(%s octets)." % (
                str(len(d)))
예제 #7
0
    def fill(self, d):
        """oldlength.fill(d)

        Set the OldLength object's data, filling its attributes.
        Tag data (d) must be either 1, 2, or 4 octets containing
        the length (integer count) of the packet body
        (see rfc2004 4.2.1).
        
        :Parameters:
            - `d`: character (StringType, length == 1)

        :Returns: Nothing

        Example:

            >>> oldlength_octets = [0x88, 0x88]
            >>> oldlength_data_string = ''.join(map(chr, oldlength_octets))
            >>> oldlength = OldLength()
            >>> oldlength.fill(oldlength_data_string)
            >>> oldlength.size
            34952
        """
        if len(d) in [1, 2, 4]:
            self._d, self.size = d, STN.str2int(d)
        elif 0 == len(d):
            self._d, self.size = '', "UNDEFINED"
        else:
            raise PGPFormatError, "Old packet length data must come in 0, 1, 2, or 4 octets. Received->(%s octets)." % (str(len(d)))
예제 #8
0
 def test01_int2str_str2int(self):
     "strnum: string/integer inversion (int2str/str2int)"
     body = self.key.body
     for i in [
             body.DSA_p.value, body.DSA_q.value, body.DSA_g.value,
             body.DSA_y.value
     ]:
         self.assertEqual(i, str2int(int2str(i)))
예제 #9
0
    def fill(self, d):
        self._d = d
        version_d = d[0]
        self.version, idx = STN.strcalc(STN.str2int, d[0], 0)

        if self.version in [2, 3]:
            hash_len, idx = STN.strcalc(STN.str2int, d[idx:idx+1], idx)
            self.type, idx = STN.strcalc(STN.str2int, d[idx:idx+1], idx)
            self.created, idx = STN.strcalc(STN.str2int, d[idx:idx+4], idx)
            self.hashed_data = d[2:idx]
            self.keyid, idx = STN.strcalc(STN.str2hex, d[idx:idx+8], idx)
            self.alg_pubkey, idx = STN.strcalc(STN.str2int, d[idx:idx+1], idx)
            self.alg_hash, idx = STN.strcalc(STN.str2int, d[idx:idx+1], idx)
            self.hashed_subpkts = [] # dummy settings to make searches easier
            self.unhashed_subpkts = [] #

        elif 4 == self.version:
            import struct
            _type_d, idx = STN.strcalc(None, d[idx:idx+1], idx)
            self.type = STN.str2int(_type_d)
            self.alg_pubkey, idx = STN.strcalc(STN.str2int, d[idx:idx+1], idx)
            self.alg_hash, idx = STN.strcalc(STN.str2int, d[idx:idx+1], idx)
            # hashed subpackets
            subpkts_len, idx = STN.strcalc(STN.str2int, d[idx:idx+2], idx)
            self.hashed_subpkts = self.__resolve_subpkts(d[idx:idx+subpkts_len])
            # hashed data & trailer - should '>i' ever return more than 4 chars?
            hashed_data = d[0:idx+subpkts_len]
            bigend = struct.pack('>i', len(hashed_data))[-4:] 
            self.hashed_data = ''.join([hashed_data, version_d, '\xff', bigend])
            idx = idx + subpkts_len
            # unhashed subpackets
            subpkts_len, idx = STN.strcalc(STN.str2int, d[idx:idx+2], idx)
            self.unhashed_subpkts = self.__resolve_subpkts(d[idx:idx+subpkts_len])
            idx = idx + subpkts_len
            # attribute convenience
            self.keyid = self.__set_subpkt_attr(SIGSUB_SIGNERID) or ''
            self.created = self.__set_subpkt_attr(SIGSUB_CREATED) or 0

        else:
            raise PGPValueError("Unsupported signature version. Received->(%s)" % str(self.version))

        self.hash_frag, idx = STN.strcalc(None, d[idx:idx+2], idx)

        if self.alg_pubkey in [ASYM_RSA_S, ASYM_RSA_EOS]:
            self.RSA, idx = MPI.strcalc_mpi(d[idx:], idx)

        elif ASYM_DSA == self.alg_pubkey:
            self.DSA_r, idx = MPI.strcalc_mpi(d[idx:], idx)
            self.DSA_s, idx = MPI.strcalc_mpi(d[idx:], idx)

        elif self.alg_pubkey in [ASYM_ELGAMAL_EOS]:
            self.ELGAMAL_a, idx = MPI.strcalc_mpi(d[idx:], idx)
            self.ELGAMAL_b, idx = MPI.strcalc_mpi(d[idx:], idx)

        else:
            raise PGPValueError("Unsupported public-key algorithm (%d)." % self.alg_pubkey)
예제 #10
0
파일: MPI.py 프로젝트: Ando02/wubiuefi
    def fill(self, d):
        import struct
        idx = 0
        self._length_d, idx = STN.strcalc(None, d[idx:idx+2], idx)

        self.bit_length = STN.str2int(self._length_d)
        self.length = STN.mpilen2int(self._length_d)

        self._d = d[0:2+self.length]
        self._int_d = d[idx:idx+self.length]
        self.size = len(self._d) # explicitly..

        i = struct.unpack('>'+str(len(self._int_d))+'s', self._int_d)[0]
        self.value = STN.str2int(i) 

        if self.check():
            pass
        else:
            raise self.err[0], self.err[1]
예제 #11
0
    def fill(self, d):
        import struct
        idx = 0
        self._length_d, idx = STN.strcalc(None, d[idx:idx + 2], idx)

        self.bit_length = STN.str2int(self._length_d)
        self.length = STN.mpilen2int(self._length_d)

        self._d = d[0:2 + self.length]
        self._int_d = d[idx:idx + self.length]
        self.size = len(self._d)  # explicitly..

        i = struct.unpack('>' + str(len(self._int_d)) + 's', self._int_d)[0]
        self.value = STN.str2int(i)

        if self.check():
            pass
        else:
            raise self.err[0], self.err[1]
예제 #12
0
파일: LiteralData.py 프로젝트: Zaryob/wubi
    def fill(self, d):
        self._d = d
        self.format = d[0:1]
        self.fnlen = STN.str2int(d[1:2])
        idx = 2

        if 0 < self.fnlen:
            self.filename, idx = STN.strcalc(None, d[idx:idx+self.fnlen], idx)
        else:
            self.filename = None

        self.modified, idx = STN.strcalc(STN.str2int, d[idx:idx+4], idx)
        self.data = d[idx:]
예제 #13
0
파일: crypto.py 프로젝트: Ando02/wubiuefi
def encrypt_public(algorithm, msg, key_tuple):
    """Encrypt data to a public key.

    :Parameters:
        - `algorithm`: integer public key algorithm constant
        - `key_tuple`: tuple containing a public and private integers
          the target key, RSA values (n, d) or ElGamal values (p, g, y)
          (see `RSA key tuple`_ and `ElGamal key tuple`_)

    :Returns: tuple ciphertext (a, b) for ElGamal and (r,) for RSA

    .. _RSA key tuple:

    RSA key tuple (n, e):

        - `n`: integer RSA product of primes p & q
        - `e`: integer RSA encryption key
    
    .. _ElGamal key tuple:

    ElGamal key tuple (p, g, y):
                
        - `p`: integer ElGamal prime
        - `g`: integer ElGamal group generator
        - `y`: integer ElGamal public key
    """
    import Crypto.Util.number

    key_tuple = tuple([long(i) for i in key_tuple]) # fastmath dep

    if algorithm in [ASYM_RSA_EOS, ASYM_RSA_E]:
        from Crypto.PublicKey import RSA

        key = RSA.construct(key_tuple)
        k = ''

    elif algorithm in [ASYM_ELGAMAL_EOS, ASYM_ELGAMAL_E]:
        from Crypto.PublicKey import ElGamal

        key = ElGamal.construct(key_tuple)
        k = Crypto.Util.number.getPrime(128, gen_random)

    else:
        raise NotImplementedError, "Can't handle public encryption algorithm->(%s)" % algorithm

    enc_tup = key.encrypt(msg, k) # Crypto returns strings instead of integers.

    return tuple([STN.str2int(x) for x in enc_tup]) # Why?
예제 #14
0
def str2mpi(s, limit):
    """Convert a MPI byte-string into an integer.

    :Parameters:
        - `s`: MPI string
        - `limit`: *optional* maximum number of MPIs to search for

    :Returns: list of MPI values (integers/longs)
    """
    import struct

    idx = 0
    mpi_list = []

    while True:

        if limit and limit == len(mpi_list):
            break

        mpilen_d, idx = read_slice(s, 2, idx)

        if 2 == len(mpilen_d):
            # we don't care about bit length, just the bytes containing them
            mpilen = mpilen2int(mpilen_d)
            int_d, idx = read_slice(s, mpilen, idx)
            len_int_d = len(int_d)

            if len_int_d == mpilen:
                i = struct.unpack('>' + str(len_int_d) + 's', int_d)[0]
                mpival = str2int(i)
                mpi_list.append(mpival)

                continue  # if good, keep going

        break  # otherwise quit

    return mpi_list, idx
예제 #15
0
def svt_int():
    str2val = lambda string, limit: str2int(string[:limit])
    val2str = lambda value, limit: _limit_int2str(value, limit)
    return str2val, val2str
 def fill(self, d):
     self._d = d
     self.version = STN.str2int(d[0:1])
     self.data = d[1:]
예제 #17
0
파일: Signature.py 프로젝트: Zaryob/wubi
    def fill(self, d):
        ord_d = ord(d[0])

        if ord_d < 192:
            slice = d[0]
            size = ord_d

        elif 192 <= ord_d < 255:
            slice = d[:2]
            #size = size + STN.doubleoct2int(slice)
            size = STN.doubleoct2int(slice)

        elif 255 == ord_d:
            slice = d[:5]
            #size = size + STN.pentoct2int(slice)
            size = STN.pentoct2int(slice)

        len_slice = len(slice)
        self._d = d[:len_slice + size]
        type_d = d[len_slice:len_slice + 1]
        self.type = 127 & ord(type_d)
        self.critical = 128 & ord(type_d)
        value_d = d[len_slice + 1:len_slice + size]

        if SIGSUB_SIGNERID == self.type:
            self.value = STN.str2hex(value_d[:8])

        elif self.type in [SIGSUB_CREATED, SIGSUB_EXPIRES, SIGSUB_KEYEXPIRES]:
            self.value = STN.str2int(value_d[:4])
            self.value = STN.str2int(value_d)

        elif self.type in [
                SIGSUB_EXPORTABLE, SIGSUB_REVOCABLE, SIGSUB_PRIMARYUID
        ]:
            self.value = STN.str2int(value_d[:1])

            if self.value not in [0, 1]:
                raise SignatureSubpacketValueError, "Subpacket (# %s) value must be 0 or 1." % (
                    str(subtype))

        elif SIGSUB_TRUST == self.type:  # level, amount
            self.value = (STN.str2int(value_d[0]), STN.str2int(value_d[1]))

        elif self.type in [
                SIGSUB_SYMCODE, SIGSUB_HASHCODE, SIGSUB_COMPCODE,
                SIGSUB_KEYSERVPREFS, SIGSUB_KEYFLAGS, SIGSUB_FEATURES
        ]:
            self.value = [ord(x) for x in value_d]

        elif SIGSUB_REVOKER == self.type:
            cls = STN.str2int(value_d[0])
            alg = STN.str2int(value_d[1])
            fprint = STN.str2hex(value_d[2:22])
            self.value = (cls, alg, fprint)

        elif SIGSUB_NOTE == self.type:
            flags = [STN.str2int(x)
                     for x in value_d[:4]]  # first four flag octs
            name_len = STN.str2int(value_d[4:6])
            val_len = STN.str2int(value_d[6:8])
            nam = value_d[8:8 + name_len]
            val = value_d[8 + name_len:8 + name_len + val_len]
            self.value = (flags, nam, val)

        elif self.type in [
                SIGSUB_KEYSERV, SIGSUB_POLICYURL, SIGSUB_SIGNERUID,
                SIGSUB_REGEX
        ]:
            self.value = value_d

        elif SIGSUB_REVOCREASON == self.type:  # code, reason
            self.value = (STN.str2int(value_d[0]), value_d[1:])

        elif SIGSUB_SIGTARGET == self.type:
            raise NotImplementedError, "SIGTARGET not supported"

        else:  # the subpacket has an unknown type, so just pack the data in
            self.value = value_d
예제 #18
0
파일: crypto.py 프로젝트: Ando02/wubiuefi
def decrypt_secret_key(keypkt, passphrase=''):
    """Retrieve decryption key values from a secret key packet.

    :Parameters:
        - `keypkt`: `OpenPGP.packet.SecretKey.SecretKey` instance or
          `OpenPGP.packet.SecretSubkey.SecretSubkey` instance
        - `passphrase`: optional decryption string

    :Returns: tuple of secret key integer values

    :Exceptions:
        - `PGPKeyDecryptionFailure`: secret key values did not encrypt
          properly

    Secret key tuples:
        - RSA keys: (d, p, q, u)
        - ElGamal keys: (x, )
        - DSA keys: (x, )

    :note: As far as key decryption goes, the only real check performed is the
        internal MPI check that the header, size, etc. make sense. Chances are
        slight that a failed decryption will render sensible MPIs. This is why
        the integrity checks are so important.
    """
    if not hasattr(keypkt.body, 's2k_usg'):
        raise PGPCryptoError("Key material does not contain secret key values (missing s2k usage).")

    if 0 == keypkt.body.s2k_usg:
        if keypkt.body.alg in [ASYM_RSA_E, ASYM_RSA_EOS]:
            key_tuple = (keypkt.body.RSA_d.value, keypkt.body.RSA_p.value, keypkt.body.RSA_q.value, keypkt.body.RSA_u.value)
        elif keypkt.body.alg in [ASYM_ELGAMAL_E, ASYM_ELGAMAL_EOS]:
            key_tuple = keypkt.body.ELGAMAL_x.value, # coerce tuple
        elif keypkt.body.alg in [ASYM_DSA]:
            key_tuple = keypkt.body.DSA_x.value, # coerce tuple

    else: # ..'idx' comes into play during the integrity check

        if 3 >= keypkt.body.version:

            if keypkt.body.alg in [ASYM_RSA_E, ASYM_RSA_EOS]:
                alg = keypkt.body.alg_sym

                if keypkt.body.s2k_usg in [254, 255]:
                    k = string2key(keypkt.body.s2k, alg, passphrase)

                else:
                    k = md5.new(passphrase).digest()

                # extra work required since MPIs integers are encrypted w/out
                # their lengths
                # create MPIs w/ encrypted integer octets 
                secRSA_d, idx = MPI.strcalc_mpi(keypkt.body._enc_d, 0)
                secRSA_p, idx = MPI.strcalc_mpi(keypkt.body._enc_d, idx)
                secRSA_q, idx = MPI.strcalc_mpi(keypkt.body._enc_d, idx)
                secRSA_u, idx = MPI.strcalc_mpi(keypkt.body._enc_d, idx)
                # decrypt integer octets
                RSA_d_int_d = decrypt_symmetric(alg, k, secRSA_d._int_d, keypkt.body.iv)
                RSA_p_int_d = decrypt_symmetric(alg, k, secRSA_d._int_d, keypkt.body.iv)
                RSA_q_int_d = decrypt_symmetric(alg, k, secRSA_d._int_d, keypkt.body.iv)
                RSA_u_int_d = decrypt_symmetric(alg, k, secRSA_d._int_d, keypkt.body.iv)
                # translate integer values
                RSA_d_value = STN.str2int(RSA_d_int_d)
                RSA_p_value = STN.str2int(RSA_p_int_d)
                RSA_q_value = STN.str2int(RSA_q_int_d)
                RSA_u_value = STN.str2int(RSA_u_int_d)

                key_tuple = (RSA_d_value, RSA_p_value, RSA_q_value, RSA_u_value)
                sec_d = ''.join([secRSA_d._d[:2], RSA_d_int_d, secRSA_p._d[:2], RSA_p_int_d, secRSA_q._d[:2], RSA_q_int_d, secRSA_q._d[:2], RSA_q_int_d])
            else:
                raise NotImplementedError("Unsupported v3 decryption key algorithm->(%s)." % keypkt.body.alg)

        elif 4 == keypkt.body.version:
            alg = keypkt.body.alg_sym
            k = string2key(keypkt.body.s2k, alg, passphrase)
            sec_d = decrypt_symmetric(alg, k, keypkt.body._enc_d, keypkt.body.iv)

            if keypkt.body.alg in [ASYM_RSA_E, ASYM_RSA_EOS, ASYM_RSA_S]:
                RSA_d, idx = MPI.strcalc_mpi(sec_d, 0)
                RSA_p, idx = MPI.strcalc_mpi(sec_d[idx:], idx)
                RSA_q, idx = MPI.strcalc_mpi(sec_d[idx:], idx)
                RSA_u, idx = MPI.strcalc_mpi(sec_d[idx:], idx)
                key_tuple = (RSA_d.value, RSA_p.value, RSA_q.value, RSA_u.value)

            elif keypkt.body.alg in [ASYM_ELGAMAL_E, ASYM_ELGAMAL_EOS]:
                ELGAMAL_x, idx = MPI.strcalc_mpi(sec_d, 0)
                key_tuple = ELGAMAL_x.value, # coerce tuple

            elif keypkt.body.alg in [ASYM_DSA]:
                DSA_x, idx = MPI.strcalc_mpi(sec_d, 0)
                key_tuple = DSA_x.value, # coerce tuple

            else:
                raise NotImplementedError("Unsupported public key algorithm->(%s)." % keypkt.body.alg)

        else:
            raise NotImplementedError, "Unsupported key version->(%s)." % keypkt.body.version

        # check integrity
        if 254 == keypkt.body.s2k_usg:

            if sec_d[idx:] != sha.new(sec_d[:idx]).digest():
                raise PGPCryptoError("Integrity hash check failed.")

        elif 255 == keypkt.body.s2k_usg:

            if keypkt.body.chksum != STN.checksum(sec_d):
                raise PGPCryptoError("Integrity checksum failed.")

    return key_tuple
예제 #19
0
파일: crypto.py 프로젝트: Ando02/wubiuefi
def decrypt(encpkt, passphrase='', sespkt=None, keypkt=None):
    """Decrypt messages in symmetrically encrypted packets (types 9 & 18).

    :Parameters:
        - `encpkt`: packet containing encrypted data (symmetrically
          encrypted or integrity protected packet, types 9 & 18)
        - `passphrase`: string decryption passphrase (see below)
        - `sespkt`: optional session key packet
        - `keypkt`: optional public key packet

    :Returns: string cleartext

    :Exceptions:
        - `PGPError`: implementation error
        - `PGPDecryptionFailure`: decryption failed
        - `PGPSessionDecryptionFailure`: session decryption failed

    This is the all-in-one handler for "normal" decryption - that is,
    decrypting symmetrically encrypted (type 9) and symmetrically
    encrypted integrity protected (type 18) data. By consolidating 
    everything to one function it will be easier (hopefully) to manage
    secure data handling in the future.

    Because this function focuses on decrypting information in packet
    types 9 and 18, decrypted data is by definition (or "will be", due
    to the mechanics of this function) the data used to build an
    OpenPGP message (not the message instance). It is up to the API
    layer to automate things like "if compressed, decompress" or "if
    signed, verify."
    """
    result = key = algorithm = None # key & algo set to force integrity failure 

    if sespkt:
        ses = sespkt.body

        if PKT_PUBKEYSESKEY == sespkt.tag.type:

            if ses.keyid == keypkt.body.id:

                try:
                    seckeys = decrypt_secret_key(keypkt, passphrase)

                except PGPError: # catch MPI value error due to ..
                    raise PGPCryptoError("Public key encrypted session key checksum failed.")

                if keypkt.body.alg in [ASYM_RSA_E, ASYM_RSA_EOS]:
                    cipher_tuple = (ses.RSA_me_modn.value,)
                    key_tuple = (keypkt.body.RSA_n.value, seckeys[0])

                elif keypkt.body.alg in [ASYM_ELGAMAL_E, ASYM_ELGAMAL_EOS]:
                    cipher_tuple = (ses.ELGAMAL_gk_modp.value, ses.ELGAMAL_myk_modp.value)
                    key_tuple = (keypkt.body.ELGAMAL_p.value, seckeys[0])

                else:
                    raise NotImplementedError("Unsupported public encryption algorithm->(%s)." % keypkt.body.alg)

            else: # shouldn't happen, programmer error
                raise PGPCryptoError("The public encryption key did not match the session key target.")

            # should be ready to decrypt session key with key tuple
            padded_key = decrypt_public(ses.alg_pubkey, key_tuple, cipher_tuple)

            if '\x02' == padded_key[0]: # handle EME-PKCS1-v1_5 encoding
                idx = padded_key.find('\x00') # 0x00 used as padding separator

                if -1 != idx and 8 <= idx:
                    message = padded_key[idx+1:]
                    algorithm = STN.str2int(message[0]) # required for both..
                    chksum = STN.str2int(message[-2:])
                    key = message[1:len(message)-2] # ..symencdata and symencintdata

                    if chksum != STN.checksum(key):
                        raise PGPCryptoError("Public Key encrypted session key checksum failed.")

                else:
                    raise PGPCryptoError("Misplaced \\x00 in session key padding, located at index->(%s)." % idx)

            else:
                raise PGPCryptoError("Session key didn't start with \\x02, received->()." % hex(ord(padded_key[0])))

        elif PKT_SYMKEYSESKEY == sespkt.tag.type: # using symmetric key session key
            algorithm = ses.alg
            key = string2key(ses.s2k, algorithm, passphrase)

            if ses.has_key:
                iv = STN.prepad(_import_cipher(algorithm).block_size)
                padded_key = decrypt_symmetric(algorithm, key, ciphertext, iv)
                algorithm = padded_key[0]
                key = padded_key[1:]

        else:
            raise NotImplementedError("Unrecognized session key type-(%s)." % sespkt.tag.type)

    # 'algorithm' & 'key' should be set, it's time to decrypt the message
    if PKT_SYMENCINTDATA == encpkt.tag.type:
        bs = _import_cipher(algorithm).block_size
        iv = STN.prepad(bs)
        cleartext = decrypt_symmetric(algorithm, key, encpkt.body.data, iv)
        prefix = cleartext[:bs+2]
        clearmsg_d = cleartext[bs+2:-22]
        mdc_d = cleartext[-22:]
        mdc = mdc_d[-20:]

        if mdc != sha.new(''.join([prefix, clearmsg_d, '\xd3\x14'])).digest():
            raise PGPCryptoError("Integrity hash check failed.")

    elif PKT_SYMENCDATA == encpkt.tag.type:

        if None == key == algorithm: # non-integrity allows default key & alg
            key = md5.new(passphrase).digest
            algorithm = SYM_IDEA

        clearmsg_d = decrypt_symmetric_resync(algorithm, key, encpkt.body.data)

    return clearmsg_d
예제 #20
0
파일: Signature.py 프로젝트: Zaryob/wubi
    def fill(self, d):
        self._d = d
        version_d = d[0]
        self.version, idx = STN.strcalc(STN.str2int, d[0], 0)

        if self.version in [2, 3]:
            hash_len, idx = STN.strcalc(STN.str2int, d[idx:idx + 1], idx)
            self.type, idx = STN.strcalc(STN.str2int, d[idx:idx + 1], idx)
            self.created, idx = STN.strcalc(STN.str2int, d[idx:idx + 4], idx)
            self.hashed_data = d[2:idx]
            self.keyid, idx = STN.strcalc(STN.str2hex, d[idx:idx + 8], idx)
            self.alg_pubkey, idx = STN.strcalc(STN.str2int, d[idx:idx + 1],
                                               idx)
            self.alg_hash, idx = STN.strcalc(STN.str2int, d[idx:idx + 1], idx)
            self.hashed_subpkts = []  # dummy settings to make searches easier
            self.unhashed_subpkts = []  #

        elif 4 == self.version:
            import struct
            _type_d, idx = STN.strcalc(None, d[idx:idx + 1], idx)
            self.type = STN.str2int(_type_d)
            self.alg_pubkey, idx = STN.strcalc(STN.str2int, d[idx:idx + 1],
                                               idx)
            self.alg_hash, idx = STN.strcalc(STN.str2int, d[idx:idx + 1], idx)
            # hashed subpackets
            subpkts_len, idx = STN.strcalc(STN.str2int, d[idx:idx + 2], idx)
            self.hashed_subpkts = self.__resolve_subpkts(d[idx:idx +
                                                           subpkts_len])
            # hashed data & trailer - should '>i' ever return more than 4 chars?
            hashed_data = d[0:idx + subpkts_len]
            bigend = struct.pack('>i', len(hashed_data))[-4:]
            self.hashed_data = ''.join(
                [hashed_data, version_d, '\xff', bigend])
            idx = idx + subpkts_len
            # unhashed subpackets
            subpkts_len, idx = STN.strcalc(STN.str2int, d[idx:idx + 2], idx)
            self.unhashed_subpkts = self.__resolve_subpkts(d[idx:idx +
                                                             subpkts_len])
            idx = idx + subpkts_len
            # attribute convenience
            self.keyid = self.__set_subpkt_attr(SIGSUB_SIGNERID) or ''
            self.created = self.__set_subpkt_attr(SIGSUB_CREATED) or 0

        else:
            raise PGPValueError(
                "Unsupported signature version. Received->(%s)" %
                str(self.version))

        self.hash_frag, idx = STN.strcalc(None, d[idx:idx + 2], idx)

        if self.alg_pubkey in [ASYM_RSA_S, ASYM_RSA_EOS]:
            self.RSA, idx = MPI.strcalc_mpi(d[idx:], idx)

        elif ASYM_DSA == self.alg_pubkey:
            self.DSA_r, idx = MPI.strcalc_mpi(d[idx:], idx)
            self.DSA_s, idx = MPI.strcalc_mpi(d[idx:], idx)

        elif self.alg_pubkey in [ASYM_ELGAMAL_EOS]:
            self.ELGAMAL_a, idx = MPI.strcalc_mpi(d[idx:], idx)
            self.ELGAMAL_b, idx = MPI.strcalc_mpi(d[idx:], idx)

        else:
            raise PGPValueError("Unsupported public-key algorithm (%d)." %
                                self.alg_pubkey)
예제 #21
0
 def testC4Inversion(self):
     """strnum: number to string inversion (int2quadoct/str2int())"""
     for o in self.good_nums:
         self.assertEqual(o[0], str2int(int2quadoct(o[0])))
예제 #22
0
 def testC0TranslationS2N(self):
     """strnum: str2int output"""
     for v in self.good_strings:
         self.assertEqual(v[1], str2int(v[0]))
예제 #23
0
 def testC0TranslationS2N(self):
     """strnum: str2int output"""
     for v in self.good_strings:
         self.assertEqual(v[1], str2int(v[0]))
예제 #24
0
 def test01_int2str_str2int(self):
     "strnum: string/integer inversion (int2str/str2int)"
     body = self.key.body
     for i in [body.DSA_p.value, body.DSA_q.value, body.DSA_g.value, body.DSA_y.value]:
         self.assertEqual(i, str2int(int2str(i)))
예제 #25
0
    def fill(self, d):
        ord_d = ord(d[0])

        if ord_d < 192:
            slice = d[0]
            size = ord_d

        elif 192 <= ord_d < 255:
            slice = d[:2]
            #size = size + STN.doubleoct2int(slice)
            size = STN.doubleoct2int(slice)

        elif 255 == ord_d:
            slice = d[:5]
            #size = size + STN.pentoct2int(slice)
            size = STN.pentoct2int(slice)

        len_slice = len(slice)
        self._d = d[:len_slice+size]
        type_d = d[len_slice:len_slice+1]
        self.type = 127 & ord(type_d)
        self.critical = 128 & ord(type_d)
        value_d = d[len_slice+1:len_slice+size]

        if SIGSUB_SIGNERID == self.type:
            self.value = STN.str2hex(value_d[:8])

        elif self.type in [SIGSUB_CREATED, SIGSUB_EXPIRES, SIGSUB_KEYEXPIRES]:
            self.value = STN.str2int(value_d[:4])            
            self.value = STN.str2int(value_d)            

        elif self.type in [SIGSUB_EXPORTABLE, SIGSUB_REVOCABLE, SIGSUB_PRIMARYUID]:
            self.value = STN.str2int(value_d[:1])

            if self.value not in [0, 1]:
                raise SignatureSubpacketValueError, "Subpacket (# %s) value must be 0 or 1." % (str(subtype))

        elif SIGSUB_TRUST == self.type: # level, amount
            self.value = (STN.str2int(value_d[0]), STN.str2int(value_d[1]))

        elif self.type in [SIGSUB_SYMCODE, SIGSUB_HASHCODE, SIGSUB_COMPCODE, SIGSUB_KEYSERVPREFS, SIGSUB_KEYFLAGS, SIGSUB_FEATURES]:
            self.value = [ord(x) for x in value_d]

        elif SIGSUB_REVOKER == self.type:
            cls = STN.str2int(value_d[0])
            alg = STN.str2int(value_d[1])
            fprint = STN.str2hex(value_d[2:22])
            self.value = (cls, alg, fprint)

        elif SIGSUB_NOTE == self.type:
            flags = [STN.str2int(x) for x in value_d[:4]] # first four flag octs
            name_len = STN.str2int(value_d[4:6])
            val_len = STN.str2int(value_d[6:8])
            nam = value_d[8:8+name_len]
            val = value_d[8+name_len:8+name_len+val_len]
            self.value = (flags, nam, val)

        elif self.type in [SIGSUB_KEYSERV, SIGSUB_POLICYURL, SIGSUB_SIGNERUID, SIGSUB_REGEX]:
            self.value = value_d

        elif SIGSUB_REVOCREASON == self.type: # code, reason
            self.value = (STN.str2int(value_d[0]), value_d[1:])

        elif SIGSUB_SIGTARGET == self.type:
            raise NotImplementedError, "SIGTARGET not supported"

        else: # the subpacket has an unknown type, so just pack the data in
            self.value = value_d
예제 #26
0
 def fill(self, d):
     self._d = d
     self.version = STN.str2int(d[0:1])
     self.data = d[1:]
예제 #27
0
 def testC4Inversion(self):
     """strnum: number to string inversion (int2quadoct/str2int())"""
     for o in self.good_nums:
         self.assertEqual(o[0], str2int(int2quadoct(o[0])))