unsigned int WinCAPICryptoKeyRSA::signSHA1PKCS1Base64Signature()

in xsec/enc/WinCAPI/WinCAPICryptoKeyRSA.cpp [354:474]


unsigned int WinCAPICryptoKeyRSA::signSHA1PKCS1Base64Signature(unsigned char * hashBuf,
        unsigned int hashLen,
        char * base64SignatureBuf,
        unsigned int base64SignatureBufLen,
		XSECCryptoHash::HashType type) const {

    // Sign a pre-calculated hash using this key

    if (m_keySpec == 0) {
        throw XSECCryptoException(XSECCryptoException::RSAError,
            "WinCAPI:RSA - Attempt to sign data using a public or un-loaded key");
    }

    /* Is this a hash we support? */
    ALG_ID alg;
    switch (type) {
    case (XSECCryptoHash::HASH_MD5):
        alg = CALG_MD5;
        break;
    case (XSECCryptoHash::HASH_SHA1):
        alg = CALG_SHA1;
        break;
    default:
        throw XSECCryptoException(XSECCryptoException::RSAError,
            "WinCAPI:RSA Unsupported hash algorithm for RSA sign - only MD5 or SHA1 supported");
    }

    // Have to create a Windows hash object and feed in the hash
    BOOL fResult;
    HCRYPTHASH h;
    fResult = CryptCreateHash(m_p,
                    alg,
                    0,
                    0,
                    &h);

    if (!fResult) {
        throw XSECCryptoException(XSECCryptoException::RSAError,
            "WinCAPI:RSA - Error creating Windows Hash Object");
    }

    // Feed the hash value into the newly created hash object
    fResult = CryptSetHashParam(
                    h,
                    HP_HASHVAL,
                    hashBuf,
                    0);

    if (!fResult) {
        if (h)
            CryptDestroyHash(h);
        throw XSECCryptoException(XSECCryptoException::RSAError,
            "WinCAPI:RSA - Error Setting Hash Value in Windows Hash object");
    }

    // Now sign
    DWORD rawSigLen;
    fResult = CryptSignHash(
                h,
                m_keySpec,
                NULL,
                0,
                NULL,
                &rawSigLen);

    if (!fResult || rawSigLen < 1) {

        if (h)
            CryptDestroyHash(h);
        throw XSECCryptoException(XSECCryptoException::RSAError,
        "WinCAPI:RSA - Error occurred obtaining RSA sig length");
    }

    BYTE * rawSig;
    XSECnew(rawSig, BYTE[rawSigLen]);
    ArrayJanitor<BYTE> j_rawSig(rawSig);

    fResult = CryptSignHash(
                h,
                m_keySpec,
                NULL,
                0,
                rawSig,
                &rawSigLen);

    if (!fResult || rawSigLen < 1) {

        // Free the hash
        if (h)
            CryptDestroyHash(h);

        throw XSECCryptoException(XSECCryptoException::RSAError,
        "WinCAPI:RSA - Error occurred signing hash");
    }

    // Free the hash
    if (h)
        CryptDestroyHash(h);

    // Now encode into a signature block
    BYTE *rawSigFinal;
    XSECnew(rawSigFinal, BYTE[rawSigLen]);
    ArrayJanitor<BYTE> j_rawSigFinal(rawSigFinal);

    BYTE * i, * j;

    i = rawSig;
    j = rawSigFinal + rawSigLen - 1;

    while (j >= rawSigFinal) {
        *j-- = *i++;
    }

    // Now encode
    XSCryptCryptoBase64 b64;
    b64.encodeInit();
    unsigned int ret = b64.encode(rawSigFinal, rawSigLen, (unsigned char *) base64SignatureBuf, base64SignatureBufLen);
    ret += b64.encodeFinish((unsigned char *) &base64SignatureBuf[ret], base64SignatureBufLen - ret);

    return ret;
}