欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互

发布时间:2025/3/20 编程问答 66 豆豆
生活随笔 收集整理的这篇文章主要介绍了 CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

(以下代码中都只做测试用,有些地方没有释放内存...这个自己解决下)

1.RSA非对称的,首先提供一个供测试用的证书和私钥的数据

1)pem格式的证书和私钥(公私钥是对应的)的base64编码

[cpp] view plaincopyprint?
  • void readPriKey(string &a){  
  •     a =  "-----BEGIN RSA PRIVATE KEY-----\n";  
  •     a.append("MIICXQIBAAKBgQDTFPiHkUX279j7OnK2ToLrwD/QI9N/fL/XoMnW1sBYJdSWs/VP\n");  
  •     a.append("5oywvy6yJ0KMpfYcbRCJh2oRbPw7T9IrSHKdOkhB9PF6qwn90xb3Bk22l1LYZNfw\n");  
  •     a.append("IQKqRjAXctR8GSC5ULBQmZK2T6m50oD5vl6rD6lnmrQyQSZ3tNNRYbxx/QIDAQAB\n");  
  •     a.append("AoGAVqzSzOAzaY3dfHPorMGacvHzgiVj8IKqSAHHP8fZHZkTLXrh7ZhPBzjKFO+Y\n");  
  •     a.append("HSb843lJhB+tx1AIVtaVB57tKLHJSrAjFem6mHV+X+JhMeX358QS0QFbUiKfAK5e\n");  
  •     a.append("AkM1UdihF/3BX47DZUe44ntRqhffwsNGuZs2tB5FPHIpnGUCQQDvuBumamo+4tff\n");  
  •     a.append("oF9Z/iuMJTyDerPgrQbC85ZoHBULLKtnzSUt7pdSsPMMBfImDpquhkLntC+kFV5b\n");  
  •     a.append("yXu2nC5bAkEA4Wr1na+izFxmOnppvOjs7eFnch2THvNsajJ+Yl/jnRGGS5CLccrd\n");  
  •     a.append("JgUm+j91VUitl88XY/GXAUDIobGw/iAAhwJBANZziODekD/D5cVcDhFPDZwpb7Jb\n");  
  •     a.append("ofHcOJFNIv/uJ3FAu/J3lsw5hsxmGnhmFVOwevaoi9AG5RvQNgK9A9zAacMCQQDT\n");  
  •     a.append("PI4qVHp0k2nhBvGra4MLcBymXXyOloJUCjlRKpZ7i/6TNULXQcl3ZYCfJXRolRDH\n");  
  •     a.append("n/NFXxGoxPK+Q2ue2JJlAkBw1Z/1q2f6JYJ8pLBvdBSmOmKvm+O7x5s0csN7DnXf\n");  
  •     a.append("aK1D4/cyCbLdqgogbolQkOwIwUuXLkitW1ldh+MinTMz\n");  
  •     a.append("-----END RSA PRIVATE KEY-----\n");  
  •   
  • }  
  •   
  • void readCert(string &a){  
  •     a = "-----BEGIN CERTIFICATE-----\n";  
  •     a.append("MIIGVTCCBT2gAwIBAgIKGCyzsAAAAAAAbjANBgkqhkiG9w0BAQUFADA9MRUwEwYK\n");  
  •     a.append("CZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNpc3MxDzANBgNVBAMT\n");  
  •     a.append("BldIVUlTUzAeFw0xMjA0MTEwMTMxNThaFw0xMzA0MTEwMTMxNThaMHIxFTATBgoJ\n");  
  •     a.append("kiaJk/IsZAEZFgVsb2NhbDETMBEGCgmSJomT8ixkARkWA2lzczEOMAwGA1UEAxMF\n");  
  •     a.append("VXNlcnMxEjAQBgNVBAMMCeWRqOe7jeemuTEgMB4GCSqGSIb3DQEJARYRemhvdXl1\n");  
  •     a.append("emh5QDEyNi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANMU+IeRRfbv\n");  
  •     a.append("2Ps6crZOguvAP9Aj0398v9egydbWwFgl1Jaz9U/mjLC/LrInQoyl9hxtEImHahFs\n");  
  •     a.append("/DtP0itIcp06SEH08XqrCf3TFvcGTbaXUthk1/AhAqpGMBdy1HwZILlQsFCZkrZP\n");  
  •     a.append("qbnSgPm+XqsPqWeatDJBJne001FhvHH9AgMBAAGjggOkMIIDoDAdBgNVHQ4EFgQU\n");  
  •     a.append("vjfBpRVvsUsaWnX4dC81QzXu5T4wHwYDVR0jBBgwFoAU++PzmmgpwxErxTVrbJp5\n");  
  •     a.append("IzqO3RswggECBgNVHR8EgfowgfcwgfSggfGgge6GgbNsZGFwOi8vL0NOPVdIVUlT\n");  
  •     a.append("UyxDTj16c3ktMDIxMWMxNWEyNTIsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNl\n");  
  •     a.append("cnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9aXNzLERDPWxv\n");  
  •     a.append("Y2FsP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1j\n");  
  •     a.append("UkxEaXN0cmlidXRpb25Qb2ludIY2aHR0cDovL3pzeS0wMjExYzE1YTI1Mi5pc3Mu\n");  
  •     a.append("bG9jYWwvQ2VydEVucm9sbC9XSFVJU1MuY3JsMIIBFgYIKwYBBQUHAQEEggEIMIIB\n");  
  •     a.append("BDCBowYIKwYBBQUHMAKGgZZsZGFwOi8vL0NOPVdIVUlTUyxDTj1BSUEsQ049UHVi\n");  
  •     a.append("bGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlv\n");  
  •     a.append("bixEQz1pc3MsREM9bG9jYWw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNz\n");  
  •     a.append("PWNlcnRpZmljYXRpb25BdXRob3JpdHkwXAYIKwYBBQUHMAKGUGh0dHA6Ly96c3kt\n");  
  •     a.append("MDIxMWMxNWEyNTIuaXNzLmxvY2FsL0NlcnRFbnJvbGwvenN5LTAyMTFjMTVhMjUy\n");  
  •     a.append("Lmlzcy5sb2NhbF9XSFVJU1MuY3J0MAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgWg\n");  
  •     a.append("MD4GCSsGAQQBgjcVBwQxMC8GJysGAQQBgjcVCIbd/wqC4JYWgbmLGoKIvT+HxNMh\n");  
  •     a.append("gXGE+cJBg4yVdgIBZAIBBjApBgNVHSUEIjAgBggrBgEFBQcDAgYIKwYBBQUHAwQG\n");  
  •     a.append("CisGAQQBgjcKAwQwNQYJKwYBBAGCNxUKBCgwJjAKBggrBgEFBQcDAjAKBggrBgEF\n");  
  •     a.append("BQcDBDAMBgorBgEEAYI3CgMEMDsGA1UdEQQ0MDKgHQYKKwYBBAGCNxQCA6APDA16\n");  
  •     a.append("c3lAaXNzLmxvY2FsgRF6aG91eXV6aHlAMTI2LmNvbTBEBgkqhkiG9w0BCQ8ENzA1\n");  
  •     a.append("MA4GCCqGSIb3DQMCAgIAgDAOBggqhkiG9w0DBAICAIAwBwYFKw4DAgcwCgYIKoZI\n");  
  •     a.append("hvcNAwcwDQYJKoZIhvcNAQEFBQADggEBABj0xXhayI5JdqbuyAbqNwzGZxt4X102\n");  
  •     a.append("CFFeTU5jauspQjqEpar+/IQ+r3/vf162bY/lLHLpDarFLbZ9dAC6nqNfnE4gg9r7\n");  
  •     a.append("p+dbkbzFyBuSTqrzHQ6JgRYSdjwaksHV+uZuP7dfP2HXw4F1T3Ch/7ZKW9+ZlVvd\n");  
  •     a.append("QCygAu0z+TS2e7oRFb+swQLVKda8kPTM/b69+r/xdTHXY6+CkfVAk4oYBB56a9AD\n");  
  •     a.append("t1XOoAUa42fJdit6+7ssLLTZkZLNsQl6qsuTdv64dIMda4C6NnUsKDfjWGa+0vs3\n");  
  •     a.append("VjVNsUC5jo4qRc4XmBvJIx6e5M420sPj2Gi/+ssgmaXK+zUWzowIoMU=\n");  
  •     a.append("-----END CERTIFICATE-----\n");  
  • }  
  • void readPriKey(string &a){a = "-----BEGIN RSA PRIVATE KEY-----\n";a.append("MIICXQIBAAKBgQDTFPiHkUX279j7OnK2ToLrwD/QI9N/fL/XoMnW1sBYJdSWs/VP\n");a.append("5oywvy6yJ0KMpfYcbRCJh2oRbPw7T9IrSHKdOkhB9PF6qwn90xb3Bk22l1LYZNfw\n");a.append("IQKqRjAXctR8GSC5ULBQmZK2T6m50oD5vl6rD6lnmrQyQSZ3tNNRYbxx/QIDAQAB\n");a.append("AoGAVqzSzOAzaY3dfHPorMGacvHzgiVj8IKqSAHHP8fZHZkTLXrh7ZhPBzjKFO+Y\n");a.append("HSb843lJhB+tx1AIVtaVB57tKLHJSrAjFem6mHV+X+JhMeX358QS0QFbUiKfAK5e\n");a.append("AkM1UdihF/3BX47DZUe44ntRqhffwsNGuZs2tB5FPHIpnGUCQQDvuBumamo+4tff\n");a.append("oF9Z/iuMJTyDerPgrQbC85ZoHBULLKtnzSUt7pdSsPMMBfImDpquhkLntC+kFV5b\n");a.append("yXu2nC5bAkEA4Wr1na+izFxmOnppvOjs7eFnch2THvNsajJ+Yl/jnRGGS5CLccrd\n");a.append("JgUm+j91VUitl88XY/GXAUDIobGw/iAAhwJBANZziODekD/D5cVcDhFPDZwpb7Jb\n");a.append("ofHcOJFNIv/uJ3FAu/J3lsw5hsxmGnhmFVOwevaoi9AG5RvQNgK9A9zAacMCQQDT\n");a.append("PI4qVHp0k2nhBvGra4MLcBymXXyOloJUCjlRKpZ7i/6TNULXQcl3ZYCfJXRolRDH\n");a.append("n/NFXxGoxPK+Q2ue2JJlAkBw1Z/1q2f6JYJ8pLBvdBSmOmKvm+O7x5s0csN7DnXf\n");a.append("aK1D4/cyCbLdqgogbolQkOwIwUuXLkitW1ldh+MinTMz\n");a.append("-----END RSA PRIVATE KEY-----\n");}void readCert(string &a){a = "-----BEGIN CERTIFICATE-----\n";a.append("MIIGVTCCBT2gAwIBAgIKGCyzsAAAAAAAbjANBgkqhkiG9w0BAQUFADA9MRUwEwYK\n");a.append("CZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNpc3MxDzANBgNVBAMT\n");a.append("BldIVUlTUzAeFw0xMjA0MTEwMTMxNThaFw0xMzA0MTEwMTMxNThaMHIxFTATBgoJ\n");a.append("kiaJk/IsZAEZFgVsb2NhbDETMBEGCgmSJomT8ixkARkWA2lzczEOMAwGA1UEAxMF\n");a.append("VXNlcnMxEjAQBgNVBAMMCeWRqOe7jeemuTEgMB4GCSqGSIb3DQEJARYRemhvdXl1\n");a.append("emh5QDEyNi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANMU+IeRRfbv\n");a.append("2Ps6crZOguvAP9Aj0398v9egydbWwFgl1Jaz9U/mjLC/LrInQoyl9hxtEImHahFs\n");a.append("/DtP0itIcp06SEH08XqrCf3TFvcGTbaXUthk1/AhAqpGMBdy1HwZILlQsFCZkrZP\n");a.append("qbnSgPm+XqsPqWeatDJBJne001FhvHH9AgMBAAGjggOkMIIDoDAdBgNVHQ4EFgQU\n");a.append("vjfBpRVvsUsaWnX4dC81QzXu5T4wHwYDVR0jBBgwFoAU++PzmmgpwxErxTVrbJp5\n");a.append("IzqO3RswggECBgNVHR8EgfowgfcwgfSggfGgge6GgbNsZGFwOi8vL0NOPVdIVUlT\n");a.append("UyxDTj16c3ktMDIxMWMxNWEyNTIsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNl\n");a.append("cnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9aXNzLERDPWxv\n");a.append("Y2FsP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1j\n");a.append("UkxEaXN0cmlidXRpb25Qb2ludIY2aHR0cDovL3pzeS0wMjExYzE1YTI1Mi5pc3Mu\n");a.append("bG9jYWwvQ2VydEVucm9sbC9XSFVJU1MuY3JsMIIBFgYIKwYBBQUHAQEEggEIMIIB\n");a.append("BDCBowYIKwYBBQUHMAKGgZZsZGFwOi8vL0NOPVdIVUlTUyxDTj1BSUEsQ049UHVi\n");a.append("bGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlv\n");a.append("bixEQz1pc3MsREM9bG9jYWw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNz\n");a.append("PWNlcnRpZmljYXRpb25BdXRob3JpdHkwXAYIKwYBBQUHMAKGUGh0dHA6Ly96c3kt\n");a.append("MDIxMWMxNWEyNTIuaXNzLmxvY2FsL0NlcnRFbnJvbGwvenN5LTAyMTFjMTVhMjUy\n");a.append("Lmlzcy5sb2NhbF9XSFVJU1MuY3J0MAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgWg\n");a.append("MD4GCSsGAQQBgjcVBwQxMC8GJysGAQQBgjcVCIbd/wqC4JYWgbmLGoKIvT+HxNMh\n");a.append("gXGE+cJBg4yVdgIBZAIBBjApBgNVHSUEIjAgBggrBgEFBQcDAgYIKwYBBQUHAwQG\n");a.append("CisGAQQBgjcKAwQwNQYJKwYBBAGCNxUKBCgwJjAKBggrBgEFBQcDAjAKBggrBgEF\n");a.append("BQcDBDAMBgorBgEEAYI3CgMEMDsGA1UdEQQ0MDKgHQYKKwYBBAGCNxQCA6APDA16\n");a.append("c3lAaXNzLmxvY2FsgRF6aG91eXV6aHlAMTI2LmNvbTBEBgkqhkiG9w0BCQ8ENzA1\n");a.append("MA4GCCqGSIb3DQMCAgIAgDAOBggqhkiG9w0DBAICAIAwBwYFKw4DAgcwCgYIKoZI\n");a.append("hvcNAwcwDQYJKoZIhvcNAQEFBQADggEBABj0xXhayI5JdqbuyAbqNwzGZxt4X102\n");a.append("CFFeTU5jauspQjqEpar+/IQ+r3/vf162bY/lLHLpDarFLbZ9dAC6nqNfnE4gg9r7\n");a.append("p+dbkbzFyBuSTqrzHQ6JgRYSdjwaksHV+uZuP7dfP2HXw4F1T3Ch/7ZKW9+ZlVvd\n");a.append("QCygAu0z+TS2e7oRFb+swQLVKda8kPTM/b69+r/xdTHXY6+CkfVAk4oYBB56a9AD\n");a.append("t1XOoAUa42fJdit6+7ssLLTZkZLNsQl6qsuTdv64dIMda4C6NnUsKDfjWGa+0vs3\n");a.append("VjVNsUC5jo4qRc4XmBvJIx6e5M420sPj2Gi/+ssgmaXK+zUWzowIoMU=\n");a.append("-----END CERTIFICATE-----\n"); }2)CryptoAPI和openssl公私钥保持一致,去掉pem头尾直接用便是,没有加密

      证书的:

    [cpp] view plaincopyprint?
  • void readCertBase64(string &a){  
  •     a = "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\n";  
  • }  
  • void readCertBase64(string &a){a = "MIIGVTCCBT2gAwIBAgIKGCyzsAAAAAAAbjANBgkqhkiG9w0BAQUFADA9MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxEzARBgoJkiaJk/IsZAEZFgNpc3MxDzANBgNVBAMTBldIVUlTUzAeFw0xMjA0MTEwMTMxNThaFw0xMzA0MTEwMTMxNThaMHIxFTATBgoJkiaJk/IsZAEZFgVsb2NhbDETMBEGCgmSJomT8ixkARkWA2lzczEOMAwGA1UEAxMFVXNlcnMxEjAQBgNVBAMMCeWRqOe7jeemuTEgMB4GCSqGSIb3DQEJARYRemhvdXl1emh5QDEyNi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANMU+IeRRfbv2Ps6crZOguvAP9Aj0398v9egydbWwFgl1Jaz9U/mjLC/LrInQoyl9hxtEImHahFs/DtP0itIcp06SEH08XqrCf3TFvcGTbaXUthk1/AhAqpGMBdy1HwZILlQsFCZkrZPqbnSgPm+XqsPqWeatDJBJne001FhvHH9AgMBAAGjggOkMIIDoDAdBgNVHQ4EFgQUvjfBpRVvsUsaWnX4dC81QzXu5T4wHwYDVR0jBBgwFoAU++PzmmgpwxErxTVrbJp5IzqO3RswggECBgNVHR8EgfowgfcwgfSggfGgge6GgbNsZGFwOi8vL0NOPVdIVUlTUyxDTj16c3ktMDIxMWMxNWEyNTIsQ049Q0RQLENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9aXNzLERDPWxvY2FsP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q/YmFzZT9vYmplY3RDbGFzcz1jUkxEaXN0cmlidXRpb25Qb2ludIY2aHR0cDovL3pzeS0wMjExYzE1YTI1Mi5pc3MubG9jYWwvQ2VydEVucm9sbC9XSFVJU1MuY3JsMIIBFgYIKwYBBQUHAQEEggEIMIIBBDCBowYIKwYBBQUHMAKGgZZsZGFwOi8vL0NOPVdIVUlTUyxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1pc3MsREM9bG9jYWw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwXAYIKwYBBQUHMAKGUGh0dHA6Ly96c3ktMDIxMWMxNWEyNTIuaXNzLmxvY2FsL0NlcnRFbnJvbGwvenN5LTAyMTFjMTVhMjUyLmlzcy5sb2NhbF9XSFVJU1MuY3J0MAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgWgMD4GCSsGAQQBgjcVBwQxMC8GJysGAQQBgjcVCIbd/wqC4JYWgbmLGoKIvT+HxNMhgXGE+cJBg4yVdgIBZAIBBjApBgNVHSUEIjAgBggrBgEFBQcDAgYIKwYBBQUHAwQGCisGAQQBgjcKAwQwNQYJKwYBBAGCNxUKBCgwJjAKBggrBgEFBQcDAjAKBggrBgEFBQcDBDAMBgorBgEEAYI3CgMEMDsGA1UdEQQ0MDKgHQYKKwYBBAGCNxQCA6APDA16c3lAaXNzLmxvY2FsgRF6aG91eXV6aHlAMTI2LmNvbTBEBgkqhkiG9w0BCQ8ENzA1MA4GCCqGSIb3DQMCAgIAgDAOBggqhkiG9w0DBAICAIAwBwYFKw4DAgcwCgYIKoZIhvcNAwcwDQYJKoZIhvcNAQEFBQADggEBABj0xXhayI5JdqbuyAbqNwzGZxt4X102CFFeTU5jauspQjqEpar+/IQ+r3/vf162bY/lLHLpDarFLbZ9dAC6nqNfnE4gg9r7p+dbkbzFyBuSTqrzHQ6JgRYSdjwaksHV+uZuP7dfP2HXw4F1T3Ch/7ZKW9+ZlVvdQCygAu0z+TS2e7oRFb+swQLVKda8kPTM/b69+r/xdTHXY6+CkfVAk4oYBB56a9ADt1XOoAUa42fJdit6+7ssLLTZkZLNsQl6qsuTdv64dIMda4C6NnUsKDfjWGa+0vs3VjVNsUC5jo4qRc4XmBvJIx6e5M420sPj2Gi/+ssgmaXK+zUWzowIoMU=\n"; }因为尝试私钥没有导入成功,暂且不管,关于这一点待会再说验证交互成功的替换方案


    2.先来看下openssl的RSA实现方案,openssl本身提供了许多的padding方式,

    因为CryptoAPI只提供了PKCS1和OAEP两种补齐方式,默认使用的PKCS1,那这里就用PKCS1来验证吧

    1)首先需要导入证书和私钥,用于后续加密解密,这里就直接采用通过Base64码来导入

    [cpp] view plaincopyprint?
  • EVP_PKEY * importKey(){  
  •     OpenSSL_add_all_algorithms();  
  •   
  •     EVP_PKEY *prikey;  
  •     string a = "";  
  •     readPriKey(a);//获取私钥的base64码   
  •     const char* sPriKey = a.c_str();  
  •     BIO* bio = BIO_new_mem_buf((void*)sPriKey,strlen(sPriKey));//通过BIO放入内存   
  •     prikey = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);//读取bio,获取私钥对象   
  •     BYTE* sign_value = (BYTE*)malloc(1024);  
  •     unsigned int len;  
  •     return prikey;  
  • }  
  • EVP_PKEY * importCert(){  
  •     X509* cert;  
  •     OpenSSL_add_all_algorithms();  
  •     string a = "";  
  •     readCert(a);//证书的base64码   
  •     const char* sCert = a.c_str();  
  •     BIO* bio = BIO_new_mem_buf((void*)sCert,strlen(sCert));//存到内存   
  •     cert = PEM_read_bio_X509(bio,NULL,NULL,NULL);//读取bio,获取证书对象   
  •   
  •     EVP_PKEY* evp_pubKey =X509_get_pubkey(cert);//获取证书的公钥   
  •   
  •       
  •     int len;  
  •     if(evp_pubKey){  
  •         return evp_pubKey;  
  •     }  
  •     else  
  •         cout << "evp_pubKey == NULL" << endl;  
  •     return NULL;  
  • }  
  • EVP_PKEY * importKey(){OpenSSL_add_all_algorithms();EVP_PKEY *prikey;string a = "";readPriKey(a);//获取私钥的base64码const char* sPriKey = a.c_str();BIO* bio = BIO_new_mem_buf((void*)sPriKey,strlen(sPriKey));//通过BIO放入内存prikey = PEM_read_bio_PrivateKey(bio,NULL,NULL,NULL);//读取bio,获取私钥对象BYTE* sign_value = (BYTE*)malloc(1024);unsigned int len;return prikey; } EVP_PKEY * importCert(){X509* cert;OpenSSL_add_all_algorithms();string a = "";readCert(a);//证书的base64码const char* sCert = a.c_str();BIO* bio = BIO_new_mem_buf((void*)sCert,strlen(sCert));//存到内存cert = PEM_read_bio_X509(bio,NULL,NULL,NULL);//读取bio,获取证书对象EVP_PKEY* evp_pubKey =X509_get_pubkey(cert);//获取证书的公钥int len;if(evp_pubKey){return evp_pubKey;}elsecout << "evp_pubKey == NULL" << endl;return NULL; }
    2)有了公钥,私钥对象,接下来做非对称加密和解密就简单些了

    这里得提下补齐方式,因为和CryptoAPI的补齐方式要保持一致,折腾了许多时间

    CryptoAPI的默认补齐方式是PKCS1,我先以为就是NO_PADDING,结果发现CryptoAPI貌似就没有对NO_PADDING的支持

    openssl有NO_PADDING的支持,如果使用这个方式,最好自己将剩余位全部补上规律的数据,便于解密后容易获取到要的明文

    NO_PADDING就必须明文和密钥大小一样了,1024位RSA对应128字节明文

    PKCS1的得减去11字节存储PKCS1自己的数据,1024位RSA只能加密117字节明文

    OAEP则得减去41字节,只能加密87字节明文

    如果超过大小,当然可以自己去分节处理,这里就不予讨论了


    [cpp] view plaincopyprint?
  • void evelop(EVP_PKEY* evp_pubKey/*公钥对象*/,BYTE** out/*加密结果*/,unsigned int &cOut/*加密结果大小*/,const BYTE* in/*明文*/,unsigned int cIn/*明文大小*/){  
  •     OpenSSL_add_all_algorithms();  
  •     bool hasErr = true;  
  •     EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(evp_pubKey,NULL);  
  •     if(!ctx)  
  •         goto err;  
  •     if(EVP_PKEY_encrypt_init(ctx)<=0)  
  •         goto err;  
  •     if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)//设置补齐方式   
  •         goto err;  
  •   
  •     if(EVP_PKEY_encrypt(ctx,NULL,&cOut,in,cIn)<=0)//得到加密的长度,一般都是跟密钥一样长,1024位的RSA密钥就是128字节   
  •         goto err;  
  •     *out =(BYTE*) OPENSSL_malloc(cOut);  
  •     if(!out)  
  •         goto err;  
  •   
  •     if(EVP_PKEY_encrypt(ctx,*out,&cOut,in,cIn)<=0)//得到加密结果   
  •         goto err;  
  •     cout << "加密成功!" << endl;  
  •     hasErr = false;  
  • err:  
  •     EVP_PKEY_CTX_free(ctx);  
  •     if(!hasErr)  
  •         return;  
  •     return;  
  • }  
  •   
  • void develop(EVP_PKEY* priKey,BYTE** out,unsigned int &cOut, BYTE* data,unsigned int cData){  
  •     OpenSSL_add_all_algorithms();  
  •     bool hasErr = true;  
  •     EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(priKey,NULL);  
  •     if(!ctx)  
  •         goto err;  
  •     if (EVP_PKEY_decrypt_init(ctx) <= 0)  
  •         goto err;  
  •     if(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)//与加密同样的PKCS1补齐   
  •         goto err;  
  •     if (EVP_PKEY_decrypt(ctx, NULL, &cOut, data, cData) <= 0)//解密结果大小   
  •         goto err;  
  •     *out =(BYTE*) OPENSSL_malloc(cOut);//分配内存   
  •     if (!out)  
  •         goto err;  
  •     if (EVP_PKEY_decrypt(ctx, *out, &cOut, data, cData) <= 0)//得到解密结果   
  •         goto err;  
  •     hasErr = false;  
  • err://输出一些错误信息,偶尔错误信息得不到,只得到一些文件名和所在行,就跑到源代码去找...麻烦死了,如果有好的方案求回复~   
  •     EVP_PKEY_CTX_free(ctx);  
  •     if(!hasErr)  
  •         return;  
  •     cout << "err in develop" << endl;  
  •   
  •     const      char*file,*data1,*efunc,*elib,*ereason,*p;  
  •   
  •     int                         line,flags;  
  •     unsigned long  errn;  
  •   
  •   
  •     errn=ERR_peek_error_line_data(&file,&line,&data1,&flags);  
  •   
  •     printf("ERR_peek_error_line_data err : %ld,file :%s,line :%d,data :%s\n",errn,file,line,data1);  
  •   
  •   
  • }  
  • void evelop(EVP_PKEY* evp_pubKey/*公钥对象*/,BYTE** out/*加密结果*/,unsigned int &cOut/*加密结果大小*/,const BYTE* in/*明文*/,unsigned int cIn/*明文大小*/){OpenSSL_add_all_algorithms();bool hasErr = true;EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(evp_pubKey,NULL);if(!ctx)goto err;if(EVP_PKEY_encrypt_init(ctx)<=0)goto err;if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)//设置补齐方式goto err;if(EVP_PKEY_encrypt(ctx,NULL,&cOut,in,cIn)<=0)//得到加密的长度,一般都是跟密钥一样长,1024位的RSA密钥就是128字节goto err;*out =(BYTE*) OPENSSL_malloc(cOut);if(!out)goto err;if(EVP_PKEY_encrypt(ctx,*out,&cOut,in,cIn)<=0)//得到加密结果goto err;cout << "加密成功!" << endl;hasErr = false; err:EVP_PKEY_CTX_free(ctx);if(!hasErr)return;return; }void develop(EVP_PKEY* priKey,BYTE** out,unsigned int &cOut, BYTE* data,unsigned int cData){OpenSSL_add_all_algorithms();bool hasErr = true;EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(priKey,NULL);if(!ctx)goto err;if (EVP_PKEY_decrypt_init(ctx) <= 0)goto err;if(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)//与加密同样的PKCS1补齐goto err;if (EVP_PKEY_decrypt(ctx, NULL, &cOut, data, cData) <= 0)//解密结果大小goto err;*out =(BYTE*) OPENSSL_malloc(cOut);//分配内存if (!out)goto err;if (EVP_PKEY_decrypt(ctx, *out, &cOut, data, cData) <= 0)//得到解密结果goto err;hasErr = false; err://输出一些错误信息,偶尔错误信息得不到,只得到一些文件名和所在行,就跑到源代码去找...麻烦死了,如果有好的方案求回复~EVP_PKEY_CTX_free(ctx);if(!hasErr)return;cout << "err in develop" << endl;const char*file,*data1,*efunc,*elib,*ereason,*p;int line,flags;unsigned long errn;errn=ERR_peek_error_line_data(&file,&line,&data1,&flags);printf("ERR_peek_error_line_data err : %ld,file :%s,line :%d,data :%s\n",errn,file,line,data1);}
    3)自己测试下上面的代码吧,应该是没问题的

    2.CryptoAPI的RSA非对称加密

    1)首先依然是公私钥数据问题

    这里先看下通过base64导入证书吧,私钥的问题放在第三部分再讨论

    [cpp] view plaincopyprint?
  • PCCERT_CONTEXT  importCryptoCert(string base64Cert){  
  •     PCCERT_CONTEXT  pCertContext = NULL;   
  •     int len;  
  •     BYTE* certEncoded = Base64::base64_decode(base64Cert,len);//BASE64解码,很多方式,先前博文中有代码   
  •     if(pCertContext = CertCreateCertificateContext(  
  •         X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,                
  •         certEncoded,    
  •         len)) //直接就通过字节数组导入成证书上下文对象了   
  •     {  
  •         printf("A new certificate has been created.\n");  
  •   
  •     }  
  •     else  
  •     {  
  •         printf("A new certificate could not be created.\n");  
  •     }  
  •     return pCertContext;  
  • }  
  • PCCERT_CONTEXT importCryptoCert(string base64Cert){PCCERT_CONTEXT pCertContext = NULL; int len;BYTE* certEncoded = Base64::base64_decode(base64Cert,len);//BASE64解码,很多方式,先前博文中有代码if(pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, certEncoded, len)) //直接就通过字节数组导入成证书上下文对象了{printf("A new certificate has been created.\n");}else{printf("A new certificate could not be created.\n");}return pCertContext; }

    2)公钥加密,CryptoAPI的公钥加密也做了一些封装,没注意到的话得折腾好长时间

    我使用的CryptEncrypt,而加密结果是以 little-endian  排列的字节数组,openssl则与其相反

    关于CryptoAPI的说明,remark最后一句话,很小的字....

    [cpp] view plaincopyprint?
  • void encryptByPubKey(HCRYPTPROV hProv,PCCERT_CONTEXT cert,BYTE* text,unsigned long &len){  
  •       
  •     HCRYPTKEY hKey;  
  •       
  •       
  •     CERT_PUBLIC_KEY_INFO pubKeyInfo = cert->pCertInfo->SubjectPublicKeyInfo;//拿到公钥信息   
  •   
  •     if(!CryptImportPublicKeyInfoEx(hProv,X509_ASN_ENCODING,&pubKeyInfo,CALG_RSA_KEYX,0,NULL,&hKey))//导入,获取公钥对象   
  •     {  
  •         printf("CryptImportPublicKeyInfoEx error:0X%x.\n",GetLastError());  
  •         return;  
  •     }  
  •   
  •     if(!CryptEncrypt(hKey,NULL,true,0,text,&len,128))//加密,padding参数为0,默认就是PKCS1的,不用管了,最后一个参数为128,是对于1024位RSA密钥,明文text得分配128个字节   
  •     {  
  •         printf("CryptEncrypt error:0X%x.\n",GetLastError());  
  •         return;  
  •     }  
  • //以下将密文倒序,如果你在openssl倒序了,那这里就不用了,反正CryptoAPI和openssl本身的排列方式就是反的   
  •     for(int i = 0 ; i < len / 2;i++)  
  •     {  
  •         BYTE temp = text[i];  
  •         text[i] = text[len - i - 1];  
  •         text[len - i - 1] = temp;  
  •     }  
  •       
  •     printByte(text,len);  
  • }  
  • void encryptByPubKey(HCRYPTPROV hProv,PCCERT_CONTEXT cert,BYTE* text,unsigned long &len){HCRYPTKEY hKey;CERT_PUBLIC_KEY_INFO pubKeyInfo = cert->pCertInfo->SubjectPublicKeyInfo;//拿到公钥信息if(!CryptImportPublicKeyInfoEx(hProv,X509_ASN_ENCODING,&pubKeyInfo,CALG_RSA_KEYX,0,NULL,&hKey))//导入,获取公钥对象{printf("CryptImportPublicKeyInfoEx error:0X%x.\n",GetLastError());return;}if(!CryptEncrypt(hKey,NULL,true,0,text,&len,128))//加密,padding参数为0,默认就是PKCS1的,不用管了,最后一个参数为128,是对于1024位RSA密钥,明文text得分配128个字节{printf("CryptEncrypt error:0X%x.\n",GetLastError());return;} //以下将密文倒序,如果你在openssl倒序了,那这里就不用了,反正CryptoAPI和openssl本身的排列方式就是反的for(int i = 0 ; i < len / 2;i++){BYTE temp = text[i];text[i] = text[len - i - 1];text[len - i - 1] = temp;}printByte(text,len); }

    3)试下这个部分的加密吧,能够被openssl解密就没问题了

    3.以上只试了CryptoAPI加密openssl解密,因为私钥没导入成功的关系,也没时间再去尝试了,暂且换一种替代方案来测试

    如果CryptoAPI解密了CryptoAPI加密的,那这个也是等价的,那干脆直接从windows密钥库获取公私钥,用CryptoAPI直接做加密解密

    从windows库获取证书就不在这讨论了,看下私钥解密的部分

    [cpp] view plaincopyprint?
  • void decryptByPriKey(PCCERT_CONTEXT cert,BYTE* encText,unsigned long len){  
  •     //将结果再反序一次,用于CryptoAPI自己解密   
  •     for(int i = 0 ; i < len / 2;i++)  
  •     {  
  •         BYTE temp = encText[i];  
  •         encText[i] = encText[len - i - 1];  
  •         encText[len - i - 1] = temp;  
  •     }  
  •   
  •     HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyProv;  
  •     DWORD *dwKeyType;  
  •     BOOL bFreeKeyProv = FALSE;    
  •     if(!CryptAcquireCertificatePrivateKey(cert, 0, 0, &hKeyProv, dwKeyType, &bFreeKeyProv))  //获取证书对应的私钥句柄   
  •     {    
  •         printf("CryptAcquireCertificatePrivateKey error:0X%x.\n",GetLastError());  
  •         return;  
  •     }   
  •   
  •     HCRYPTKEY hKey;  
  •     if(!CryptGetUserKey(hKeyProv,AT_KEYEXCHANGE,&hKey))//通过句柄获取私钥对象   
  •     {  
  •         printf("CryptGetUserKey error:0X%x.\n",GetLastError());  
  •         return;  
  •     }  
  •   
  •     if(!CryptDecrypt(hKey,NULL,true,0,encText,&len)){//解密,也可以把padding参数换成CRYPT_DECRYPT_RSA_NO_PADDING_CHECK   
  •         printf("CryptDecrypt error:0X%x.\n",GetLastError());  
  •         return;  
  •     }  
  •   
  •     printByte(encText,len);  
  • }  
  • void decryptByPriKey(PCCERT_CONTEXT cert,BYTE* encText,unsigned long len){//将结果再反序一次,用于CryptoAPI自己解密for(int i = 0 ; i < len / 2;i++){BYTE temp = encText[i];encText[i] = encText[len - i - 1];encText[len - i - 1] = temp;}HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyProv;DWORD *dwKeyType;BOOL bFreeKeyProv = FALSE; if(!CryptAcquireCertificatePrivateKey(cert, 0, 0, &hKeyProv, dwKeyType, &bFreeKeyProv)) //获取证书对应的私钥句柄{ printf("CryptAcquireCertificatePrivateKey error:0X%x.\n",GetLastError());return;} HCRYPTKEY hKey;if(!CryptGetUserKey(hKeyProv,AT_KEYEXCHANGE,&hKey))//通过句柄获取私钥对象{printf("CryptGetUserKey error:0X%x.\n",GetLastError());return;}if(!CryptDecrypt(hKey,NULL,true,0,encText,&len)){//解密,也可以把padding参数换成CRYPT_DECRYPT_RSA_NO_PADDING_CHECKprintf("CryptDecrypt error:0X%x.\n",GetLastError());return;}printByte(encText,len); }如果到此都没有什么问题,整个交互就算完成了.

    前一篇提了AES的,还差一个签名的下回再来讨论了

    更多 0

    总结

    以上是生活随笔为你收集整理的CryptoAPI与openssl RSA非对称加密解密(PKCS1 PADDING)交互的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。