def get_smart_cards_sessions():
        ''' Check for connected smart card

            Returns:
                a session list of connected smart cards
        '''
        # getting a smart card session
        return SignatureUtils().fetch_smart_card_sessions()
    def session_login(sessions, pin):
        ''' Attempt to login on connected smart cards

            Param:
                sessions: connected smart card slots
                pin: user pin

            Returns:
                logged in session
        '''

        # login on the session
        return SignatureUtils().user_login(sessions, pin)
Exemplo n.º 3
0
def sign(datau,
         session,
         cert,
         cert_value,
         hashalgo,
         attrs=True,
         signed_value=None):
    if signed_value is None:
        signed_value = getattr(hashlib, hashalgo)(datau).digest()
    signed_time = datetime.now()

    x509 = Certificate.load(cert_value)
    certificates = []
    certificates.append(x509)

    cert_value_digest = bytes(
        session.digest(cert_value, Mechanism(LowLevel.CKM_SHA256)))
    MyLogger().my_logger().info('building signed attributes...')
    signer = {
        'version':
        'v1',
        'sid':
        cms.SignerIdentifier({
            'issuer_and_serial_number':
            cms.IssuerAndSerialNumber({
                'issuer': x509.issuer,
                'serial_number': x509.serial_number,
            }),
        }),
        'digest_algorithm':
        algos.DigestAlgorithm({'algorithm': hashalgo}),
        'signature_algorithm':
        algos.SignedDigestAlgorithm({'algorithm': 'rsassa_pkcs1v15'}),
        'signature':
        signed_value,
    }
    if attrs:
        signer['signed_attrs'] = [
            cms.CMSAttribute({
                'type': cms.CMSAttributeType('content_type'),
                'values': ('data', ),
            }),
            cms.CMSAttribute({
                'type': cms.CMSAttributeType('message_digest'),
                'values': (signed_value, ),
            }),
            cms.CMSAttribute({
                'type':
                cms.CMSAttributeType('signing_time'),
                'values': (cms.Time({'utc_time': core.UTCTime(signed_time)}), )
            }),
            cms.CMSAttribute({
                'type':
                cms.CMSAttributeType('1.2.840.113549.1.9.16.2.47'),
                'values': (tsp.SigningCertificateV2({
                    'certs': (tsp.ESSCertIDv2({
                        'hash_algorithm':
                        algos.DigestAlgorithm({
                            'algorithm': hashalgo,
                            'parameters': None
                        }),
                        'cert_hash':
                        cert_value_digest,
                    }), ),
                }), )
            }),
        ]
    config = {
        'version':
        'v1',
        'digest_algorithms':
        cms.DigestAlgorithms((algos.DigestAlgorithm({'algorithm':
                                                     hashalgo}), )),
        'encap_content_info': {
            'content_type': 'data',
        },
        'certificates':
        certificates,
        # 'crls': [],
        'signer_infos': [
            signer,
        ],
    }
    datas = cms.ContentInfo({
        'content_type': cms.ContentType('signed_data'),
        'content': cms.SignedData(config),
    })
    if attrs:
        tosign = datas['content']['signer_infos'][0]['signed_attrs'].dump()
        tosign = b'\x31' + tosign[1:]
    else:
        tosign = datau

    MyLogger().my_logger().info('signed attributes ready')
    # fetching private key from smart card
    priv_key = SignatureUtils.fetch_private_key(session, cert)
    mechanism = Mechanism(LowLevel.CKM_SHA256_RSA_PKCS, None)
    MyLogger().my_logger().info('signing...')
    # signing bytes to be signed
    signature = session.sign(priv_key, tosign, mechanism)

    datas['content']['signer_infos'][0]['signature'] = bytes(signature)

    return datas.dump()
    def sign_pdf(file_path, open_session, user_cf, sig_attributes):
        ''' Return a signed pdf file path
                The file name will be the same with (firmato) before the extension and .pdf at the end
                The path will be the same

            Param:
                file_path: complete or relative path of the file to sign
                open_session: logged in session (from login_attempt())
        '''
        # fetching smart card certificate
        certificate = SignatureUtils.fetch_certificate(open_session)
        # getting certificate value
        certificate_value = SignatureUtils.get_certificate_value(
            open_session, certificate)

        # check for signer identity
        # if user_cf == "X" * 15, avoid this check
        if user_cf != "X" * 15:
            # only for REST calls
            DigiSignLib()._check_certificate_owner(certificate_value, user_cf)

        # check for certificate time validity
        DigiSignLib()._check_certificate_validity(certificate_value)

        MyLogger().my_logger().info(f"reading pdf file {file_path}")
        datau = open(file_path, 'rb').read()
        datas = pdf_builder.sign(datau, open_session, certificate,
                                 certificate_value, 'sha256', sig_attributes)

        signed_file_path = DigiSignLib().get_signed_files_path(
            file_path, 'pdf')

        MyLogger().my_logger().info(f"saving output to {signed_file_path}")
        with open(signed_file_path, 'wb') as fp:
            fp.write(datau)
            fp.write(datas)

        MyLogger().my_logger().info(
            f"verifying pdf signatures of {signed_file_path}")
        try:
            new_data = open(signed_file_path, 'rb').read()
            results = verify(new_data, [certificate_value])
            for key, res in enumerate(results, start=1):
                print('Signature %d: ' % key, res)
                MyLogger().my_logger().info(f"Signature {key}: {res}")
                if not res['hashok?']:
                    raise PdfVerificationError(
                        f"Hash verification of Signature {key} is failed.")
                if not res['signatureok?']:
                    raise PdfVerificationError(
                        f"Signature verification of Signature {key} is failed."
                    )
                if not res['certok?']:
                    # TODO verify certificates
                    MyLogger().my_logger().error(
                        f"Certificate verification of Signature {key} is failed."
                    )
        except:
            MyLogger().my_logger().error(
                f"Error during verification of Signature {key}:")
            raise

        return signed_file_path
    def session_close(session):
        ''' Close smart card `session` '''

        # session close
        SignatureUtils().close_session(session)
    def session_logout(session):
        ''' User logout from session '''

        # logout from the session
        SignatureUtils().user_logout(session)
    def sign_p7m(file_path, open_session, user_cf, sig_attrs):
        ''' Return a signed p7m file path
                The file name will be the same with (firmato) before the extension and .p7m at the end
                The path will be the same

            Param:
                file_path: complete or relative path of the file to sign
                open_session: logged in session (from login_attempt())
        '''

        # fetching sig type
        sig_type = sig_attrs['p7m_sig_type']
        # fetching file content
        file_content = DigiSignLib().get_file_content(file_path)
        # check existing signatures
        p7m_attrs = P7mAttributes(b'', b'', b'')
        mime = MimeTypes().guess_type(file_path)[0]
        if mime == 'application/pkcs7':
            info = cms.ContentInfo.load(file_content)
            # retrieving existing signatures attributes
            signed_data = info['content']
            p7m_attrs.algos = signed_data['digest_algorithms'].contents
            p7m_attrs.certificates = signed_data['certificates'].contents
            #
            if sig_type == 'parallel':
                p7m_attrs.signer_infos = signed_data['signer_infos'].contents
                file_content = signed_data['encap_content_info'].native[
                    'content']

        # hashing file content
        file_content_digest = SignatureUtils().digest(open_session,
                                                      file_content)

        # fetching smart card certificate
        certificate = SignatureUtils().fetch_certificate(open_session)
        # getting certificate value
        certificate_value = SignatureUtils().get_certificate_value(
            open_session, certificate)
        # hashing certificate value
        certificate_value_digest = SignatureUtils().digest(
            open_session, certificate_value)

        # check for signer identity
        # if user_cf == "X" * 15, avoid this check
        if user_cf != "X" * 15:
            # only for REST calls
            DigiSignLib()._check_certificate_owner(certificate_value, user_cf)

        # check for certificate time validity
        DigiSignLib()._check_certificate_validity(certificate_value)

        # getting signed attributes p7m field
        try:
            signed_attributes = P7mEncoder().encode_signed_attributes(
                file_content_digest, certificate_value_digest)
        except:
            raise P7mCreationError("Exception on encoding signed attributes")
        # getting bytes to be signed
        try:
            bytes_to_sign = P7mEncoder().bytes_to_sign(
                file_content_digest, certificate_value_digest)
        except:
            raise P7mCreationError("Exception on encoding bytes to sign")

        # fetching private key from smart card
        privKey = SignatureUtils().fetch_private_key(open_session, certificate)
        # signing bytes to be signed
        signed_attributes_signed = SignatureUtils().signature(
            open_session, privKey, bytes_to_sign)

        # getting issuer from certificate
        issuer = SignatureUtils().get_certificate_issuer(
            open_session, certificate)
        # getting serial number from certificate
        serial_number = SignatureUtils().get_certificate_serial_number(
            open_session, certificate)
        # getting signer info p7m field
        try:
            signer_info = P7mEncoder().encode_signer_info(
                issuer, serial_number, signed_attributes,
                signed_attributes_signed, p7m_attrs.signer_infos)
        except:
            raise P7mCreationError("Exception on encoding signer info")

        # create the p7m content
        try:
            output_content = P7mEncoder().make_a_p7m(file_content,
                                                     certificate_value,
                                                     signer_info, p7m_attrs)
        except:
            raise P7mCreationError("Exception on encoding p7m file content")

        # saves p7m to file
        signed_file_path = DigiSignLib().get_signed_files_path(
            file_path, 'p7m', sig_type)
        DigiSignLib().save_file_content(signed_file_path, output_content)

        return signed_file_path