Beispiel #1
0
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 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)
Beispiel #5
0
 def test02_str2hex_hex2str(self):
     "strnum: string/hex inversion (str2hex/hex2str)"
     fprint = self.key.body.fingerprint
     xprint = str2hex(hex2str(fprint))
     self.assertEqual(fprint, xprint)
Beispiel #6
0
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)
Beispiel #7
0
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))
Beispiel #8
0
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)
Beispiel #9
0
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))