def create_OnePassSignatureBody(*args, **kwords): """Create a OnePassSignatureBody instance. :Parameters: - `args`: ordered parameters - `kwords`: parameter keywords :Returns: `OnePassSignatureBody` instance Parameter keywords: `sigtype`: integer signature type constant `alg_hash`: integer hash algorithm constant `alg_pubkey`: integer public key algorithm constant `keyid`: string 16-character hex signing key ID `nest`: integer nested status `version`: integer one-pass version """ if 0 < len(args) and isinstance(args[0], dict): kwords = args[0] sigtype = kwords.get('sigtype') alg_hash = kwords.get('alg_hash') alg_pubkey = kwords.get('alg_pubkey') keyid = kwords.get('keyid') nest = kwords.get('nest') version = kwords.setdefault('version', 3) errmsg = None version_d = STN.int2str(version) if 1 < len(version_d): errmsg = "One-pass version length (%s octs) exceeded 1 octet limit." % len(version_d) sigtype_d = STN.int2str(sigtype) if 1 < len(sigtype_d): errmsg = "One-pass sigtype length (%s octs) exceeded 1 octet limit." % len(type_d) alg_hash_d = STN.int2str(alg_hash) if 1 < len(alg_hash_d): errmsg = "One-pass hash algorithm length (%s octs) exceeded 1 octet limit." % len(alg_hash_d) alg_pubkey_d = STN.int2str(alg_pubkey) if 1 < len(alg_pubkey_d): errmsg = "One-pass public key algorithm length (%s octs) exceeded 1 octet limit." % len(alg_pubkey_d) keyid_d = STN.hex2str(keyid) if 8 != len(keyid_d): errmsg = "One-pass key ID should be a 16 octet (not %s octs) hex string." % len(keyid) nest_d = STN.int2str(nest) if 1 < len(nest_d): errmsg = "One-pass nest length (%s octs) exceeded 1 octet limit." % len(nest_d) if errmsg: raise PGPValueError(errmsg) d = ''.join([version_d, sigtype_d, alg_hash_d, alg_pubkey_d, keyid_d, nest_d]) return OnePassSignatureBody(d)
def create_PublicKeyEncryptedSessionKeyBody(*args, **kwords): """ """ try: kwords = args[0] except IndexError: pass version = '\x03' keyid = STN.hex2str(kwords['keyid']) algorithm = STN.int2str(kwords['alg'])[0] if kwords['alg'] in [ASYM_RSA_EOS, ASYM_RSA_E, ASYM_RSA_S]: mpi_d = MPI.create_MPI(kwords['mpis'][0])._d elif ASYM_ELGAMAL_E == kwords['alg']: a_d = MPI.create_MPI(kwords['mpis'][0])._d b_d = MPI.create_MPI(kwords['mpis'][1])._d mpi_d = ''.join([a_d, b_d]) else: raise PGPValueError, "Unsupported public key algorithm. Received alg->(%s)" % alg _d = ''.join([version, keyid, algorithm, mpi_d]) return PublicKeyEncryptedSessionKeyBody(_d)
def test02_str2hex_hex2str(self): "strnum: string/hex inversion (str2hex/hex2str)" fprint = self.key.body.fingerprint xprint = str2hex(hex2str(fprint)) self.assertEqual(fprint, xprint)
def create_SignatureSubpacket(type, value): """Create a SignatureSubpacket instance. :Parameters: - `type`: integer signature subpacket type constant (see `OpenPGP.constant.signatures`) - `value`: variable value depending on `type` (see `Subpacket types and values`_) :Returns: `SignatureSubpacket` instance .. _Subpacket types and values: Subpacket types and values: - ``SIGSUB_SIGNERID``: hex key ID string (16 octets) - ``SIGSUB_CREATED``: integer timestamp of signature creation(must resolve to 4 or less octets, restricting value to less than 4294967296) - ``SIGSUB_EXPIRES``, ``SIGSUB_KEYEXPIRES``: integer time past creation of signature or key expiration (must resolve to 4 or less octets, restricting value to less than 4294967296) - ``SIGSUB_EXPORTABLE``, `SIGSUB_REVOCABLE``, ``SIGSUB_PRIMARYUID``: integer 1 or 0 for True or False - ``SIGSUB_TRUST``: tuple(integer level, integer amount) - ``SIGSUB_SYMCODE``, ``SIGSUB_HASHALGS``, ``SIGSUB_COMPALGS``, ``SIGSUB_KEYSERVPREFS``, ``SIGSUB_KEYFLAGS``, ``SIGSUB_FEATURES``: list of integers, see rfc2440 for specifics - ``SIGSUB_REVOKER``: tuple(integer class, integer algorithm, string 40 octet caps hex SHA1 fingerprint hash string - ``SIGSUB_NOTATION``: tuple([list of 4 flags], string name, string value) see rfc2440 for specifics, list of flags may be replaced with None for basic text notation [0x80, 0x0, 0x0, 0x0] - ``SIGSUB_KEYSERV``, ``SIGSUB_POLICYURL``, ``SIGSUB_SIGNERUID``, ``SIGSUB_REGEX``: string see rfc2440 for specifics - ``SIGSUB_REVOCREASON``: tuple (integer code, string reason) - ``SIGSUB_SIGTARGET``: Not Implemented """ from Packet import create_NewLength # set value_d if SIGSUB_SIGNERID == type: value_d = STN.hex2str(value) if len(value_d) != 8: raise SignatureSubpacketValueError( "Length of subpacket key id (%s) is not 8 octets." % len(value)) elif type in [SIGSUB_CREATED, SIGSUB_EXPIRES, SIGSUB_KEYEXPIRES]: value_d = STN.int2str(value) while len(value_d) < 4: value_d = '\x00' + value_d if len(value_d) > 4: raise SignatureSubpacketValueError( "Length of subpacket time (%s) exceeds 4 octet limit." % len(value_d)) elif type in [SIGSUB_EXPORTABLE, SIGSUB_REVOCABLE, SIGSUB_PRIMARYUID]: if value not in [0, 1]: raise SignatureSubpacketValueError( "Subpacket (# %s) value must be 0 or 1." % (str(subtype))) else: value_d = STN.int2str(value) elif SIGSUB_TRUST == type: # level, amount value_d = STN.int2str(value[0]) + STN.int2str(value[1]) elif type in [ SIGSUB_SYMCODE, SIGSUB_HASHCODE, SIGSUB_COMPCODE, SIGSUB_KEYSERVPREFS, SIGSUB_KEYFLAGS, SIGSUB_FEATURES ]: value_d = ''.join([STN.int2str(x) for x in value]) elif SIGSUB_REVOKER == type: # value_d = STN.int2str(value[0]) + STN.int2str(value[1]) + STN.hex2str( value[2]) elif SIGSUB_NOTE == type: # [f1, f2, f3, f4], name, value # TODO need check for oversized flags if value[0]: # allow for basic text notations w/ "not value[0]" flag_d = ''.join([STN.int2str(x) for x in value[0]]) # first four flag octs else: flag_d = '\x80\x00\x00\x00' nam, val = value[1], value[2] namlen, vallen = STN.int2str(len(nam)), STN.int2str(len(val)) if len(namlen) == 1: namlen = '\x00' + namlen elif len(namlen) > 2: raise SignatureSubpacketValueError( "Length (%s) of subpacket notation 'name' exceeds 2 octet limit." % len(nam)) if len(vallen) == 1: vallen = '\x00' + vallen elif len(vallen) > 2: raise SignatureSubpacketValueError( "Length (%s) of subpacket notation 'value' exceeds 2 octet limit." % len(val)) value_d = flag_d + namlen + vallen + nam + val elif type in [ SIGSUB_KEYSERV, SIGSUB_POLICYURL, SIGSUB_SIGNERUID, SIGSUB_REGEX ]: value_d = value elif SIGSUB_REVOCREASON == type: # code, reason value_d = STN.int2str(value[0]) + value[1] elif SIGSUB_SIGTARGET == type: raise NotImplementedError, "SIGTARGET not supported" else: # subpacket is an unknown type, so just pack the data in value_d = value # resolve length string len_d = len(value_d) + 1 # + 1 octet type slice = create_NewLength(len_d)._d # set type string (character) type_d = STN.int2str(type)[0] subpkt_d = ''.join([slice, type_d, value_d]) return SignatureSubpacket(subpkt_d)
def create_SignatureBody(*args, **kwords): """Assemble signature information into a SignatureBody instance. :Parameters: - `args`: parameter list - `kwords`: keyword parameter dictionary :Keywords: - `sigtype`: integer signature type constant (see `OpenPGP.constant.signatures`) - `alg_pubkey`: integer signature algorithm (see `OpenPGP.constant.algorithms`) - `alg_hash`: integer signature algorithm (see `OpenPGP.constant.algorithms`) - `signature`: algorithm-dependent signature MPIs - DSA MPI tuple (``DSA_r``, ``DSA_s``), single RSA MPI ``RSA``, or ElGamal MPI tuple (``ELGAMAL_a``, ``ELGAMAL_b``) (see `DSA signature tuple`_, `RSA signature value`_, and `ElGamal signature tuple`_) - `hash_frag`: 2 octet string of signed hash fragment - `hashed_subpkts`: list of `SignatureSubpacket` instances included in the hashed (protected) portion of the signature - `unhashed_subpkts`: list of `SignatureSubpacket` instances included in the unhashed (unprotected) portion of the signature - `created`: integer timestamp of signature creation, **v3 only** - `keyid`: string ID of signing key **v3 only** :Returns: `SignatureBody` instance .. _DSA signature tuple: DSA signature tuple (``DSA_r``, ``DSA_s``): - `DSA_r`: `OpenPGP.packet.MPI` instance - `DSA_s`: `OpenPGP.packet.MPI` instance .. _RSA signature value: RSA signature value ``RSA``: - ``RSA``: `OpenPGP.packet.MPI` instance .. _ElGamal signature tuple: ElGamal signature tuple (``ELGAMAL_a``, ``ELGAMAL_b``): - ``ELGAMAL_a``: `OpenPGP.packet.MPI` instance - ``ELGAMAL_b``: `OpenPGP.packet.MPI` instance :note: This function only assembles the provided information into a signature packet, it does not reconcile anything - namely, the values of the MPIs with the signed data and hash fragment. :note: All keyword parameters can be specified in a dictionary, sent as a single parameter (args[0]). """ try: kwords = args[0] except IndexError: pass version = kwords['version'] sigtype = kwords['sigtype'] alg_pubkey = kwords['alg_pubkey'] alg_hash = kwords['alg_hash'] signature = kwords['signature'] hash_frag = kwords['hash_frag'] hashed_subpkts = kwords.get('hashed_subpkts') # optional unhashed_subpkts = kwords.get('unhashed_subpkts') # optional _d = [] _d.append(STN.int2str(version)[0]) ################# version if 3 == version: ################# 3 _d.append('\x05') # hash length (required) _d.append(STN.int2str(sigtype)[0]) # signature type _d.append(STN.int2str(kwords['created'])[:4]) # creation timestamp _d.append(STN.hex2str(kwords['keyid'])[:8]) # signing key ID _d.append(STN.int2str(alg_pubkey)[0]) # public key algorithm _d.append(STN.int2str(alg_hash)[0]) # hash algorithm elif 4 == version: ################# 4 _d.append(STN.int2str(sigtype)[0]) # signature type _d.append(STN.int2str(alg_pubkey)[0]) # public key algorithm _d.append(STN.int2str(alg_hash)[0]) # hash algorithm if hashed_subpkts: # hashed subpackets _d.append(__cat_subpkt_block(hashed_subpkts)) else: _d.append('\x00\x00') if unhashed_subpkts: # unhashed subpackets _d.append(__cat_subpkt_block(unhashed_subpkts)) else: _d.append('\x00\x00') _d.append(hash_frag[:2]) # hash fragment if alg_pubkey in [ASYM_RSA_S, ASYM_RSA_EOS]: # RSA MPI _d.append(''.join([x._d for x in signature])) elif alg_pubkey in [ASYM_DSA, ASYM_ELGAMAL_EOS]: # DSA MPIs _d.append(''.join([x._d for x in signature])) else: raise PGPValueError, "Unsupported signature algorithm %s." % algorithm return SignatureBody(''.join(_d))
def create_SignatureSubpacket(type, value): """Create a SignatureSubpacket instance. :Parameters: - `type`: integer signature subpacket type constant (see `OpenPGP.constant.signatures`) - `value`: variable value depending on `type` (see `Subpacket types and values`_) :Returns: `SignatureSubpacket` instance .. _Subpacket types and values: Subpacket types and values: - ``SIGSUB_SIGNERID``: hex key ID string (16 octets) - ``SIGSUB_CREATED``: integer timestamp of signature creation(must resolve to 4 or less octets, restricting value to less than 4294967296) - ``SIGSUB_EXPIRES``, ``SIGSUB_KEYEXPIRES``: integer time past creation of signature or key expiration (must resolve to 4 or less octets, restricting value to less than 4294967296) - ``SIGSUB_EXPORTABLE``, `SIGSUB_REVOCABLE``, ``SIGSUB_PRIMARYUID``: integer 1 or 0 for True or False - ``SIGSUB_TRUST``: tuple(integer level, integer amount) - ``SIGSUB_SYMCODE``, ``SIGSUB_HASHALGS``, ``SIGSUB_COMPALGS``, ``SIGSUB_KEYSERVPREFS``, ``SIGSUB_KEYFLAGS``, ``SIGSUB_FEATURES``: list of integers, see rfc2440 for specifics - ``SIGSUB_REVOKER``: tuple(integer class, integer algorithm, string 40 octet caps hex SHA1 fingerprint hash string - ``SIGSUB_NOTATION``: tuple([list of 4 flags], string name, string value) see rfc2440 for specifics, list of flags may be replaced with None for basic text notation [0x80, 0x0, 0x0, 0x0] - ``SIGSUB_KEYSERV``, ``SIGSUB_POLICYURL``, ``SIGSUB_SIGNERUID``, ``SIGSUB_REGEX``: string see rfc2440 for specifics - ``SIGSUB_REVOCREASON``: tuple (integer code, string reason) - ``SIGSUB_SIGTARGET``: Not Implemented """ from Packet import create_NewLength # set value_d if SIGSUB_SIGNERID == type: value_d = STN.hex2str(value) if len(value_d) != 8: raise SignatureSubpacketValueError("Length of subpacket key id (%s) is not 8 octets." % len(value)) elif type in [SIGSUB_CREATED, SIGSUB_EXPIRES, SIGSUB_KEYEXPIRES]: value_d = STN.int2str(value) while len(value_d) < 4: value_d = '\x00' + value_d if len(value_d) > 4: raise SignatureSubpacketValueError("Length of subpacket time (%s) exceeds 4 octet limit." % len(value_d)) elif type in [SIGSUB_EXPORTABLE, SIGSUB_REVOCABLE, SIGSUB_PRIMARYUID]: if value not in [0, 1]: raise SignatureSubpacketValueError("Subpacket (# %s) value must be 0 or 1." % (str(subtype))) else: value_d = STN.int2str(value) elif SIGSUB_TRUST == type: # level, amount value_d = STN.int2str(value[0]) + STN.int2str(value[1]) elif type in [SIGSUB_SYMCODE, SIGSUB_HASHCODE, SIGSUB_COMPCODE, SIGSUB_KEYSERVPREFS, SIGSUB_KEYFLAGS, SIGSUB_FEATURES]: value_d = ''.join([STN.int2str(x) for x in value]) elif SIGSUB_REVOKER == type: # value_d = STN.int2str(value[0]) + STN.int2str(value[1]) + STN.hex2str(value[2]) elif SIGSUB_NOTE == type: # [f1, f2, f3, f4], name, value # TODO need check for oversized flags if value[0]: # allow for basic text notations w/ "not value[0]" flag_d = ''.join([STN.int2str(x) for x in value[0]]) # first four flag octs else: flag_d = '\x80\x00\x00\x00' nam, val = value[1], value[2] namlen, vallen = STN.int2str(len(nam)), STN.int2str(len(val)) if len(namlen) == 1: namlen = '\x00' + namlen elif len(namlen) > 2: raise SignatureSubpacketValueError("Length (%s) of subpacket notation 'name' exceeds 2 octet limit." % len(nam)) if len(vallen) == 1: vallen = '\x00' + vallen elif len(vallen) > 2: raise SignatureSubpacketValueError("Length (%s) of subpacket notation 'value' exceeds 2 octet limit." % len(val)) value_d = flag_d + namlen + vallen + nam + val elif type in [SIGSUB_KEYSERV, SIGSUB_POLICYURL, SIGSUB_SIGNERUID, SIGSUB_REGEX]: value_d = value elif SIGSUB_REVOCREASON == type: # code, reason value_d = STN.int2str(value[0]) + value[1] elif SIGSUB_SIGTARGET == type: raise NotImplementedError, "SIGTARGET not supported" else: # subpacket is an unknown type, so just pack the data in value_d = value # resolve length string len_d = len(value_d) + 1 # + 1 octet type slice = create_NewLength(len_d)._d # set type string (character) type_d = STN.int2str(type)[0] subpkt_d = ''.join([slice, type_d, value_d]) return SignatureSubpacket(subpkt_d)