OpenCSP开源程序解析之OPENCSP_Key.cpp

    #include ".\opencsp_key.h"
    #include ".\opencsp_m$csp.h"
    #include ".\opencsp_alg.h"

    OPENCSP_M$CSP* OPENCSP_Key::_csp;

    OPENCSP_Key::OPENCSP_Key(ALG_ID algId, DWORD dwFlags)
    :_hKey(0), _perms(0), _algId(algId), _flags(dwFlags), _hKeyOfMSCSP(0)
    {
        _hKey = getHandle();
        _csp = OPENCSP_M$CSP::createM$Instance();
    }


    OPENCSP_Key::~OPENCSP_Key(void)
    {
        if (_hKeyOfMSCSP)
            _csp->destroyKey(_hKeyOfMSCSP);
    }

    DWORD OPENCSP_Key::generate(ALG_ID algId, DWORD dwFlags, OPENCSP_Key*& pKey)   //产生密钥
    { 
        DWORD dwRet;
        switch(algId)
        {
        case CALG_RC2:                  //微软提供产生私钥的算法
        case CALG_RC4:
        case CALG_DES:
        case CALG_3DES:
        case CALG_3DES_112:
            {
                //会话密钥,会话密钥有时称对称密钥,因为同一密钥用于加密和解密。
                OPENCSP_Key* key = new OPENCSP_SessionKey(algId, dwFlags); 
                if (!key)
                    return NTE_NO_MEMORY;
                dwRet = key->_csp->genKey(algId, dwFlags, &key->_hKeyOfMSCSP);
                if (dwRet != S_OK) 
                {
                    delete key;
                    return dwRet;
                }
                pKey = key;
            }
            break;
        //容器里的密钥对有两种类型:AT_KEYEXCHANGE,表示交换的密钥对,AT_SIGNATURE表示签名的密钥对。
        case AT_KEYEXCHANGE:
        case AT_SIGNATURE:
            {
                OPENCSP_Key* key = new OPENCSP_RSAKeyInMemory(algId, dwFlags); //RSA:"非对称加密算法"
                if (!key)
                    return NTE_NO_MEMORY;
                dwRet = key->_csp->genKey(algId, dwFlags, &key->_hKeyOfMSCSP);
                if (dwRet != S_OK) 
                {
                    delete key;
                    return dwRet;
                }
                pKey = key;
            }
            break;
        }

        return S_OK;
    }

    DWORD OPENCSP_Key::generate(ALG_ID algId, DWORD dwFlags, OPENCSP_CardAccess* pCard,
        const KEYSET_NAME& kn, OPENCSP_Key*& pKey)
    {
        DWORD fOK = S_OK;
        switch(algId)
        {
        case CALG_RSA_KEYX:
        case CALG_RSA_SIGN:
            {
                BYTE bObjectStatus = 0, bKeyUsage = 0;
                //读取密钥容器状态
                fOK = pCard->getKeysetIdObjectStatus(kn.c_str(), &bObjectStatus, &bKeyUsage);
                if (fOK != S_OK)
                {
                    return fOK;
                }

                if (bObjectStatus & 0x04)
                {
                    return NTE_EXISTS; // in the keyset there is a key pairs already
                }

                KEY_GEN_PARAM kpg;
                kpg.algId = (algId == CALG_RSA_KEYX ? AT_KEYEXCHANGE : AT_SIGNATURE);
                kpg.keySize = ((dwFlags & KEY_LENGTH_MASK) >> 16);

                fOK = pCard->generateKeys(kn.c_str(), kpg);    ////////////产生密钥对,ID,参数
                if (fOK != S_OK) return fOK;

                OPENCSP_Key* key = new OPENCSP_RSAKeyInCard(pCard, kn, algId, dwFlags);//非对称卡实现
                if (!key)   return NTE_NO_MEMORY;

                pKey = key;
            }
            break;
        default:
            return NTE_BAD_ALGID;
        }

        return S_OK;
    }

    DWORD OPENCSP_Key::getUserKey(DWORD dwKeySpec, OPENCSP_Key*& pKey)  //获得会话密钥
    {
        ALG_ID algId = (dwKeySpec == AT_KEYEXCHANGE ? CALG_RSA_KEYX : CALG_RSA_SIGN);
        DWORD dwFlags = CRYPT_EXPORTABLE;

        OPENCSP_Key* key = new OPENCSP_RSAKeyInMemory(algId, dwFlags);
        if (!key) return NTE_NO_MEMORY;

        DWORD dwRet = key->_csp->getUserKey(dwKeySpec, &(key->_hKeyOfMSCSP));
        if (dwRet == NTE_BAD_KEY)
        {
            key->_csp->genKey(dwKeySpec, RSA1024BIT_KEY | dwFlags, &(key->_hKeyOfMSCSP));
        }
        pKey = key;
        return S_OK;
    }

    DWORD OPENCSP_Key::getUserKey(DWORD dwKeySpec, OPENCSP_CardAccess* pCard, 
        const KEYSET_NAME& kn, OPENCSP_Key*& pKey)
    {
        DWORD fOK = S_OK;
        ALG_ID algId = (dwKeySpec == AT_KEYEXCHANGE ? CALG_RSA_KEYX : CALG_RSA_SIGN);

        BYTE bObjectStatus = 0, bKeyUsage = 0;
        fOK = pCard->getKeysetIdObjectStatus(kn.c_str(), &bObjectStatus, &bKeyUsage);//读取密钥容器状态
        if (S_OK != fOK) goto END;

        if (!(bObjectStatus & 0x04))
        {
            fOK =  NTE_NO_KEY;
            goto END;
        }

        if (bKeyUsage != dwKeySpec)
        {
            fOK = NTE_NO_KEY;
            goto END;
        }

        OPENCSP_Key* p = new OPENCSP_RSAKeyInCard(pCard, kn, algId);
        if (!p)
        {
            fOK = NTE_NO_MEMORY;
            goto END;
        }

        pKey = p;

    END:
        return fOK;
    }

    DWORD OPENCSP_Key::importKey(const BYTE* pbData, DWORD dwDataLen, HCRYPTKEY hPubKey,
        DWORD dwFlags, OPENCSP_CardAccess* pCard, const KEYSET_NAME& kn, OPENCSP_Key*& pKey)
    {                                     //导入会话密钥hKey
        BYTE bData[1024] = {0x0};
        DWORD dwLen = 0;
        BLOBHEADER bh; 
        DWORD dwKeySpec = 0;

        DWORD fOK = S_OK;
        BYTE bObjectStatus = 0, bKeyUsage = 0;
        fOK = pCard->getKeysetIdObjectStatus(kn.c_str(), &bObjectStatus, &bKeyUsage);//读取密钥容器状态
        if (S_OK != fOK) return fOK;

        if (bObjectStatus & 0x04)
        {
            return NTE_EXISTS;
        }

        // get key usage
        memcpy(&bh, pbData, sizeof(PUBLICKEYSTRUC));
        dwKeySpec = (bh.aiKeyAlg == CALG_RSA_KEYX ? AT_KEYEXCHANGE : AT_SIGNATURE);

        memcpy(bData, (LPBYTE)pbData + sizeof(PUBLICKEYSTRUC),
            dwDataLen - sizeof(PUBLICKEYSTRUC));//移到内存
        dwLen = dwDataLen  - sizeof(PUBLICKEYSTRUC);
        if (hPubKey)
        {
            fOK = _csp->decrypt(hPubKey, 0, TRUE, dwFlags, bData, &dwLen);
            if (S_OK != fOK) return fOK;
            {
                return fOK;
            }
        }

        DWORD dwIndex = 0, dwKeyLen;
        RSAPUBKEY rsapubkey;
        MY_DATA_BLOB pubExponent, modulus, prime1, prime2, exponent1, exponent2, coefficient;
        memcpy(&rsapubkey, bData, sizeof(RSAPUBKEY));

        if (rsapubkey.magic != 0x32415352)     //数据不对
        {
            // Not PRIVATEKEYBLOB
            return NTE_BAD_DATA;
        }
        if (OPENCSP_Alg::getKeyLen(CALG_RSA_KEYX) != rsapubkey.bitlen)  //长度不对
        {
            // key length is not expected!
            return NTE_BAD_DATA;
        }

        /*                java中RSA加解密的实现

        public static void main(String[] args) throws Exception {  
            // TODO Auto-generated method stub  
            HashMap<String, Object> map = RSAUtils.getKeys();  
            //生成公钥和私钥  
            RSAPublicKey publicKey = (RSAPublicKey) map.get("public");  
            RSAPrivateKey privateKey = (RSAPrivateKey) map.get("private");  

            //模  
            String modulus = publicKey.getModulus().toString();  
            //公钥指数  
            String public_exponent = publicKey.getPublicExponent().toString();  
            //私钥指数  
            String private_exponent = privateKey.getPrivateExponent().toString();  
            //明文  
            String ming = "123456789";  
            //使用模和指数生成公钥和私钥  
            RSAPublicKey pubKey = RSAUtils.getPublicKey(modulus, public_exponent);  
            RSAPrivateKey priKey = RSAUtils.getPrivateKey(modulus, private_exponent);  
            //加密后的密文  
            String mi = RSAUtils.encryptByPublicKey(ming, pubKey);  
            System.err.println(mi);  
            //解密后的明文  
            ming = RSAUtils.decryptByPrivateKey(mi, priKey);  
            System.err.println(ming);  
        }  
        */

        /*
        (1)选择一对不同的、足够大的素数p,q。
        (2)计算n=pq。
        (3)计算f(n)=(p-1)(q-1),同时对p, q严加保密,不让任何人知道。
        (4)找一个与f(n)互质的数e,且1<e<f(n)。
        (5)计算d,使得de≡1 mod f(n)。
        (6)公钥KU=(e,n),私钥KR=(d,n)。
        (7)加密时,先将明文变换成0至n-1的一个整数M。若明文较长,
             可先分割成适当的组,然后再进行交换。设密文为C,加密
        (8)解密
        */

        // Now collect key pair components     非对称加密算法:RSA加密算法。RSA密钥数据结构
        dwKeyLen = rsapubkey.bitlen;  //模数的实际位长度,8的倍数
        pubExponent.insert(pubExponent.end(), bData + 2 * (sizeof(DWORD)),
            bData + 3 * (sizeof(DWORD)));  //公开密钥e
        dwIndex += sizeof(RSAPUBKEY);

        modulus.insert(modulus.end(), bData + dwIndex,
            bData + dwIndex + dwKeyLen / 8); //模数,实际长度bitlen/8字节
        dwIndex += dwKeyLen / 8;

        prime1.insert(prime1.end(), bData + dwIndex, 
            bData + dwIndex + dwKeyLen / 16);  //素数p,实际长度bitlen/16字节
        dwIndex += dwKeyLen / 16;

        prime2.insert(prime2.end(), bData + dwIndex, 
            bData + dwIndex + dwKeyLen / 16);  //素数q,实际长度bitlen/16字节
        dwIndex += dwKeyLen / 16;

        exponent1.insert(exponent1.end(), bData + dwIndex,
            bData + dwIndex + dwKeyLen / 16);//d mod (p-1)的值,实际长度bitlen/16字节
        dwIndex += dwKeyLen / 16;

        exponent2.insert(exponent2.end(), bData + dwIndex,
            bData + dwIndex + dwKeyLen / 16);//d mod (q-1)的值,实际长度bitlen/16字节
        dwIndex += dwKeyLen / 16;

        coefficient.insert(coefficient.end(), bData + dwIndex,
            bData + dwIndex + dwKeyLen / 16);//q模p的乘法逆元,实际长度bitlen/16字节
        dwIndex += dwKeyLen / 16;

        // In MS, it's always little endian, so reverse it.
        // At the same time, construct them to meet with smart card requirement
        MY_DATA_BLOB rsakeyblob;

        // PUBLIC KEY: N + E
        reverse(modulus.begin(),        modulus.end());
           //填充数据结构后,翻转是改变字节序,与与卡传送数据有关
        rsakeyblob.insert(rsakeyblob.end(), modulus.begin(), modulus.end()); 
        reverse(pubExponent.begin(),    pubExponent.end());
        rsakeyblob.insert(rsakeyblob.end(), pubExponent.begin(), pubExponent.end());

        // PRIVATE KEY: Q + P + Qi + DQ + DP
        reverse(prime2.begin(),         prime2.end());
        rsakeyblob.insert(rsakeyblob.end(), prime2.begin(), prime2.end());
        reverse(prime1.begin(),         prime1.end());
        rsakeyblob.insert(rsakeyblob.end(), prime1.begin(), prime1.end());
        reverse(coefficient.begin(),    coefficient.end());
        rsakeyblob.insert(rsakeyblob.end(), coefficient.begin(), coefficient.end());
        reverse(exponent2.begin(),      exponent2.end());
        rsakeyblob.insert(rsakeyblob.end(), exponent2.begin(), exponent2.end());
        reverse(exponent1.begin(),      exponent1.end());
        rsakeyblob.insert(rsakeyblob.end(), exponent1.begin(), exponent1.end());

        fOK = pCard->importKey(kn.c_str(), (BYTE)dwKeySpec, (LPBYTE)&rsakeyblob[0], 
            (DWORD)rsakeyblob.size());////将密钥对导入特定的密钥容器
        if (fOK != S_OK) return fOK;

        pKey = new OPENCSP_RSAKeyInCard(pCard, kn, CALG_RSA_KEYX);

        return fOK;
    }

    DWORD OPENCSP_Key::importKey(const BYTE* pbData, DWORD dwDataLen,
        //导入密钥from a key binary large object (BLOB) to CSP
        HCRYPTKEY hPubKey, DWORD dwFlags, OPENCSP_Key*& pKey)
    {
        OPENCSP_Key* key;
        BLOBHEADER bh;
        memcpy(&bh, pbData, sizeof(bh));

        switch (bh.bType)
        {
        case SIMPLEBLOB:
            {
                key = new OPENCSP_SessionKey(bh.aiKeyAlg, dwFlags);
                if (!key) return NTE_NO_MEMORY;
                DWORD dwRet = key->_csp->importKey(pbData, dwDataLen, hPubKey, 
                    dwFlags, &key->_hKeyOfMSCSP);
                if (S_OK != dwRet)
                {
                    delete key;
                    return dwRet;
                }

                pKey = key;
            }
        }
        return S_OK;
    }

    const BOOL OPENCSP_Key::isSessionKey() const           //是否是会话密钥
    {
        return (!(GET_ALG_TYPE(_algId) ^ ALG_TYPE_RSA) ? TRUE : FALSE);
    }

    const BOOL OPENCSP_Key::isBlockCipherKey() const
    {
        return (!(GET_ALG_TYPE(_algId) ^ ALG_TYPE_BLOCK) ? TRUE : FALSE);
    }

    const BOOL OPENCSP_Key::isExportable() const   //是否可以导出
    {
        return (_flags ^ CRYPT_EXPORTABLE ? TRUE : FALSE);
    }

    //----------------------------------------------------------------------------------------
    OPENCSP_SessionKey::OPENCSP_SessionKey(ALG_ID algId, DWORD dwFlags)
    :OPENCSP_Key(algId, dwFlags)
    {
    }

    OPENCSP_SessionKey::~OPENCSP_SessionKey()
    {
    }

    DWORD OPENCSP_SessionKey::exportKey(HCRYPTKEY hKey, DWORD dwBlobType, DWORD dwFlags,
        BYTE* pbData, DWORD* pdwDataLen)//从CSP导出密钥
    {
        _csp->exportKey(_hKeyOfMSCSP, hKey, dwBlobType, dwFlags, pbData, pdwDataLen);

        return GetLastError();
    }
    DWORD OPENCSP_SessionKey::encrypt(BOOL Final, DWORD dwFlags, BYTE* pbData, 
        DWORD* pdwDataLen, DWORD dwBufLen)   //加密
    {
        _csp->encrypt(_hKeyOfMSCSP, 0, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
        return GetLastError();
    }  
    DWORD OPENCSP_SessionKey::decrypt(BOOL Final, DWORD dwFlags, BYTE* pbData,
        DWORD* pdwDataLen)  //解密
    {
        _csp->decrypt(_hKeyOfMSCSP, 0, Final, dwFlags, pbData, pdwDataLen);
        return GetLastError();
    }

    DWORD OPENCSP_SessionKey::signHash(OPENCSP_Hash* pHash, LPCTSTR sDescription,
        DWORD dwFlags, BYTE* pbSignature, DWORD* pdwSigLen)//哈希值签名
    {
        return E_NOTIMPL;
    }

    DWORD OPENCSP_SessionKey::verifySignature(OPENCSP_Hash* pHash, const BYTE* pbSignature,
        DWORD dwSigLen, LPCTSTR szDescription, DWORD dwFlags)//验证签名
    {
        return E_NOTIMPL;
    }


    const DWORD OPENCSP_SessionKey::getBlockLen() const
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_BLOCKLEN, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    const DWORD OPENCSP_SessionKey::getKeyLen() const  //获取密钥长度
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_KEYLEN, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    const DWORD OPENCSP_SessionKey::getPerms() const  //获取权限
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_PERMISSIONS, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    DWORD OPENCSP_SessionKey::setPerms(BYTE* pbData)    //设置访问权限
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_PERMISSIONS, pbData, 0);
    }

    DWORD OPENCSP_SessionKey::getSaltValue(SALT_VALUE& sv) const  //获取混淆值,哈希算法中唯一
    {
        DWORD fOK;
        BYTE bData[64] = {0};
        DWORD dwLen = sizeof(bData);

        fOK = _csp->getKeyParam(_hKeyOfMSCSP, KP_SALT, bData, &dwLen, 0);
        if (S_OK != fOK) return fOK;
        sv.insert(sv.end(), bData, bData + dwLen);

        return S_OK;
    }

    DWORD OPENCSP_SessionKey::setSaltValue(BYTE* pbData)     //设置混淆值
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_SALT, pbData, 0);
    }

    DWORD OPENCSP_SessionKey::getIV(IV_VALUE& iv) const   //获取算法的初始向量
    {
        DWORD fOK;
        BYTE bData[64] = {0};
        DWORD dwLen = sizeof(bData);

        fOK = _csp->getKeyParam(_hKeyOfMSCSP, KP_IV, bData, &dwLen, 0);
        if (!fOK) return fOK;
        iv.insert(iv.end(), bData, bData + dwLen);

        return S_OK;
    }

    DWORD OPENCSP_SessionKey::setIV(BYTE* pbData)    //设置算法的初始向量
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_IV, pbData, 0);
    }
    //算法填充,No padding加密以一个完整的块结束,而没有多余的数据
    DWORD OPENCSP_SessionKey::setPadding(BYTE* pbData)    
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_PADDING, pbData, 0);
    }

    DWORD OPENCSP_SessionKey::setMode(BYTE* pbData)   //设置加密模式
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_MODE, pbData, 0);
    }

    DWORD OPENCSP_SessionKey::setModeBits(BYTE* pbData)  //设置加密模式位数
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_MODE_BITS, pbData, 0);
    }

    DWORD OPENCSP_SessionKey::getPadding(PADDING_VALUE& pv) const  //获取算法填充
    {
        DWORD fOK;
        BYTE bData[32] = {0};
        DWORD dwLen = sizeof(bData);

        fOK = _csp->getKeyParam(_hKeyOfMSCSP, KP_PADDING, bData, &dwLen, 0);
        if (S_OK != fOK) return fOK;
        pv.insert(pv.end(), bData, bData + dwLen);
        return S_OK;
    }

    const DWORD OPENCSP_SessionKey::getMode() const  //获取加密模式
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_MODE, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    const DWORD OPENCSP_SessionKey::getModeBits() const  //得到加密模式位数
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_MODE_BITS, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    const DWORD OPENCSP_SessionKey::getEffectiveLen() const  //得到加密有效位
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_EFFECTIVE_KEYLEN, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    DWORD OPENCSP_SessionKey::setEffectiveLen(BYTE* pbData)  //设置加密有效位
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_EFFECTIVE_KEYLEN, pbData, 0);
    }

    //----------------------------------------------------------------------------------------
    OPENCSP_RSAKeyInMemory::OPENCSP_RSAKeyInMemory(ALG_ID algId, DWORD dwFlags)
    :OPENCSP_Key(algId, dwFlags)
    {
    }

    OPENCSP_RSAKeyInMemory::~OPENCSP_RSAKeyInMemory()
    {
    }

    DWORD OPENCSP_RSAKeyInMemory::exportKey(HCRYPTKEY hKey, DWORD dwBlobType,
        DWORD dwFlags, BYTE* pbData, DWORD* pdwDataLen)
    {
        _csp->exportKey(_hKeyOfMSCSP, hKey, dwBlobType, dwFlags, pbData, pdwDataLen);
        return GetLastError();
    }

    DWORD OPENCSP_RSAKeyInMemory::encrypt(BOOL Final, DWORD dwFlags, BYTE* pbData,
        DWORD* pdwDataLen, DWORD dwBufLen)
    {
        _csp->encrypt(_hKeyOfMSCSP, 0, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
        return GetLastError();
    }

    DWORD OPENCSP_RSAKeyInMemory::decrypt(BOOL Final, DWORD dwFlags, BYTE* pbData,
        DWORD* pdwDataLen)
    {
        _csp->decrypt(_hKeyOfMSCSP, 0, Final, dwFlags, pbData, pdwDataLen);
        return GetLastError();
    }

    DWORD OPENCSP_RSAKeyInMemory::signHash(OPENCSP_Hash* pHash, LPCTSTR sDescription, 
        DWORD dwFlags, BYTE* pbSignature, DWORD* pdwSigLen)
    {
        _csp->signHash(pHash->getMSHash(), AT_KEYEXCHANGE, sDescription, dwFlags, 
            pbSignature, pdwSigLen);
        return GetLastError();
    }

    DWORD OPENCSP_RSAKeyInMemory::verifySignature(OPENCSP_Hash* pHash, const BYTE* pbSignature,
        DWORD dwSigLen, LPCTSTR szDescription, DWORD dwFlags)
    {
        _csp->verifySignature(pHash->getMSHash(), pbSignature, dwSigLen, getKeyOfMSCSP(),
            szDescription, dwFlags);
        return GetLastError();
    }

    const DWORD OPENCSP_RSAKeyInMemory::getBlockLen() const
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_BLOCKLEN, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    const DWORD OPENCSP_RSAKeyInMemory::getKeyLen() const
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_KEYLEN, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    const DWORD OPENCSP_RSAKeyInMemory::getPerms() const
    {
        DWORD dwRet = 0;
        BYTE bData[4] = {0};
        DWORD dwLen = sizeof(bData);

        _csp->getKeyParam(_hKeyOfMSCSP, KP_PERMISSIONS, bData, &dwLen, 0);
        memcpy(&dwRet, &bData[0], dwLen);

        return dwRet;
    }

    DWORD OPENCSP_RSAKeyInMemory::setPerms(BYTE* pbData)
    {
        return _csp->setKeyParam(_hKeyOfMSCSP, KP_PERMISSIONS, pbData, 0);
    }


    //------------------------------------------------------------------------------------
    DWORD OPENCSP_RSAKeyInCard::_perm = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ;

    OPENCSP_RSAKeyInCard::OPENCSP_RSAKeyInCard(OPENCSP_CardAccess* pCardAccess, 
        const KEYSET_NAME& kn, ALG_ID algId, DWORD dwFlags)
    :OPENCSP_Key(algId, dwFlags), _cardPtr(pCardAccess), _keysetName(kn)
    {
    }

    OPENCSP_RSAKeyInCard::~OPENCSP_RSAKeyInCard()
    {
    }

    const DWORD OPENCSP_RSAKeyInCard::getBlockLen() const
    {
        return OPENCSP_Alg::getKeyLen(_algId);
    }

    const DWORD OPENCSP_RSAKeyInCard::getKeyLen() const
    {
        return OPENCSP_Alg::getKeyLen(_algId);
    }

    const DWORD OPENCSP_RSAKeyInCard::getPerms() const
    {
        return _perm;
    }

    DWORD OPENCSP_RSAKeyInCard::setPerms(BYTE* pbData)
    {
        return NTE_PERM;
    }

    DWORD OPENCSP_RSAKeyInCard::exportKey(HCRYPTKEY hKey, DWORD dwBlobType,
        DWORD dwFlags, BYTE* pbData, DWORD* pdwDataLen)   //从卡到电脑
    {
        DWORD fOK = S_OK;

        switch(dwBlobType)    //二进制容器的类型
        {
        case PUBLICKEYBLOB:
            {
                if (hKey != 0)
                    return NTE_BAD_KEY;

                if (pbData == NULL)
                {
                    *pdwDataLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + 128;
                    return S_OK;
                }

                if (pbData && (*pdwDataLen < sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + 128))
                {
                    *pdwDataLen = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + 128;
                    return ERROR_MORE_DATA;
                }

                BYTE bData[512] = {0};
                DWORD dwDataLen = 512;
                fOK = _cardPtr->readPublicKey(_keysetName.c_str(), bData, &dwDataLen); //读公钥
                if (fOK != S_OK)
                    return fOK;

                // now construct public key blob      //造个存储公钥的BIOB
                DWORD dwIndex = 0;
                PUBLICKEYSTRUC pks = {0};
                pks.aiKeyAlg = CALG_RSA_KEYX;
                pks.bType = PUBLICKEYBLOB;
                pks.bVersion = CUR_BLOB_VERSION;
                pks.reserved = 0;

                RSAPUBKEY rpk = {0};
                rpk.bitlen = 1024;
                rpk.magic = 0x31415352; //Microsoft's magic number
                MY_DATA_BLOB mdb;
                mdb.insert(mdb.end(), bData, bData + sizeof(DWORD));
                reverse(mdb.begin(), mdb.end());
                memcpy(&(rpk.pubexp), &mdb[0], sizeof(DWORD)); 

                memcpy(pbData, &pks, sizeof(PUBLICKEYSTRUC));
                dwIndex += sizeof(PUBLICKEYSTRUC);
                memcpy(pbData + dwIndex, &rpk, sizeof(RSAPUBKEY));
                dwIndex += sizeof(RSAPUBKEY);

                /* BIG -> LITTLE endian transform */      
                mdb.clear();
                mdb.insert(mdb.end(), bData + sizeof(DWORD), 
                    bData + sizeof(DWORD) + dwDataLen - sizeof(DWORD));
                reverse(mdb.begin(), mdb.end());
                memcpy(pbData + dwIndex, &mdb[0], mdb.size());
                /*pubExponent has already assigned*/
                *pdwDataLen = dwIndex + dwDataLen - sizeof(DWORD);
            }
            break;
        case PRIVATEKEYBLOB:
            // not support export private key from card!
            return NTE_BAD_DATA;
        default:
            return NTE_BAD_TYPE;
        }
        return fOK;
    }
    DWORD OPENCSP_RSAKeyInCard::encrypt(BOOL Final, DWORD dwFlags, BYTE* pbData, 
        DWORD* pdwDataLen, DWORD dwBufLen)
    {
        DWORD fOK = S_OK;

        if (dwFlags != 0)
            return NTE_BAD_FLAGS;

        if (!pbData) return NTE_BAD_DATA;
        if (*pdwDataLen > 0x80 - 2 - 1) return NTE_BAD_DATA;
        if (dwBufLen < 0x80) return NTE_BAD_LEN;

        BYTE bIn[128] = {0x00, 0x02}, bOut[128] = {0};
        DWORD dwInLen, dwOutLen = 128, dwPadding;
        dwInLen = *pdwDataLen;

        dwPadding = 0x80 - 2 - 1 - dwInLen;
        memset(bIn + 2, 0xff, dwPadding);
        memcpy(bIn + 2 + dwPadding + 1, pbData, dwInLen);

        MY_DATA_BLOB mdb;
        mdb.insert(mdb.end(), bIn, bIn + 0x80);
        reverse(mdb.begin(), mdb.end());
        memcpy(bIn, &mdb[0], mdb.size());

        fOK = _cardPtr->computeCrypt(_keysetName.c_str(), CARD_OPER_RSA_VERYIFY, bIn,
            0x80, bOut, &dwOutLen);////////用密钥计算
        if (fOK != S_OK)
            return fOK;

        memcpy(pbData, bOut, dwOutLen);
        *pdwDataLen = dwOutLen;

        return S_OK;
    }

    DWORD OPENCSP_RSAKeyInCard::decrypt(BOOL Final, DWORD dwFlags, BYTE* pbData, 
        DWORD* pdwDataLen)
    {
        // use private key to decrypt(SIGN)
        DWORD fOK = S_OK;

        if (dwFlags != 0) return NTE_BAD_FLAGS;
        if (!pbData) return NTE_BAD_DATA;
        if (*pdwDataLen != 0x80) return NTE_BAD_DATA;

        MY_DATA_BLOB mdb;
        BYTE bOut[128] = {0};
        DWORD dwInLen, dwOutLen = 128;
        dwInLen = *pdwDataLen;

        mdb.clear();
        mdb.insert(mdb.end(), pbData, pbData + dwInLen);
        reverse(mdb.begin(), mdb.end());

        fOK = _cardPtr->computeCrypt(_keysetName.c_str(), CARD_OPER_RSA_SIGN, &mdb[0],
            dwInLen, bOut, &dwOutLen);//用密钥计算
        if (fOK != S_OK)
            return fOK;

        // get the actual data
        if (bOut[0] == 0x00 && bOut[1] == 0x02)
        {
            DWORD dwIndex = 2;
            while (1)
            {
                if (bOut[dwIndex] == 0)
                {
                    break;
                }
                dwIndex++;
            }
            *pdwDataLen = dwOutLen - dwIndex - 1;
            memcpy(pbData, bOut + dwIndex + 1, *pdwDataLen);
        }
        else
            return NTE_BAD_DATA;

        return S_OK;
    }

    DWORD OPENCSP_RSAKeyInCard::signHash(OPENCSP_Hash* pHash, LPCTSTR sDescription, 
        DWORD dwFlags, BYTE* pbSignature, DWORD* pdwSigLen)
    {
        DWORD fOK = S_OK;

        HASH_VALUE hv;
        hv.clear();

        if (dwFlags == 0)
        {
            if (pHash->getHashAlg() == CALG_MD5)
                hv.insert(hv.end(), s_bMD5DigestInfo, s_bMD5DigestInfo + sizeof(s_bMD5DigestInfo));
            if (pHash->getHashAlg() == CALG_SHA1)
                hv.insert(hv.end(), s_bShaDigestInfo, s_bShaDigestInfo + sizeof(s_bShaDigestInfo));
        }
        fOK = pHash->getHashValue(hv);
        if (fOK != S_OK)
            return fOK;

        BYTE bIn[0x80] = {0x00, 0x01}, bOut[0x80] = {0};
        DWORD dwInLen, dwOutLen = 0x80, dwPaddings = 0;

        dwInLen = (DWORD)hv.size();
        dwPaddings = 0x80 - 2 - dwInLen - 1;
        memset(bIn + 2, 0xff, dwPaddings);
        memcpy(bIn + 2 + dwPaddings + 1, &hv[0], dwInLen);

        fOK = _cardPtr->computeCrypt(_keysetName.c_str(), CARD_OPER_RSA_SIGN, bIn,
            0x80, bOut, &dwOutLen);//用密钥计算
        if (fOK != S_OK) return fOK;

        MY_DATA_BLOB mdb;
        mdb.clear();
        mdb.insert(mdb.end(), bOut, bOut + 0x80);
        reverse(mdb.begin(), mdb.end());

        *pdwSigLen = 0x80;
        memcpy(pbSignature, &mdb[0], 0x80);

        return fOK;
    }

    DWORD OPENCSP_RSAKeyInCard::verifySignature(OPENCSP_Hash* pHash, const BYTE* pbSignature,
        DWORD dwSigLen, LPCTSTR szDescription, DWORD dwFlags)
    {
        DWORD fOK = S_OK;
        BYTE bIn[128] = {0x00}, bOut[128] = {0x00};
        DWORD dwInLen = dwSigLen, dwOutLen = 0x80;
        MY_DATA_BLOB mdb;

        if (dwInLen != 0x80) return ERROR_BAD_LENGTH;
        if (pbSignature == NULL) return NTE_BAD_DATA;

        HASH_VALUE hv;
        hv.clear();

        if (dwFlags == 0)
        {
            if (pHash->getHashAlg() == CALG_MD5)
                hv.insert(hv.end(), s_bMD5DigestInfo, s_bMD5DigestInfo + sizeof(s_bMD5DigestInfo));
            if (pHash->getHashAlg() == CALG_SHA1)
                hv.insert(hv.end(), s_bShaDigestInfo, s_bShaDigestInfo + sizeof(s_bShaDigestInfo));
        }
        fOK = pHash->getHashValue(hv);
        if (fOK != S_OK)
            return fOK;

        mdb.clear();
        mdb.insert(mdb.end(), pbSignature, pbSignature + 0x80);
        reverse(mdb.begin(), mdb.end());

        fOK = _cardPtr->computeCrypt(_keysetName.c_str(), CARD_OPER_RSA_VERYIFY, &mdb[0],
            0x80, bOut, &dwOutLen);//用密钥计算
        if (fOK != S_OK)
            return fOK;

        // discard off padding(PKCS#1 type 1)
        if (bOut[0] == 0x00 && bOut[1] == 0x01)
        {
            DWORD dwIndex = 2;
            while(1)
            {
                if (bOut[dwIndex] == 0)
                {
                    break;
                }
                dwIndex ++;
            }
            if (memcmp(&bOut[dwIndex + 1], &hv[0], 0x80 - dwIndex - 1) != 0)
            {
                return NTE_BAD_SIGNATURE;
            }
        }
        else 
            return NTE_BAD_DATA;

        return fOK;
    }


    DWORD OPENCSP_RSAKeyInCard::getCertificate(BYTE* pbCert, LPDWORD lpdwCertSize)
    {
        DWORD fOK = S_OK;

        BYTE bObjStatus = 0, bKeyUsage = 0;
        fOK = _cardPtr->getKeysetIdObjectStatus(_keysetName.c_str(), &bObjStatus,
            &bKeyUsage);//读取密钥容器状态
        if (fOK != S_OK)
        {
            return fOK;
        }

        if ((bObjStatus & 0x01) != 0)
        {
            // certificate doesn't exist yet
            return NTE_BAD_KEY;
        }

        fOK = _cardPtr->readCertificate(_keysetName.c_str(), pbCert, lpdwCertSize);//读取证书
        if (fOK != S_OK)
        {
            return fOK;
        }
        return S_OK;
    }

    DWORD OPENCSP_RSAKeyInCard::setCertificate(LPCBYTE pbCert, DWORD dwCertSize)
    {
        DWORD fOK = S_OK;

        BYTE bObjStatus = 0, bKeyUsage = 0;
        fOK = _cardPtr->getKeysetIdObjectStatus(_keysetName.c_str(), &bObjStatus, &bKeyUsage);
        if (fOK != S_OK)
        {
            return fOK;
        }

        if (bObjStatus & 0x01)
        {
            // certificate doesn't exist yet
            return NTE_EXISTS;
        }

        fOK = _cardPtr->writeCertificate(_keysetName.c_str(), pbCert, dwCertSize);//写证书到密钥容器
        if (fOK != S_OK)
        {
            return fOK;
        }
        return S_OK;
    }

你可能感兴趣的:(opencsp)