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;
}