/usr/lib/python3/dist-packages/pskc/signature.py is in python3-pskc 1.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | # signature.py - module for handling signed XML files
# coding: utf-8
#
# Copyright (C) 2017 Arthur de Jong
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
"""Module for handling signed PSKC files.
This module defines a Signature class that handles the signature checking,
keys and certificates.
"""
def sign_x509(xml, key, certificate, algorithm=None, digest_algorithm=None,
canonicalization_method=None):
"""Sign PSKC data using X.509 certificate and private key.
xml: an XML document
key: the private key in binary format
certificate: the X.509 certificate
"""
import signxml
algorithm = algorithm or 'rsa-sha256'
digest_algorithm = digest_algorithm or 'sha256'
canonicalization_method = (
canonicalization_method or
signxml.XMLSignatureProcessor.default_c14n_algorithm)
return signxml.XMLSigner(
method=signxml.methods.enveloped,
signature_algorithm=algorithm.rsplit('#', 1)[-1].lower(),
digest_algorithm=digest_algorithm.rsplit('#', 1)[-1].lower(),
c14n_algorithm=canonicalization_method,
).sign(xml, key=key, cert=certificate)
def verify_x509(tree, certificate=None, ca_pem_file=None):
"""Verify signature in PSKC data against a trusted X.509 certificate.
If a certificate is supplied it is used to validate the signature,
otherwise any embedded certificate is used and validated against a
certificate in ca_pem_file if it specified and otherwise the operating
system CA certificates.
"""
from signxml import XMLVerifier
return XMLVerifier().verify(
tree, x509_cert=certificate, ca_pem_file=ca_pem_file).signed_xml
class Signature(object):
"""Class for handling signature checking of the PSKC file.
Instances of this class provide the following properties:
is_signed: boolean to indicate whether a signature is present
algorithm: identifier of the signing algorithm used
canonicalization_method: identifier of the XML canonicalization used
digest_algorithm: algorithm used for creating the hash
issuer: issuer of the certificate
serial: serial number of the certificate
key: key that will be used when creating a signed PSKC file
certificate: the certificate that is embedded in the signature
signed_pskc: a PSKC instance with the signed information
"""
def __init__(self, pskc):
self.pskc = pskc
self._algorithm = None
self.canonicalization_method = None
self.digest_algorithm = None
self.issuer = None
self.serial = None
self.key = None
self.certificate = None
@property
def is_signed(self):
"""Test whether the PSKC file contains a signature (not whether the
signature is valid)."""
return bool(
self.algorithm or self.canonicalization_method or
self.digest_algorithm or self.issuer or self.certificate)
@property
def algorithm(self):
"""Provide the signing algorithm used."""
if self._algorithm:
return self._algorithm
@algorithm.setter
def algorithm(self, value):
from pskc.algorithms import normalise_algorithm
self._algorithm = normalise_algorithm(value)
@property
def signed_pskc(self):
"""Provide the signed PSKC information."""
if not hasattr(self, '_signed_pskc'):
self.verify()
return self._signed_pskc
def verify(self, certificate=None, ca_pem_file=None):
"""Check that the signature was made with the specified certificate.
If no certificate is provided the signature is expected to contain a
signature that is signed by the CA certificate (or the CA standard CA
certificates when ca_pem_file is absent)."""
from pskc import PSKC
from pskc.parser import PSKCParser
signed_xml = verify_x509(self.tree, certificate, ca_pem_file)
pskc = PSKC()
PSKCParser.parse_document(pskc, signed_xml)
self._signed_pskc = pskc
return True
def sign(self, key, certificate=None):
"""Add an XML signature to the file."""
self.key = key
self.certificate = certificate
def sign_xml(self, xml):
"""Sign an XML document with the configured key and certificate."""
return sign_x509(
xml, self.key, self.certificate, self.algorithm,
self.digest_algorithm, self.canonicalization_method)
|