示例#1
0
/**
 * Sign the signature using BDOC-BES profile. Sets required fields,
 * calculates digests and finally signs the signature object using
 * the provided <code>signer</code> implementation.
 *
 * @param signer signer that signs the signature object.
 * @throws SignatureException exception is throws if signing failed.
 */
void digidoc::SignatureBES::sign(Signer* signer) throw(SignatureException, SignException)
{
    // Set required signature fields.
    try
    {
        setSigningCertificate(signer->getCert());
        setSignatureProductionPlace(signer->getSignatureProductionPlace());
        setSignerRole(signer->getSignerRole());
        setSigningTime(util::date::currentTime());
    }
    catch( const IOException &e )
    {
        THROW_SIGNEXCEPTION_CAUSE( e, "Failed to sign document" );
    }

    // Calculate digest of the Signature->Object->SignedProperties node.
    std::auto_ptr<Digest> calc = Digest::create();
    std::vector<unsigned char> digest = calcDigestOnNode(calc.get(), XADES_NAMESPACE, "SignedProperties");
    addReference("#S0-SignedProperties", calc->getUri(), digest, "http://uri.etsi.org/01903#SignedProperties");

    // Calculate SHA1 digest of the Signature->SignedInfo node.
    calc = Digest::create(NID_sha1);
    std::vector<unsigned char> sha1 = calcDigestOnNode(calc.get(), DSIG_NAMESPACE, "SignedInfo");
    Signer::Digest sigDigestSha1 = { NID_sha1, &sha1[0], calc->getSize() };

    // Sign the calculated SAH1 digest and add the signature value (SHA1-RSA) to the signature.
    std::vector<unsigned char> buf(128);
    Signer::Signature signatureSha1Rsa = { &buf[0], buf.size() };
    signer->sign(sigDigestSha1, signatureSha1Rsa);
    setSignatureValue(signatureSha1Rsa);
}
示例#2
0
/**
 * Prepares SignedInfo
 *
 * @param signer signer that signs the signature object.
 * @throws SignatureException exception is throws if signing failed.
 */
std::vector<unsigned char> digidoc::SignatureBES::prepareSignedInfo(Signer* signer) throw(SignatureException, SignException)
{
    // Calculate digests for the documents and add these to the signature reference.
    for(unsigned int i = 0; i < bdoc.documentCount(); ++i)
    {
        digidoc::Document doc = bdoc.getDocument(i);
        try
        {
            DEBUG("Adding document '%s', '%s' to the signature references.", doc.getFileName().c_str(), doc.getMediaType().c_str());
            // URIs must encode non-ASCII characters in the format %HH where HH is the hex representation of the character
            std::string uri = std::string("/") + digidoc::util::File::toUri(doc.getFileName());
            std::auto_ptr<Digest> calc(new Digest());
            std::vector<unsigned char> digest = doc.calcDigest(calc.get());
            DEBUGMEM("digest", &digest[0], digest.size());
            addReference(uri, calc->getUri(), digest);
        }
        catch(const Exception& e)
        {
            delete signature;
            THROW_SIGNEXCEPTION_CAUSE(e, "Failed to calculate digests for document '%s'.", doc.getFileName().c_str());
        }
    }

    // Set required signature fields.
    try
    {
        setSigningCertificate(signer->getCert());
        setSignatureProductionPlace(signer->getSignatureProductionPlace());
        setSignerRole(signer->getSignerRole());
        setSigningTime(util::date::currentTime());
    }
    catch( const IOException &e )
    {
        THROW_SIGNEXCEPTION_CAUSE( e, "Failed to sign document" );
    }

    xml_schema::Uri uri(URI_ID_RSA_SHA1);
    switch(signer->type())
    {
    case NID_sha224: uri = xml_schema::Uri(URI_ID_RSA_SHA224); break;
    case NID_sha256: uri = xml_schema::Uri(URI_ID_RSA_SHA256); break;
    case NID_sha384: uri = xml_schema::Uri(URI_ID_RSA_SHA384); break;
    case NID_sha512: uri = xml_schema::Uri(URI_ID_RSA_SHA512); break;
    default: break;
    }
    signature->signedInfo().signatureMethod(dsig::SignatureMethodType(uri));

    // Calculate digest of the Signature->Object->SignedProperties node.
    std::auto_ptr<Digest> calc(new Digest());
    std::vector<unsigned char> digest = calcDigestOnNode(calc.get(), XADES_NAMESPACE, "SignedProperties");
    addReference("#" + getId() +"-SignedProperties", calc->getUri(), digest, "http://uri.etsi.org/01903#SignedProperties");

    // Calculate SHA digest of the Signature->SignedInfo node.
    calc.reset(new Digest(signer->type()));
    return calcDigestOnNode(calc.get(), URI_ID_DSIG, "SignedInfo");
}
示例#3
0
/**
 * Validate signature value.
 *
 * @throws throws exception if signature value did not match.
 */
void digidoc::SignatureBES::checkSignatureValue() const throw(SignatureException)
{
    DEBUG("SignatureBES::checkSignatureValue()");
    try
    {
        // Initialize RSA crypter.
        X509* cert = getSigningCertificate().getX509();
        X509_scope certScope(&cert);
        RSACrypt rsa(cert);

        // Calculate SHA1 digest of the Signature->SignedInfo node.
        std::auto_ptr<Digest> calc = Digest::create(NID_sha1);
        std::vector<unsigned char> sha1 = calcDigestOnNode(calc.get(), DSIG_NAMESPACE, "SignedInfo");
        DEBUGMEM("Digest", &sha1[0], sha1.size());

        // Get signature value.
        std::vector<unsigned char> signatureSha1Rsa = getSignatureValue();

        // Verify signature value with public RSA key.
        bool valid = rsa.verify(calc->getMethod(), sha1, signatureSha1Rsa);

        // Check that signature matched.
        if(!valid)
        {
            THROW_SIGNATUREEXCEPTION("Signature is not valid.");
        }
    }
    catch(const IOException& e)
    {
        THROW_SIGNATUREEXCEPTION_CAUSE(e, "Failed to validate signature.");
    }
}
示例#4
0
void bdoc::Signature::checkSignatureValue()
{
    X509Cert cert(getSigningCertificate());

    const dsig::SignatureMethodType::AlgorithmType&
    algorithmType = getSignatureMethodAlgorithmType();
    const char* algorithmUri = algorithmType.c_str();

    // Get hash method URI from signature method URI.
    signatureMethod sm;
    hashMethod hm;
    safeBuffer hashMethodUri;
    if (!XSECmapURIToSignatureMethods(XMLString::transcode(algorithmUri), sm, hm)
            || !hashMethod2URI(hashMethodUri, hm)) {
        THROW_STACK_EXCEPTION("Couldn't extract hash method from "
                              "signature method URI '%s'.", algorithmUri);
    }

    std::auto_ptr<Digest> calc = Digest::create(hashMethodUri.rawCharBuffer());
    std::vector<unsigned char> digest =
        calcDigestOnNode(calc.get(), DSIG_NAMESPACE, "SignedInfo");

    std::vector<unsigned char> signatureValue = getSignatureValue();

    if (!cert.verifySignature(calc->getMethod(), calc->getSize(), digest,
                              signatureValue)) {
        THROW_STACK_EXCEPTION("Signature is not valid.");
    }
}
示例#5
0
void bdoc::Signature::checkReferenceToSigProps(
    const bdoc::dsig::ReferenceType& refType)
{
    const dsig::ReferenceType::URIOptional& uriOpt = refType.uRI();

    if (!uriOpt.present()) {
        THROW_STACK_EXCEPTION(
            "SignedInfo reference to SignedProperties does not "
            "have attribute 'URI'");
    }

    const dsig::DigestMethodType& digestMethod = refType.digestMethod();
    const dsig::DigestMethodType::AlgorithmType&
    algorithm = digestMethod.algorithm();

    if (!Digest::isSupported(algorithm)) {
        THROW_STACK_EXCEPTION(
            "reference to SignedProperties digest method "
            "algorithm '%s' is not supported", algorithm.c_str());
    }

    const dsig::DigestValueType& digestValue = refType.digestValue();

    std::auto_ptr<Digest> calc =
        Digest::create(refType.digestMethod().algorithm());

    std::vector<unsigned char> calculatedDigestValue =
        calcDigestOnNode(
            calc.get(), xadesnamespace(), "SignedProperties");

    if (digestValue.begin() + calculatedDigestValue.size()
            != digestValue.end()) {
        THROW_STACK_EXCEPTION(
            "SignedProperties digest lengths do not match");
    }

    for (size_t i = 0; i < calculatedDigestValue.size(); i++) {
        const char* dv = digestValue.begin() + i;
        if (*dv != static_cast<char>(calculatedDigestValue[i])) {
            THROW_STACK_EXCEPTION(
                "SignedProperties digest values do not match");
        }
    }
}
示例#6
0
/// TODO: comment
///
/// @throws SignatureException on a problem in signature
void digidoc::SignatureBES::checkReferenceToSigProps(const digidoc::dsig::ReferenceType& refType)
const throw(SignatureException)
{
    // check attribute URI (e.g. "#SigId-SignedProperties")
    const dsig::ReferenceType::URIOptional& uriOpt = refType.uRI();

    if ( !uriOpt.present() )
    {
        THROW_SIGNATUREEXCEPTION("SignedInfo reference to SignedProperties does not have attribute 'URI'");
    }

    /*  This check is pointless. It might make sense to check the syntax of the
     *  URL, but this is better left for the resolvers to handle.
        std::string foundUri = uriOpt.get();
        std::string expectedUri =
            std::string("#") + id() + "-SignedProperties";

        if ( foundUri != expectedUri )
        {
            THROW_SIGNATUREEXCEPTION("SignedInfo reference to SignedProperties attribute 'URI' is invalid");
        }
    */

    // check DigestMethod
    const dsig::DigestMethodType& digestMethod = refType.digestMethod();
    const dsig::DigestMethodType::AlgorithmType& algorithm = digestMethod.algorithm();

    if ( !Digest::isSupported( algorithm ) )
    {
        THROW_SIGNATUREEXCEPTION("reference to SignedProperties digest method algorithm '%s' is not supported", algorithm.c_str());
    }

    // check DigestValue
    const dsig::DigestValueType& digestValue = refType.digestValue();


    // TODO: do it nicely.
    //xml_schema::dom::auto_ptr<xercesc::DOMDocument> dom = createDom();
    //xercesc::DOMNode* signedPropsNode = dom->getFirstChild()->getLastChild()->getFirstChild()->getFirstChild();

    // xercesc::DOMNode* idNode(NULL);
// FIXME: Äkki oleks parem kasutada olemasolevat signature puud, mitte Xercese oma?
//	if (!signedPropsNode->hasAttributes()
//	   || (idNode = signedPropsNode->getAttributes()->getNamedItem(xercesc::XMLString::transcode("Id"))) == NULL )
//    {
//        THROW_SIGNATUREEXCEPTION("SignedProperties does not have attribute 'Id'");
//    }

    std::auto_ptr<Digest> calc = Digest::create(refType.digestMethod().algorithm());
    //std::vector<unsigned char> calculatedDigestValue = calcDigestOnNode(calc.get(), signedPropsNode);
    std::vector<unsigned char> calculatedDigestValue = calcDigestOnNode(calc.get(), XADES_NAMESPACE, "SignedProperties");

    if ( digestValue.begin() + calculatedDigestValue.size() != digestValue.end() )
    {
        THROW_SIGNATUREEXCEPTION("SignedProperties digest lengths do not match");
    }

    for ( size_t i = 0; i < calculatedDigestValue.size(); i++ )
    {
        const char* dv = digestValue.begin() + i;
        if ( *dv != static_cast<char>(calculatedDigestValue[i]) )
        {
            DEBUGMEM("Document digest:", &digestValue.data()[0], digestValue.size());
            DEBUGMEM("Calculated digest:", &calculatedDigestValue[0], calculatedDigestValue.size());
            THROW_SIGNATUREEXCEPTION("SignedProperties digest values do not match");
        }
    }
}