├── .gitignore ├── AStyle.exe ├── README.md ├── bin └── x86 │ └── vs2013 │ └── CryptoAPI-examples │ └── md │ ├── rsa-sing-file-test.bat │ └── rsa_file_sign │ ├── rsa-sign-file.exe │ ├── rsa_file_sign.bat │ ├── rsa_file_verify.bat │ ├── rsa_gen_key.bat │ └── test.txt ├── format_code.bat ├── premake5.exe ├── projects.bat ├── projects.lua └── src ├── base64 ├── encode.c ├── encode.h ├── memory.c ├── memory.h └── test.c ├── dsa_gen └── dsagen.c ├── rsa-sign-file ├── aes_rsa_sign.cpp ├── aes_rsa_sign.h ├── common.cpp ├── common.h ├── crypto_api_aes.cpp ├── crypto_api_aes.h ├── crypto_api_certificate.cpp ├── crypto_api_certificate.h ├── crypto_api_rsa.cpp ├── crypto_api_rsa.h └── main.cpp ├── rsa_gen └── dss.c ├── rsa_key_decode └── dh_decode.c ├── rsa_key_encode └── dh_encode.c ├── rsa_tool ├── encode.c ├── encode.h ├── memory.c ├── memory.h ├── rsa.c ├── rsa.h └── rsa_tool.c ├── rsacert ├── RSACert.cpp ├── RSACert.vcproj └── ReadMe.Txt ├── rsakey ├── RSAKey.cpp ├── RSAKey.vcproj └── ReadMe.Txt ├── sessionkey ├── ReadMe.Txt ├── SessionKey.cpp └── SessionKey.vcproj ├── signhash ├── Readme.txt ├── SignHash.cpp ├── Signhash.sln └── Signhash.vcproj └── test-base64 └── base64.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /build 3 | -------------------------------------------------------------------------------- /AStyle.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/AStyle.exe -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CryptoAPI-examples 2 | microsoft CryptoAPI examples 3 | 4 | RSA 加解密可采用 openssl cryptopp CryptoAPI 5 | 6 | 采用微软自带的 CryptoAPI 写个命令行更简单一些 7 | 8 | CryptoAPI 支持的加密算法 9 | 10 | ``` cpp 11 | CALG_3DES = 0x00006603,// Triple DES encryption algorithm. 12 | CALG_3DES_112 = 0x00006609,// Two-key triple DES encryption with effective key length equal to 112 bits. 13 | CALG_AES = 0x00006611,// Advanced Encryption Standard (AES). This algorithm is supported by the Microsoft AES Cryptographic Provider. 14 | CALG_AES_128 = 0x0000660e,// 128 bit AES. This algorithm is supported by the Microsoft AES Cryptographic Provider. 15 | CALG_AES_192 = 0x0000660f,// 192 bit AES. This algorithm is supported by the Microsoft AES Cryptographic Provider. 16 | CALG_AES_256 = 0x00006610,// 256 bit AES. This algorithm is supported by the Microsoft AES Cryptographic Provider. 17 | CALG_AGREEDKEY_ANY = 0x0000aa03,// Temporary algorithm identifier for handles of Diffie-Hellman–agreed keys. 18 | CALG_CYLINK_MEK = 0x0000660c,// An algorithm to create a 40-bit DES key that has parity bits and zeroed key bits to make its key length 64 bits. This algorithm is supported by the Microsoft Base Cryptographic Provider. 19 | CALG_DES = 0x00006601,// DES encryption algorithm. 20 | CALG_DESX = 0x00006604,// DESX encryption algorithm. 21 | CALG_DH_EPHEM = 0x0000aa02,// Diffie-Hellman ephemeral key exchange algorithm. 22 | CALG_DH_SF = 0x0000aa01,// Diffie-Hellman store and forward key exchange algorithm. 23 | CALG_DSS_SIGN = 0x00002200,// DSA public key signature algorithm. 24 | CALG_ECDH = 0x0000aa05,// Elliptic curve Diffie-Hellman key exchange algorithm. Note This algorithm is supported only through Cryptography API: Next Generation. Windows Server 2003 and Windows XP: This algorithm is not supported. 25 | CALG_ECDSA = 0x00002203,// Elliptic curve digital signature algorithm. Note This algorithm is supported only through Cryptography API: Next Generation. Windows Server 2003 and Windows XP: This algorithm is not supported. 26 | CALG_ECMQV = 0x0000a001,// Elliptic curve Menezes, Qu, and Vanstone (MQV) key exchange algorithm. This algorithm is not supported. 27 | CALG_HASH_REPLACE_OWF = 0x0000800b,// One way function hashing algorithm. 28 | CALG_HUGHES_MD5 = 0x0000a003,// Hughes MD5 hashing algorithm. 29 | CALG_HMAC = 0x00008009,// HMAC keyed hash algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 30 | CALG_KEA_KEYX = 0x0000aa04,// KEA key exchange algorithm (FORTEZZA). This algorithm is not supported. 31 | CALG_MAC = 0x00008005,// MAC keyed hash algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 32 | CALG_MD2 = 0x00008001,// MD2 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 33 | CALG_MD4 = 0x00008002,// MD4 hashing algorithm. 34 | CALG_MD5 = 0x00008003,// MD5 hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 35 | CALG_NO_SIGN = 0x00002000,// No signature algorithm. 36 | CALG_OID_INFO_CNG_ONLY = 0xffffffff,// The algorithm is only implemented in CNG. The macro, IS_SPECIAL_OID_INFO_ALGID, can be used to determine whether a cryptography algorithm is only supported by using the CNG functions. 37 | CALG_OID_INFO_PARAMETERS = 0xfffffffe,// The algorithm is defined in the encoded parameters. The algorithm is only supported by using CNG. The macro, IS_SPECIAL_OID_INFO_ALGID, can be used to determine whether a cryptography algorithm is only supported by using the CNG functions. 38 | CALG_PCT1_MASTER = 0x00004c04,// Used by the Schannel.dll operations system. This ALG_ID should not be used by applications. 39 | CALG_RC2 = 0x00006602,// RC2 block encryption algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 40 | CALG_RC4 = 0x00006801,// RC4 stream encryption algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 41 | CALG_RC5 = 0x0000660d,// RC5 block encryption algorithm. 42 | CALG_RSA_KEYX = 0x0000a400,// RSA public key exchange algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 43 | CALG_RSA_SIGN = 0x00002400,// RSA public key signature algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 44 | CALG_SCHANNEL_ENC_KEY = 0x00004c07,// Used by the Schannel.dll operations system. This ALG_ID should not be used by applications. 45 | CALG_SCHANNEL_MAC_KEY = 0x00004c03,// Used by the Schannel.dll operations system. This ALG_ID should not be used by applications. 46 | CALG_SCHANNEL_MASTER_HASH = 0x00004c02,// Used by the Schannel.dll operations system. This ALG_ID should not be used by applications. 47 | CALG_SEAL = 0x00006802,// SEAL encryption algorithm. This algorithm is not supported. 48 | CALG_SHA = 0x00008004,// SHA hashing algorithm. This algorithm is supported by the Microsoft Base Cryptographic Provider. 49 | CALG_SHA1 = 0x00008004,// Same as CALG_SHA. This algorithm is supported by the Microsoft Base Cryptographic Provider. 50 | CALG_SHA_256 = 0x0000800c,// 256 bit SHA hashing algorithm. This algorithm is supported by Microsoft Enhanced RSA and AES Cryptographic Provider.. Windows XP with SP3: This algorithm is supported by the Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype). Windows XP with SP2, Windows XP with SP1, and Windows XP: This algorithm is not supported. 51 | CALG_SHA_384 = 0x0000800d,// 384 bit SHA hashing algorithm. This algorithm is supported by Microsoft Enhanced RSA and AES Cryptographic Provider. Windows XP with SP3: This algorithm is supported by the Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype). Windows XP with SP2, Windows XP with SP1, and Windows XP: This algorithm is not supported. 52 | ``` 53 | 54 | ## CryptoAPI 简介 55 | 56 | CryptoAPI 为开发者提供在 Windows 下使用 PKI 的 API。CryptoAPI 包括编码、解码、加密、解密、Hash、数字证书管理和证书存储等功能。 57 | 58 | ## 常用 API 59 | 60 | ### CSP 相关 61 | 62 | 一个 CSP 是实现加密操作的独立模块,要实现加密,至少需要一个 CSP。每个 CSP 对 CryptAPI 的实现是不同的,使用的算法不同,有些包含了对硬件的支持。 63 | 64 | - CryptAcquireContext 获得指定 CSP 的密钥容器的句柄 65 | - CryptReleaseContext 释放由 CryptAcquireContext 得到的句柄 66 | 67 | 68 | ``` cpp 69 | BOOL OpenCryptContext(HCRYPTPROV* provider) 70 | { 71 | DWORD dwVersion = GetVersion(); 72 | DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion))); 73 | LPCTSTR pszProvider = MS_ENH_RSA_AES_PROV; 74 | 75 | if (dwMajor <= 5) 76 | pszProvider = MS_ENH_RSA_AES_PROV_XP; 77 | 78 | if (!CryptAcquireContext(provider, 0, pszProvider, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 79 | if (!CryptAcquireContext(provider, 0, pszProvider, PROV_RSA_AES, CRYPT_NEWKEYSET)) { 80 | return FALSE; 81 | } 82 | } 83 | 84 | return TRUE; 85 | } 86 | ``` 87 | 88 | 89 | 90 | ### 密钥相关 91 | 92 | 用来创建和销毁密钥,也可以使用一个已有的密钥 93 | 94 | - CryptDeriveKey 从一个密码中派生一个密钥 95 | - CryptDestoryKey 销毁密钥 96 | - CryptDuplicateKey 制作一个密钥和密钥状态的精确复制 97 | - CryptGenKey 创建一个随机密钥 98 | - CryptImportKey 把一个密钥 BLOB 传送到 CSP 中 99 | 100 | ### 加解密相关 101 | 102 | 用来加解密数据,需要指定一个密钥,这个密钥可以是由 CryptGenKey 、 CryptDuplicateKey 、 CryptImportKey 产生。 103 | 104 | - CryptEncrypt 使用指定加密密钥来加密一段信息 105 | - CryptDecrypt 使用指定加密密钥来解密一段密文 106 | 107 | ### 哈希和数字签名函数 108 | 109 | 用来计算 Hash、创建和校验数字签名。 110 | 111 | 112 | - CryptCreateHash 创建一个空哈希对象 113 | - CryptDestoryHash 销毁一个哈希对象 114 | - CryptDuplicateHash 复制一个哈希对象 115 | - CryptGetHashParam 得到一个哈希对象参数 116 | - CryptHashData 对一块数据进行哈希,把它加到指定的哈希对象中 117 | - CryptHashSessionKey 对一个会话密钥进行哈希,把它加到指定的哈希对象中 118 | - CryptSetHashParam 设置一个哈希对象的参数 119 | - CryptSignHash 对一个哈希对象进行签名 120 | - CryptVerifySignature 校验一个数字签名 121 | 122 | 123 | ## 会话密钥(对称加密)的生成 124 | 125 | 一般会话密钥可通过自己设置的(字符串密码+盐) HASH 后生成密钥, 或者通过随机数直接生成 126 | 127 | 如果是 AES 可以生成 key 和 iv 128 | 129 | ## 非对称加密的密钥生成 130 | 131 | 随机生成,生成的密钥保存到证书文件里(.pem/.pfx)里,可通过 openssl 来生成 132 | 133 | 134 | ## 加密脚本文件的流程 135 | 136 | 1. 生成一个固定 AES 密钥,用于加密脚本 137 | 2. 用 AES 密钥加密脚本 A.txt 生成 A.dat,用来保护脚本不明文出现 138 | 3. 生成 RSA 密钥对 139 | 4. 使用 RSA 私钥对 A.dat 进行签名,将签名信息放在 A.dat 的末端(生成 A.enc.dat) 140 | 5. 在客户端使用 RSA 公钥对 A.enc.dat 的前置数据(总大小-签名信息大小)进行 hash 签名验证 141 | 142 | 143 | 144 | ## links 145 | 146 | - [循环读取文件块加解密](https://github.com/balalala/Courseware_Office/blob/71d60e0b2eb718c7bd4de87e387757c4ae04baeb/win2.4/PKI/V2.4-20121023/Samples/CryptoAPI/VC/EncryptDecryptFile/EncryptFile.cpp) 147 | - [读写证书](https://github.com/ermilindwalekar/Windows_Classic_Samples/blob/cded84bed49cb8ef2095e6470ac83ee3264c4113/Samples/Win7Samples/netds/peertopeer/DRT/CAPIWrappers.cpp) 148 | - [数字证书原理,公钥私钥加密 - 读过最浅显易懂的密钥 topic](http://www.jianshu.com/p/671ebeddcf60) 149 | - [使用 C++ 实现数字证书中心演示系统](http://www.jianshu.com/p/3661d70138da) 150 | - [Singler 的专栏 C/C++ 与数字安全](http://blog.csdn.net/yyfzy) 151 | - [Win7_SDK_Samples/security/cryptoapi](https://github.com/bugparty/Win7_SDK_Samples/tree/0a9b432d9a3842208dfb97812920e3bc8abec024/security/cryptoapi) 152 | - https://github.com/DigitalGlobe/tools 153 | - https://github.com/leeqwind/PESignAnalyzer 154 | - [证书转换](https://github.com/ASMlover/study/blob/28cac4c6c504303c08973255c58d10a8d369bd69/cplusplus/RCF/include/RCF/Certificate.hpp) 155 | - [EncryptingDecrypting Data through PFX certificate on Windows Mobile](https://blogs.msdn.microsoft.com/raffael/2008/04/01/encryptingdecrypting-data-through-pfx-certificate-on-windows-mobile/) 156 | - [How to use certificate from disk with Microsoft CryptoAPI](https://www.codeproject.com/Articles/125124/How-to-use-certificate-from-disk-with-Microsoft-Cr) 157 | - [Digital Certificate Creator Tool](https://www.codeproject.com/Articles/570333/DigitalplusCertificateplusCreatorplusTool) 158 | - [Creating Self-signed Certificates](https://www.codeproject.com/Articles/1163827/Creating-Self-signed-Certificates) 159 | - [Encrypt/Self Decrypt Files in Native C++ and .NET](https://www.codeproject.com/Articles/4645/Encrypt-Self-Decrypt-Files-in-Native-C-and-NET) 160 | - [How to Sign Device Drivers with WDK 7.1](https://www.codeproject.com/Tips/1003158/How-to-Sign-Device-Drivers-with-WDK) -------------------------------------------------------------------------------- /bin/x86/vs2013/CryptoAPI-examples/md/rsa-sing-file-test.bat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/bin/x86/vs2013/CryptoAPI-examples/md/rsa-sing-file-test.bat -------------------------------------------------------------------------------- /bin/x86/vs2013/CryptoAPI-examples/md/rsa_file_sign/rsa-sign-file.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/bin/x86/vs2013/CryptoAPI-examples/md/rsa_file_sign/rsa-sign-file.exe -------------------------------------------------------------------------------- /bin/x86/vs2013/CryptoAPI-examples/md/rsa_file_sign/rsa_file_sign.bat: -------------------------------------------------------------------------------- 1 | rsa-sign-file.exe --src_filename=test.txt -------------------------------------------------------------------------------- /bin/x86/vs2013/CryptoAPI-examples/md/rsa_file_sign/rsa_file_verify.bat: -------------------------------------------------------------------------------- 1 | rsa-sign-file.exe --enc_filename=test.txt.enc -------------------------------------------------------------------------------- /bin/x86/vs2013/CryptoAPI-examples/md/rsa_file_sign/rsa_gen_key.bat: -------------------------------------------------------------------------------- 1 | rsa-sign-file.exe --genkey -------------------------------------------------------------------------------- /bin/x86/vs2013/CryptoAPI-examples/md/rsa_file_sign/test.txt: -------------------------------------------------------------------------------- 1 | 111111111111111111111111 -------------------------------------------------------------------------------- /format_code.bat: -------------------------------------------------------------------------------- 1 | cd /d "%~dp0" 2 | set astyle=%~dp0AStyle.exe --style=linux --s4 --p --H --U --f --v --w --c --xe --xL --xW 3 | set dir_path=".\src" 4 | echo "format source code......" 5 | for /R %dir_path% %%a in (*.cpp;*.c;*.cc;*.h;*.hpp) do %astyle% "%%a" 1>nul 2>nul 6 | echo "delete backup source code......" 7 | for /R %dir_path% %%a in (*.orig) do del "%%a" 8 | echo "format source code end." -------------------------------------------------------------------------------- /premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/premake5.exe -------------------------------------------------------------------------------- /projects.bat: -------------------------------------------------------------------------------- 1 | cd /d "%~dp0" 2 | set PATH=%~dp0;%PATH% 3 | mklink /d /j "E:\book-code" "H:\rover\rover-self-work\cpp\book-code" 4 | premake5 --file=projects.lua vs2013 5 | ::premake5 --file=projects.lua vs2005 6 | pause -------------------------------------------------------------------------------- /src/base64/encode.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include "encode.h" 31 | 32 | /** 33 | * 34 | * convert base64 string to binary 35 | * 36 | */ 37 | LPVOID b64tobin(LPVOID in, DWORD inLen, DWORD flags, PDWORD outLen) 38 | { 39 | LPVOID out = NULL; 40 | 41 | // calculate how much space required 42 | if (CryptStringToBinary(in, inLen, 43 | CRYPT_STRING_BASE64 | flags, 44 | NULL, outLen, NULL, NULL)) { 45 | out = xmalloc(*outLen); 46 | 47 | if (out != NULL) { 48 | // decode base64 49 | CryptStringToBinary(in, inLen, 50 | CRYPT_STRING_BASE64 | flags, 51 | out, outLen, NULL, NULL); 52 | } 53 | } 54 | 55 | return out; 56 | } 57 | 58 | /** 59 | * 60 | * convert binary to base64 string 61 | * 62 | */ 63 | LPVOID bintob64(LPVOID in, DWORD inLen, DWORD flags) 64 | { 65 | DWORD outLen; 66 | LPVOID out = NULL; 67 | 68 | // calculate space for string 69 | if (CryptBinaryToString(in, inLen, 70 | CRYPT_STRING_BASE64 | flags, NULL, &outLen)) { 71 | out = xmalloc(outLen); 72 | 73 | // convert it 74 | if (out != NULL) { 75 | CryptBinaryToString(in, inLen, 76 | CRYPT_STRING_BASE64 | flags, out, &outLen); 77 | } 78 | } 79 | 80 | return out; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/base64/encode.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #ifndef ENCODE_H 31 | #define ENCODE_H 32 | 33 | #include 34 | #include 35 | 36 | #include "memory.h" 37 | 38 | #ifdef _MSC_VER 39 | #pragma comment(lib, "Crypt32.lib") 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | LPVOID bintob64(LPVOID, DWORD, DWORD); 47 | LPVOID b64tobin(LPVOID, DWORD, DWORD, PDWORD); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/base64/memory.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include "memory.h" 31 | 32 | // allocate memory 33 | LPVOID xmalloc(DWORD dwSize) 34 | { 35 | return HeapAlloc(GetProcessHeap(), 36 | HEAP_ZERO_MEMORY, dwSize); 37 | } 38 | 39 | // re-allocate memory 40 | LPVOID xrealloc(LPVOID lpMem, DWORD dwSize) 41 | { 42 | return HeapReAlloc(GetProcessHeap(), 43 | HEAP_ZERO_MEMORY, lpMem, dwSize); 44 | } 45 | 46 | // free memory 47 | void xfree(LPVOID lpMem) 48 | { 49 | HeapFree(GetProcessHeap(), 0, lpMem); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/base64/memory.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #ifndef MEMORY_H 31 | #define MEMORY_H 32 | 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | LPVOID xmalloc(DWORD); 40 | LPVOID xrealloc(LPVOID, DWORD); 41 | void xfree(LPVOID); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/base64/test.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "encode.h" 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | void *b64, *bin; 13 | int len; 14 | 15 | if (argc != 2) { 16 | printf("\nusage: test \n"); 17 | return 0; 18 | } 19 | 20 | b64 = bintob64(argv[1], strlen(argv[1]), CRYPT_STRING_NOCR); 21 | printf("\n%s", b64); 22 | bin = b64tobin(b64, strlen(b64), 0, &len); 23 | xfree(b64); 24 | xfree(bin); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/dsa_gen/dsagen.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2016 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #if !defined(__GNUC__) 39 | #pragma comment(lib, "crypt32.lib") 40 | #pragma comment(lib, "advapi32.lib") 41 | #pragma comment(lib, "shlwapi.lib") 42 | #pragma comment(lib, "user32.lib") 43 | #endif 44 | 45 | #define DSA_KEY_LEN 1024 // this is the maximum key length on windows 7 46 | 47 | #define DSA_PUBLIC_BIN "dsa_public.bin" 48 | #define DSA_PUBLIC_H "dsa_public.h" 49 | 50 | #define DSA_PRIVATE_BIN "dsa_private.bin" 51 | #define DSA_PRIVATE_H "dsa_private.h" 52 | 53 | #define DSA_C_ARRAY 0 54 | #define DSA_BINARY 1 55 | #define DSA_SIGN 2 56 | #define DSA_VERIFY 3 57 | 58 | FILE *fd = NULL; 59 | HCRYPTPROV hProv = 0; // crypto API provider 60 | HCRYPTKEY hKey = 0; // key object 61 | HCRYPTHASH hHash = 0; // hash object 62 | 63 | BYTE *pbBlob = NULL; 64 | DWORD dwBlob = 0; 65 | 66 | BYTE *pbSignature = NULL; 67 | DWORD dwSigLen = 0; 68 | 69 | DWORD keylen = DSA_KEY_LEN; 70 | 71 | char *input = NULL, *signature = NULL; 72 | 73 | // allocate memory 74 | void *xmalloc(SIZE_T dwSize) 75 | { 76 | return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 77 | } 78 | 79 | // free memory 80 | void xfree(void *mem) 81 | { 82 | HeapFree(GetProcessHeap(), 0, mem); 83 | } 84 | 85 | // display extended windows error 86 | void xstrerror(char *fmt, ...) 87 | { 88 | char *error = NULL; 89 | va_list arglist; 90 | char buffer[2048]; 91 | DWORD dwError = GetLastError(); 92 | va_start(arglist, fmt); 93 | wvnsprintf(buffer, sizeof(buffer) - 1, fmt, arglist); 94 | va_end(arglist); 95 | 96 | if (FormatMessage( 97 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 98 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 99 | (LPSTR)&error, 0, NULL)) { 100 | printf(" [ %s : %s\n", buffer, error); 101 | LocalFree(error); 102 | } else { 103 | printf(" [ %s : %i\n", buffer, dwError); 104 | } 105 | } 106 | 107 | // initialize crypto provider 108 | BOOL open_crypt(void) 109 | { 110 | BOOL bStatus = FALSE; 111 | bStatus = CryptAcquireContext(&hProv, NULL, NULL, 112 | PROV_DSS, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); 113 | return bStatus; 114 | } 115 | 116 | void close_crypt(void) 117 | { 118 | // release provider 119 | if (hProv != 0) { 120 | CryptReleaseContext(hProv, 0); 121 | hProv = 0; 122 | } 123 | } 124 | 125 | // open key file 126 | BOOL open_key(char *key_file) 127 | { 128 | BOOL bStatus = FALSE; 129 | HANDLE hFile; 130 | DWORD dwRead; 131 | // open private key 132 | hFile = CreateFile(key_file, GENERIC_READ, 133 | FILE_SHARE_READ, NULL, OPEN_EXISTING, 134 | FILE_ATTRIBUTE_NORMAL, NULL); 135 | 136 | if (hFile != INVALID_HANDLE_VALUE) { 137 | dwBlob = GetFileSize(hFile, NULL); 138 | 139 | if (dwBlob != 0 && (pbBlob = (PBYTE)xmalloc(dwBlob)) != NULL) { 140 | // read key 141 | ReadFile(hFile, pbBlob, dwBlob, &dwRead, NULL); 142 | printf(" [ read %i bytes from %s\n", dwBlob, key_file); 143 | // import key into object 144 | bStatus = CryptImportKey(hProv, pbBlob, dwBlob, 0, 0, &hKey); 145 | } else { 146 | xstrerror("HeapAlloc()"); 147 | } 148 | 149 | // close key file 150 | CloseHandle(hFile); 151 | } else { 152 | xstrerror("CreateFile(%s)", key_file); 153 | } 154 | 155 | return bStatus; 156 | } 157 | 158 | void close_key(void) 159 | { 160 | if (pbBlob != NULL) { 161 | xfree(pbBlob); 162 | pbBlob = NULL; 163 | } 164 | 165 | if (fd != NULL) { 166 | fclose(fd); 167 | fd = NULL; 168 | } 169 | } 170 | 171 | // generates SHA-1 hash of input 172 | BOOL open_hash(void) 173 | { 174 | BOOL bStatus = FALSE; 175 | 176 | // create hash object 177 | if (CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash)) { 178 | // hash input 179 | bStatus = CryptHashData(hHash, input, lstrlen(input), 0); 180 | } 181 | 182 | return bStatus; 183 | } 184 | 185 | // destroy hash object 186 | void close_hash(void) 187 | { 188 | if (hHash != 0) { 189 | CryptDestroyHash(hHash); 190 | hHash = 0; 191 | } 192 | } 193 | 194 | // print binary as c array 195 | void bin2c(char s[]) 196 | { 197 | int i; 198 | fprintf(fd, "\nchar %s_KEY[]=\n{", s); 199 | 200 | for (i = 0; i < dwBlob; i++) { 201 | if ((i & 7) == 0 && i != 0) fprintf(fd, "\n"); 202 | 203 | if (i != 0) fprintf(fd, " "); 204 | 205 | fprintf(fd, "0x%02x", pbBlob[i]); 206 | 207 | if ((i + 1) != dwBlob) fprintf(fd, ","); 208 | } 209 | 210 | fprintf(fd, "};"); 211 | } 212 | 213 | // export key as C array string 214 | void export_key(DWORD dwType, char out[], int fmt) 215 | { 216 | DWORD dwWritten, i; 217 | char *type = (dwType == PUBLICKEYBLOB) ? "PUBLIC" : "PRIVATE"; 218 | fd = fopen(out, "wb"); 219 | 220 | if (fd != NULL) { 221 | // obtain lengtth of key blob 222 | if (CryptExportKey(hKey, 0, dwType, 0, NULL, &dwBlob)) { 223 | // allocate memory 224 | if (pbBlob = (PBYTE)xmalloc(dwBlob)) { 225 | // get blob 226 | if (CryptExportKey(hKey, 0, dwType, 0, pbBlob, &dwBlob)) { 227 | printf(" [ writing %i bytes to %s\n", dwBlob, out); 228 | 229 | switch (fmt) { 230 | case DSA_C_ARRAY: 231 | bin2c(type); 232 | break; 233 | 234 | case DSA_BINARY: 235 | fwrite(pbBlob, 1, dwBlob, fd); 236 | break; 237 | } 238 | } 239 | 240 | xfree(pbBlob); 241 | pbBlob = NULL; 242 | } 243 | } else { 244 | xstrerror("CryptExportKey()"); 245 | } 246 | 247 | fclose(fd); 248 | } else { 249 | xstrerror("fopen(%s)", out); 250 | } 251 | } 252 | 253 | // generate public/private key pair for digital signatures 254 | void genkeys(void) 255 | { 256 | if (open_crypt()) { 257 | if (CryptGenKey(hProv, AT_SIGNATURE, 258 | keylen << 16 | CRYPT_EXPORTABLE, &hKey)) { 259 | // export as C array and binary 260 | export_key(PUBLICKEYBLOB, DSA_PUBLIC_H, DSA_C_ARRAY); 261 | export_key(PUBLICKEYBLOB, DSA_PUBLIC_BIN, DSA_BINARY); 262 | export_key(PRIVATEKEYBLOB, DSA_PRIVATE_H, DSA_C_ARRAY); 263 | export_key(PRIVATEKEYBLOB, DSA_PRIVATE_BIN, DSA_BINARY); 264 | close_key(); 265 | } else { 266 | xstrerror("CryptGenKey(%i)", keylen); 267 | } 268 | 269 | close_crypt(); 270 | } else { 271 | xstrerror("CryptAcquireContext()"); 272 | } 273 | } 274 | 275 | // convert binary signature to hex string 276 | // pointer should be freed after use 277 | PBYTE sig2hex(void) 278 | { 279 | DWORD len = 0; 280 | PBYTE hex; 281 | // determine how much space we need 282 | CryptBinaryToString(pbSignature, dwSigLen, 283 | CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, NULL, &len); 284 | // allocate memory 285 | hex = xmalloc(len); 286 | // get the string 287 | CryptBinaryToString(pbSignature, dwSigLen, 288 | CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, hex, &len); 289 | // return it (ensure pointer is freed after being used) 290 | return hex; 291 | } 292 | 293 | // convert signature to binary 294 | // ensure to free pbSignature after use 295 | void sig2bin(void) 296 | { 297 | DWORD slen = lstrlen(signature); 298 | // determine how much space we need 299 | CryptStringToBinary(signature, slen, 300 | CRYPT_STRING_HEX_ANY, NULL, &dwSigLen, NULL, NULL); 301 | // allocate memory 302 | pbSignature = xmalloc(dwSigLen); 303 | // get the binary 304 | CryptStringToBinary(signature, slen, 305 | CRYPT_STRING_HEX_ANY, pbSignature, &dwSigLen, NULL, NULL); 306 | } 307 | 308 | // sign a hash of input using private key 309 | void sign(void) 310 | { 311 | // initialize crypto API 312 | if (open_crypt()) { 313 | // import our private key 314 | if (open_key(DSA_PRIVATE_BIN)) { 315 | // hash the input 316 | if (open_hash()) { 317 | // obtain size of signature 318 | CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen); 319 | pbSignature = xmalloc(dwSigLen); 320 | 321 | // sign the hash to obtain signature 322 | if (CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)) { 323 | if (sig2hex()) { 324 | printf(" [ signature is: %s\n", sig2hex()); 325 | } 326 | 327 | xfree(pbSignature); 328 | } else { 329 | xstrerror("CryptSignHash()"); 330 | } 331 | 332 | close_hash(); 333 | } else { 334 | xstrerror("open_hash()"); 335 | } 336 | 337 | close_key(); 338 | } else { 339 | xstrerror("open_key()"); 340 | } 341 | 342 | close_crypt(); 343 | } else { 344 | xstrerror("open_crypt()"); 345 | } 346 | } 347 | 348 | // verify a signature using public key 349 | BOOL verify(void) 350 | { 351 | BOOL bStatus = FALSE; 352 | 353 | // initialize crypto API 354 | if (open_crypt()) { 355 | // import public key 356 | if (open_key(DSA_PUBLIC_BIN)) { 357 | // hash the input 358 | if (open_hash()) { 359 | // convert signature to binary 360 | sig2bin(); 361 | 362 | if (pbSignature != NULL) { 363 | // verify signature 364 | bStatus = CryptVerifySignature(hHash, pbSignature, 365 | dwSigLen, hKey, NULL, 0); 366 | printf(" [ signature is %s\n", 367 | bStatus ? "valid" : "invalid"); 368 | xfree(pbSignature); 369 | } 370 | 371 | close_hash(); 372 | } else { 373 | printf("open_hash()"); 374 | } 375 | 376 | close_key(); 377 | } else { 378 | printf("open_key()"); 379 | } 380 | 381 | close_crypt(); 382 | } else { 383 | printf("open_crypt()"); 384 | } 385 | 386 | return bStatus; 387 | } 388 | 389 | char* getparam(int argc, char *argv[], int *i) 390 | { 391 | int n = *i; 392 | 393 | if (argv[n][2] != 0) { 394 | return &argv[n][2]; 395 | } 396 | 397 | if ((n + 1) < argc) { 398 | *i = n + 1; 399 | return argv[n + 1]; 400 | } 401 | 402 | printf(" [ %c%c requires parameter\n", argv[n][0], argv[n][1]); 403 | exit(0); 404 | } 405 | 406 | void usage(void) 407 | { 408 | printf(" [ usage: dsagen [options]\n"); 409 | printf(" -g Generate DSA key pair\n"); 410 | printf(" -k Key length in bits (default is %i)\n", DSA_KEY_LEN); 411 | printf(" -m Sign using private key\n"); 412 | printf(" -v Verify using public key, requires -m\n\n"); 413 | exit(0); 414 | } 415 | 416 | int main(int argc, char *argv[]) 417 | { 418 | int i, g = 0, s = 0, v = 0; 419 | char opt; 420 | printf("\n\n [ DSA key generation/signing/verifcation\n\n"); 421 | 422 | for (i = 1; i < argc; i++) { 423 | if (argv[i][0] == '-' || argv[i][0] == '/') { 424 | opt = argv[i][1]; 425 | 426 | switch (opt) { 427 | case 'g': // generate DSA key pair 428 | g = 1; 429 | break; 430 | 431 | case 'm': // sign a message using DSA (just for testing) 432 | input = getparam(argc, argv, &i); 433 | s = 1; 434 | break; 435 | 436 | case 'k': // key length (max is 1024-bits) 437 | keylen = atoi(getparam(argc, argv, &i)); 438 | break; 439 | 440 | case 'v': // verify DSA signature (just for testing) 441 | signature = getparam(argc, argv, &i); 442 | v = 1; 443 | break; 444 | 445 | default: 446 | usage(); 447 | break; 448 | } 449 | } 450 | } 451 | 452 | // generate keys? 453 | if (g) { 454 | printf(" [ generating DSA key pair of %i-bits\n", keylen); 455 | genkeys(); 456 | } else 457 | 458 | // generate signature of message using DSA private key? 459 | if (s == 1 && v == 0) { 460 | // have input? 461 | if (input == NULL) { 462 | printf(" [ signing requires a message, use -m option\n"); 463 | return 0; 464 | } 465 | 466 | printf(" [ signing message using DSA\n"); 467 | sign(); 468 | } else 469 | 470 | // verify signature using DSA public key? 471 | if (v) { 472 | // have input + signature? 473 | if (input == NULL || signature == NULL) { 474 | printf(" [ verification requires message and signature\n"); 475 | return 0; 476 | } 477 | 478 | printf(" [ verifying message and signature using DSA\n"); 479 | verify(); 480 | } else { 481 | usage(); 482 | } 483 | 484 | return 0; 485 | } 486 | -------------------------------------------------------------------------------- /src/rsa-sign-file/aes_rsa_sign.cpp: -------------------------------------------------------------------------------- 1 | #include "aes_rsa_sign.h" 2 | #include "crypto_api_aes.h" 3 | #include "crypto_api_rsa.h" 4 | #include "common.h" 5 | #include 6 | #include 7 | 8 | 9 | bool aes_encrypt_file_and_rsa_sign(const char* filename, const char* outfilename) 10 | { 11 | bool retval = false; 12 | std::vector inData; 13 | std::string out_filename = std::string(outfilename); 14 | 15 | do { 16 | char base64_key[] = "JUC/gPtu9fygSLbZaS/o1mxrfOGfRMkbZOOAsAaW9MU="; 17 | char base64_iv[] = "jJGbbzjndPzqgof8ou9MQA=="; 18 | 19 | if (!aes_encrypt_file(base64_key, base64_iv, filename, out_filename.c_str())) { 20 | break; 21 | } 22 | 23 | if (!sign_file2(out_filename)) { 24 | break; 25 | } 26 | 27 | retval = true; 28 | } while (0); 29 | 30 | return retval; 31 | } 32 | 33 | bool rsa_verify_file_and_aes_decrypt(const char* filename, std::string& out_string) 34 | { 35 | bool retval = false; 36 | std::vector key; 37 | std::vector iv; 38 | 39 | do { 40 | if (!verify_file2(filename)) { 41 | break; 42 | } 43 | 44 | std::vector inData; 45 | 46 | if (!get_enc_file_data(filename, inData)) { 47 | break; 48 | } 49 | 50 | char base64_key[] = "JUC/gPtu9fygSLbZaS/o1mxrfOGfRMkbZOOAsAaW9MU="; 51 | char base64_iv[] = "jJGbbzjndPzqgof8ou9MQA=="; 52 | 53 | if (!get_key_iv_from_base64(base64_key, base64_iv, key, iv)) { 54 | break; 55 | } 56 | 57 | DWORD inData_len = inData.size(); 58 | DWORD Decrypt_Len = aes_Decrypt(&key[0], key.size(), &iv[0], (LPBYTE)&inData[0], &inData_len); 59 | 60 | if (!Decrypt_Len) 61 | break; 62 | 63 | out_string = std::string((char*)&inData[0]); 64 | out_string.at(Decrypt_Len) = '\0'; 65 | out_string.resize(Decrypt_Len); 66 | retval = true; 67 | } while (0); 68 | 69 | return retval; 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/rsa-sign-file/aes_rsa_sign.h: -------------------------------------------------------------------------------- 1 | #ifndef __CACTUS_AES_RSA_SIGN_H__ 2 | #define __CACTUS_AES_RSA_SIGN_H__ 3 | 4 | #include 5 | #include 6 | 7 | bool aes_encrypt_file_and_rsa_sign(const char* filename, const char* outfilename); 8 | bool rsa_verify_file_and_aes_decrypt(const char* filename, std::string& out_string); 9 | 10 | 11 | #endif // __CACTUS_AES_RSA_SIGN_H__ 12 | -------------------------------------------------------------------------------- /src/rsa-sign-file/common.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // allocate memory 8 | void* xmalloc(SIZE_T dwSize) { 9 | return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 10 | } 11 | 12 | // free memory 13 | void xfree(void* mem) { 14 | HeapFree(GetProcessHeap(), 0, mem); 15 | } 16 | 17 | // print binary as c array 18 | void print_bin2c(BYTE* buffer, unsigned int buffer_len) { 19 | int i; 20 | 21 | for (i = 0; i < buffer_len; i++) { 22 | if ((i & 7) == 0 && i != 0) printf("\n"); 23 | 24 | if (i != 0) printf(" "); 25 | 26 | printf("0x%02x", buffer[i]); 27 | 28 | if ((i + 1) != buffer_len) printf(","); 29 | } 30 | } 31 | 32 | std::string HexEncode(const void* bytes, size_t size) { 33 | static const char kHexChars[] = "0123456789ABCDEF"; 34 | // Each input byte creates two output hex characters. 35 | std::string ret(size * 2, '\0'); 36 | 37 | for (size_t i = 0; i < size; ++i) { 38 | char b = reinterpret_cast(bytes)[i]; 39 | ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; 40 | ret[(i * 2) + 1] = kHexChars[b & 0xf]; 41 | } 42 | 43 | return ret; 44 | } 45 | 46 | BOOL get_file_contents(const char* filename, std::vector& out_buffer) { 47 | std::ifstream in(filename, std::ios::in | std::ios::binary); 48 | 49 | if (in) { 50 | in.seekg(0, std::ios::end); 51 | out_buffer.resize(in.tellg()); 52 | in.seekg(0, std::ios::beg); 53 | in.read((char*)&out_buffer[0], out_buffer.size()); 54 | in.close(); 55 | return TRUE; 56 | } 57 | 58 | return FALSE; 59 | } 60 | 61 | void put_file_content(const char* filename, const BYTE* data, DWORD data_len) { 62 | FILE* f = fopen(filename, "wb+"); 63 | fwrite(data, 1, data_len, f); 64 | fflush(f); 65 | fclose(f); 66 | } 67 | 68 | // display extended windows error 69 | void xstrerror(char* fmt, ...) { 70 | char* error = NULL; 71 | va_list arglist; 72 | char buffer[2048]; 73 | DWORD dwError = GetLastError(); 74 | va_start(arglist, fmt); 75 | wvnsprintf(buffer, sizeof(buffer) - 1, fmt, arglist); 76 | va_end(arglist); 77 | 78 | if (FormatMessage( 79 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 80 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 81 | (LPSTR)&error, 0, NULL)) { 82 | printf(" [ %s : %s\n", buffer, error); 83 | LocalFree(error); 84 | } else { 85 | printf(" [ %s : %i\n", buffer, dwError); 86 | } 87 | } 88 | 89 | 90 | DWORD GetCipherBlockSize(HCRYPTKEY key) { 91 | DWORD block_size_in_bits = 0; 92 | DWORD param_size = sizeof(block_size_in_bits); 93 | BOOL ok = CryptGetKeyParam(key, KP_BLOCKLEN, 94 | reinterpret_cast(&block_size_in_bits), 95 | ¶m_size, 0); 96 | 97 | if (!ok) 98 | return 0; 99 | 100 | return block_size_in_bits / 8; 101 | } 102 | 103 | 104 | bool Base64EncodeA(char** dest, unsigned long* dlen, const unsigned char* src, unsigned long slen) { 105 | if (src == NULL) 106 | return false; 107 | 108 | if (!CryptBinaryToStringA(src, slen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, dlen)) 109 | return false; 110 | 111 | //*dest = (char *)malloc(*dlen * sizeof(char)); 112 | *dest = (char*)xmalloc(*dlen * sizeof(char)); 113 | 114 | if (*dest == NULL) return false; 115 | 116 | SecureZeroMemory(*dest, *dlen * sizeof(char)); 117 | 118 | if (!CryptBinaryToStringA(src, slen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, *dest, dlen)) { 119 | //SAFE_FREE(*dest); 120 | xfree(*dest); 121 | return false; 122 | } 123 | 124 | return true; 125 | } 126 | 127 | 128 | bool Base64DecodeA(unsigned char** dest, unsigned long* dlen, const char* src, unsigned long slen) { 129 | if (src == NULL) 130 | return false; 131 | 132 | if (!CryptStringToBinaryA(src, slen, CRYPT_STRING_BASE64, NULL, dlen, NULL, NULL)) 133 | return false; 134 | 135 | //*dest = (unsigned char *)malloc((*dlen + 1) * sizeof(unsigned char)); 136 | *dest = (unsigned char*)xmalloc((*dlen + 1) * sizeof(unsigned char)); 137 | 138 | if (*dest == NULL) return false; 139 | 140 | SecureZeroMemory(*dest, (*dlen + 1) * sizeof(unsigned char)); 141 | 142 | if (!CryptStringToBinaryA(src, slen, CRYPT_STRING_BASE64, *dest, dlen, NULL, NULL)) { 143 | //SAFE_FREE(*dest); 144 | xfree(*dest); 145 | return false; 146 | } 147 | 148 | return true; 149 | } 150 | 151 | 152 | bool Bin2Hex(char** dest, unsigned long* dlen, const unsigned char* src, unsigned long slen) { 153 | if (src == NULL) 154 | return false; 155 | 156 | if (!CryptBinaryToString(src, slen, CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, NULL, dlen)) 157 | return false; 158 | 159 | *dest = (char*)xmalloc(*dlen * sizeof(char)); 160 | 161 | if (*dest == NULL) return false; 162 | 163 | SecureZeroMemory(*dest, *dlen * sizeof(char)); 164 | 165 | if (!CryptBinaryToStringA(src, slen, CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, *dest, dlen)) { 166 | //SAFE_FREE(*dest); 167 | xfree(*dest); 168 | return false; 169 | } 170 | 171 | return true; 172 | } 173 | 174 | 175 | bool Hex2Bin(unsigned char** dest, unsigned long* dlen, const char* src, unsigned long slen) { 176 | if (src == NULL) 177 | return false; 178 | 179 | if (!CryptStringToBinaryA(src, slen, CRYPT_STRING_HEXRAW, NULL, dlen, NULL, NULL)) 180 | return false; 181 | 182 | //*dest = (unsigned char *)malloc((*dlen + 1) * sizeof(unsigned char)); 183 | *dest = (unsigned char*)xmalloc((*dlen + 1) * sizeof(unsigned char)); 184 | 185 | if (*dest == NULL) return false; 186 | 187 | SecureZeroMemory(*dest, (*dlen + 1) * sizeof(unsigned char)); 188 | 189 | if (!CryptStringToBinaryA(src, slen, CRYPT_STRING_HEXRAW, *dest, dlen, NULL, NULL)) { 190 | //SAFE_FREE(*dest); 191 | xfree(*dest); 192 | return false; 193 | } 194 | 195 | return true; 196 | } 197 | 198 | 199 | 200 | bool get_key_iv_from_base64(const char* key_base64_str, const char* iv_base64_str, std::vector& key, std::vector& iv) { 201 | bool ret = false; 202 | LPBYTE dest_key = NULL; 203 | unsigned long dest_key_len; 204 | LPBYTE dest_iv = NULL; 205 | unsigned long dest_iv_len; 206 | 207 | do { 208 | if (!Base64DecodeA(&dest_key, &dest_key_len, key_base64_str, strlen(key_base64_str))) 209 | break; 210 | 211 | key.resize(dest_key_len); 212 | memcpy(&key[0], dest_key, dest_key_len); 213 | 214 | if (!Base64DecodeA(&dest_iv, &dest_iv_len, iv_base64_str, strlen(iv_base64_str))) 215 | break; 216 | 217 | iv.resize(dest_key_len); 218 | memcpy(&iv[0], dest_key, dest_key_len); 219 | ret = true; 220 | } while (0); 221 | 222 | if (dest_key) { 223 | xfree(dest_key); 224 | dest_key = NULL; 225 | } 226 | 227 | if (dest_iv) { 228 | xfree(dest_iv); 229 | dest_iv = NULL; 230 | } 231 | 232 | return ret; 233 | } 234 | 235 | bool get_key_iv_from_hex(const char* key_hex_str, const char* iv_hex_str, std::vector& key, std::vector& iv) { 236 | bool ret = false; 237 | LPBYTE dest_key = NULL; 238 | unsigned long dest_key_len; 239 | LPBYTE dest_iv = NULL; 240 | unsigned long dest_iv_len; 241 | 242 | do { 243 | if (!Hex2Bin(&dest_key, &dest_key_len, key_hex_str, strlen(key_hex_str))) 244 | break; 245 | 246 | key.resize(dest_key_len); 247 | memcpy(&key[0], dest_key, dest_key_len); 248 | 249 | if (!Hex2Bin(&dest_iv, &dest_iv_len, iv_hex_str, strlen(iv_hex_str))) 250 | break; 251 | 252 | iv.resize(dest_key_len); 253 | memcpy(&iv[0], dest_key, dest_key_len); 254 | ret = true; 255 | } while (0); 256 | 257 | if (dest_key) { 258 | xfree(dest_key); 259 | dest_key = NULL; 260 | } 261 | 262 | if (dest_iv) { 263 | xfree(dest_iv); 264 | dest_iv = NULL; 265 | } 266 | 267 | return ret; 268 | } 269 | 270 | char* Xor(char* szData, DWORD dwKey, int nLength) { 271 | if (szData == NULL) 272 | return NULL; 273 | 274 | for (int i = 0; i < nLength; i++) 275 | szData[i] = szData[i] ^ (char)dwKey; 276 | 277 | return szData; 278 | } 279 | 280 | void reverse(BYTE* data, int nLen) { 281 | for (int ii = 0; ii < nLen / 2; ii++) { 282 | BYTE c = data[ii]; 283 | data[ii] = data[nLen - ii - 1]; 284 | data[nLen - ii - 1] = c; 285 | } 286 | } 287 | 288 | PBYTE sig2hex(BYTE* pbSignature, DWORD dwSigLen) { 289 | DWORD len = 0; 290 | PBYTE hex; 291 | // determine how much space we need 292 | CryptBinaryToString(pbSignature, dwSigLen, 293 | CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, NULL, &len); 294 | // allocate memory 295 | hex = (BYTE*)xmalloc(len); 296 | // get the string 297 | CryptBinaryToString(pbSignature, dwSigLen, 298 | CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, (char*)hex, &len); 299 | // return it (ensure pointer is freed after being used) 300 | return hex; 301 | } 302 | 303 | void put_file_sign_content(const char* filename, const BYTE* data, DWORD data_len) { 304 | FILE* f = fopen(filename, "ab+"); 305 | fwrite(data, 1, data_len, f); 306 | fflush(f); 307 | fclose(f); 308 | } 309 | 310 | BOOL get_enc_file_data(const char* filename, std::vector& out_buffer) { 311 | std::ifstream in(filename, std::ios::in | std::ios::binary); 312 | 313 | if (in) { 314 | in.seekg(0, std::ios::end); 315 | size_t filesize = in.tellg(); 316 | in.seekg(0, std::ios::beg); 317 | 318 | if (filesize > 256) { 319 | out_buffer.resize(filesize - 256); 320 | in.read((char*)&out_buffer[0], out_buffer.size()); 321 | in.close(); 322 | return TRUE; 323 | } 324 | } 325 | 326 | return FALSE; 327 | } 328 | 329 | BOOL get_enc_file_sign_message(const char* filename, std::vector& out_buffer) { 330 | std::ifstream in(filename, std::ios::in | std::ios::binary); 331 | 332 | if (in) { 333 | in.seekg(0, std::ios::end); 334 | size_t filesize = in.tellg(); 335 | in.seekg(0, std::ios::beg); 336 | 337 | if (filesize > 256) { 338 | in.seekg(filesize - 256, std::ios::beg); 339 | out_buffer.resize(256); 340 | in.read((char*)&out_buffer[0], out_buffer.size()); 341 | in.close(); 342 | return TRUE; 343 | } 344 | } 345 | 346 | return FALSE; 347 | } 348 | 349 | BOOL OpenCryptContext(HCRYPTPROV* provider) { 350 | DWORD dwVersion = GetVersion(); 351 | DWORD dwMajor = (DWORD)(LOBYTE(LOWORD(dwVersion))); 352 | LPCTSTR pszProvider = MS_ENH_RSA_AES_PROV; 353 | 354 | if (dwMajor <= 5) 355 | pszProvider = MS_ENH_RSA_AES_PROV_XP; 356 | 357 | if (!CryptAcquireContext(provider, 0, pszProvider, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { 358 | if (!CryptAcquireContext(provider, 0, pszProvider, PROV_RSA_AES, CRYPT_NEWKEYSET)) { 359 | return FALSE; 360 | } 361 | } 362 | 363 | return TRUE; 364 | } 365 | 366 | typedef std::vector ByteVec; 367 | 368 | std::string toHex(const std::vector& byteVec) { 369 | std::ostringstream buf; 370 | for (ByteVec::const_iterator it = byteVec.begin(); it != byteVec.end(); it++) 371 | buf << std::setfill('0') << std::setw(2) << std::hex << 372 | (short)*it; 373 | return buf.str(); 374 | } 375 | 376 | 377 | bool getOneChar(ByteVec& hexStr, int& c) { 378 | if (hexStr.empty()) return false; 379 | int ch = hexStr.back(); 380 | hexStr.pop_back(); 381 | while (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') { 382 | if (hexStr.empty()) return false; 383 | ch = hexStr.back(); 384 | hexStr.pop_back(); 385 | } 386 | if (ch >= '0' && ch <= '9') 387 | c = ch - '0'; 388 | else if (ch >= 'A' && ch <= 'F') 389 | c = ch - 'A' + 10; 390 | else if (ch >= 'a' && ch <= 'f') 391 | c = ch - 'a' + 10; 392 | return true; 393 | } 394 | 395 | ByteVec fromHex(const std::string& hexStr) { 396 | ByteVec retVal, inpVal(hexStr.length(), '\0'); 397 | copy(hexStr.begin(), hexStr.end(), inpVal.begin()); 398 | reverse(inpVal.begin(), inpVal.end()); 399 | int c1, c2; 400 | while (getOneChar(inpVal, c1) && getOneChar(inpVal, c2)) { 401 | retVal.push_back((c1 << 4) | c2); 402 | } 403 | return retVal; 404 | } 405 | 406 | 407 | int win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{ */ 408 | 409 | unsigned int has_contextg = 0; 410 | 411 | BOOL ret; 412 | size_t i = 0; 413 | 414 | HCRYPTPROV hCryptProv; 415 | unsigned int has_crypto_ctx = 0; 416 | 417 | if (has_crypto_ctx == 0) { 418 | /* CRYPT_VERIFYCONTEXT > only hashing&co-like use, no need to acces prv keys */ 419 | if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT)) { 420 | /* Could mean that the key container does not exist, let try 421 | again by asking for a new one. If it fails here, it surely means that the user running 422 | this process does not have the permission(s) to use this container. 423 | */ 424 | if (GetLastError() == NTE_BAD_KEYSET) { 425 | if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT)) { 426 | has_crypto_ctx = 1; 427 | } 428 | else { 429 | has_crypto_ctx = 0; 430 | } 431 | } 432 | } 433 | else { 434 | has_crypto_ctx = 1; 435 | } 436 | } 437 | 438 | 439 | if (has_crypto_ctx == 0) { 440 | return FAILURE; 441 | } 442 | 443 | ret = CryptGenRandom(hCryptProv, size, buf); 444 | 445 | if (ret) { 446 | return SUCCESS; 447 | } 448 | else { 449 | return FAILURE; 450 | } 451 | } 452 | 453 | int usleep(unsigned int useconds) 454 | { 455 | HANDLE timer; 456 | LARGE_INTEGER due; 457 | 458 | due.QuadPart = -(10 * (__int64)useconds); 459 | 460 | timer = CreateWaitableTimer(NULL, TRUE, NULL); 461 | SetWaitableTimer(timer, &due, 0, NULL, NULL, 0); 462 | WaitForSingleObject(timer, INFINITE); 463 | CloseHandle(timer); 464 | return 0; 465 | } 466 | 467 | 468 | int utf16string_length(LPWSTR s) { 469 | int i = 0; 470 | 471 | while (s[i]) { 472 | i++; 473 | } 474 | return i; 475 | } 476 | 477 | LPSTR utf16string_convert(LPWSTR s) { 478 | LPSTR r; 479 | int i = 0; 480 | r = (LPSTR)malloc((utf16string_length(s) + 1)*sizeof(CHAR)); 481 | if (r != NULL){ 482 | while (s[i]) { 483 | r[i] = s[i]; 484 | i++; 485 | } 486 | r[i] = '\0'; 487 | } 488 | return r; 489 | } -------------------------------------------------------------------------------- /src/rsa-sign-file/common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/src/rsa-sign-file/common.h -------------------------------------------------------------------------------- /src/rsa-sign-file/crypto_api_aes.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/src/rsa-sign-file/crypto_api_aes.cpp -------------------------------------------------------------------------------- /src/rsa-sign-file/crypto_api_aes.h: -------------------------------------------------------------------------------- 1 | #ifndef __CACTUS_CRYPTO_API_AES_H__ 2 | #define __CACTUS_CRYPTO_API_AES_H__ 3 | 4 | #include 5 | #include 6 | 7 | 8 | class CryptAES 9 | { 10 | public: 11 | 12 | struct AESKEY128 { 13 | BLOBHEADER Header; 14 | DWORD dwKeyLen; 15 | BYTE pKey[16]; 16 | 17 | AESKEY128() 18 | { 19 | this->Header.bType = PLAINTEXTKEYBLOB; 20 | this->Header.bVersion = CUR_BLOB_VERSION; 21 | this->Header.reserved = 0; 22 | this->Header.aiKeyAlg = CALG_AES_128; 23 | this->dwKeyLen = 16; 24 | } 25 | }; 26 | 27 | CryptAES(BYTE *pKey, BYTE *pIV); 28 | ~CryptAES(); 29 | 30 | int Encrypt(BYTE *pData, DWORD *pdwDataSize, DWORD dwBufferSize, BOOL bFinal); 31 | int Decrypt(BYTE *pData, DWORD *pdwDataSize, BOOL bFinal); 32 | 33 | private: 34 | HCRYPTPROV hProv; 35 | HCRYPTKEY hKey; 36 | }; 37 | 38 | 39 | // From: 40 | // http://msdn.microsoft.com/en-us/library/windows/desktop/aa379931(v=vs.85).aspx 41 | typedef struct _plaintext_blob_t { 42 | BLOBHEADER hdr; 43 | DWORD cbKeySize; 44 | BYTE rgbKeyData[1]; 45 | } plaintext_blob_t; 46 | 47 | void gen_aes256_key_iv(); 48 | 49 | 50 | DWORD aes_Encrypt(LPBYTE key, DWORD SizeKey, LPBYTE iv, LPBYTE InData, DWORD SizeInData, LPBYTE *OutData); 51 | DWORD aes_Decrypt(LPBYTE key, DWORD SizeKey, LPBYTE iv, LPBYTE Data, LPDWORD SizeData); 52 | 53 | bool aes_encrypt_file(const char* base64_key, const char* base64_iv, const char* filename, const char* out_filename); 54 | bool aes_decrypt_file(const char* base64_key, const char* base64_iv, const char* filename, const char* out_filename); 55 | 56 | 57 | void aes_encrypt_test(); 58 | 59 | #endif // __CACTUS_CRYPTO_API_AES_H__ 60 | -------------------------------------------------------------------------------- /src/rsa-sign-file/crypto_api_certificate.h: -------------------------------------------------------------------------------- 1 | #ifndef __CACTUS_CRYPTO_API_CERTIFICATE_H__ 2 | #define __CACTUS_CRYPTO_API_CERTIFICATE_H__ 3 | 4 | 5 | 6 | 7 | 8 | #include 9 | #include 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #define OPENSIGN_ERROR_NONE 0 16 | #define OPENSIGN_ERROR_DIGEST_VALUE_UNAVAILABLE 1 17 | #define OPENSIGN_ERROR_DIGEST_SIZE_UNAVAILABLE 2 18 | #define OPENSIGN_ERROR_HHASH_DESTROY_FAILURE 3 19 | #define OPENSIGN_ERROR_HHASH_CREATE_FAILURE 4 20 | #define OPENSIGN_ERROR_HHASH_SIGNATURE_VALUE_UNAVAILABLE 11 21 | #define OPENSIGN_ERROR_HHASH_SIGNATURE_SIZE_UNAVAILABLE 13 22 | #define OPENSIGN_ERROR_HHASH_HASHDATA_FAILURE 15 23 | #define OPENSIGN_ERROR_HCRYPTPROV_RELEASE_FAILURE 5 24 | #define OPENSIGN_ERROR_HCRYPTPROV_ACQUIRE_FAILURE 6 25 | #define OPENSIGN_ERROR_CERTSTORE_OPEN_FAILURE 7 26 | #define OPENSIGN_ERROR_CERTSTORE_CERTIFICATE_NOT_FOUND 8 27 | #define OPENSIGN_ERROR_CERTSTORE_CLOSE_FAILURE 9 28 | #define OPENSIGN_ERROR_CCONTEXT_PROVINFO_VALUE_UNAVAILABLE 10 29 | #define OPENSIGN_ERROR_CCONTEXT_PROVINFO_SIZE_UNAVAILABLE 14 30 | #define OPENSIGN_ERROR_CERTGETNAMESTRING_SIZE_FAILURE 16 31 | #define OPENSIGN_ERROR_CERTGETNAMESTRING_VALUE_FAILURE 17 32 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE 29 33 | #define OPENSIGN_ERROR_KEYUSAGE_NOT_PRESENT 19 34 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_1 20 35 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_2 21 36 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_3 22 37 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_4 23 38 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_5 24 39 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_6 25 40 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_7 26 41 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_8 27 42 | #define OPENSIGN_ERROR_MEMORY_ALLOCATION_FAILURE_9 28 43 | 44 | extern int lastError; 45 | 46 | struct byte_array_t{ 47 | BYTE* data; 48 | long size; 49 | }; 50 | 51 | struct certificate_data { 52 | byte_array_t* pbCertEncoded; 53 | long count; 54 | certificate_data *prev; 55 | 56 | }; 57 | 58 | void freeCertificateList(struct certificate_data* head); 59 | 60 | struct certificate_data* getCertificatesInMyStore(); 61 | 62 | int digest(BYTE *to_be_hashed, 63 | DWORD to_be_hashed_length, 64 | BYTE **digest_value, 65 | DWORD *digest_value_length, 66 | ALG_ID alg_id); 67 | 68 | int sign(BYTE *certificate, 69 | DWORD certificate_length, 70 | BYTE *to_be_signed, 71 | DWORD to_be_signed_length, 72 | BYTE **signature, 73 | DWORD *signature_length, 74 | ALG_ID alg_id); 75 | 76 | int getCertificateDn(BYTE *certificate, 77 | DWORD certificate_length, 78 | DWORD issuerFlag, 79 | WCHAR **issuerDn, 80 | DWORD *dnLen); 81 | 82 | int getCertificateVersion(BYTE *certificate, 83 | DWORD certificate_length, 84 | DWORD *version); 85 | 86 | int getCertificateTimestamp(BYTE *certificate, 87 | DWORD certificate_length, 88 | BOOL notBefore, 89 | FILETIME *timestamp); 90 | 91 | int getCertificateSerialNumber(BYTE* certificate, 92 | DWORD certificate_length, 93 | CRYPT_INTEGER_BLOB *blSerialNumber); 94 | 95 | int getCertificateKeyUsage(BYTE *certificate, 96 | DWORD certificate_length, 97 | BYTE* keyusage); 98 | 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif 103 | #endif // __CACTUS_CRYPTO_API_CERTIFICATE_H__f 104 | -------------------------------------------------------------------------------- /src/rsa-sign-file/crypto_api_rsa.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wyrover/CryptoAPI-examples/9fab0763b15f550d9a4ab996a542e17950a7807b/src/rsa-sign-file/crypto_api_rsa.cpp -------------------------------------------------------------------------------- /src/rsa-sign-file/crypto_api_rsa.h: -------------------------------------------------------------------------------- 1 | #ifndef __CACTUS_CRYPTO_API_RSA_H__ 2 | #define __CACTUS_CRYPTO_API_RSA_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | //bool CryptoInit(HCRYPTKEY *key, HCRYPTPROV *provider, unsigned char **publicKey, unsigned char **privateKey); 10 | //bool Encrypt(HCRYPTKEY key, char **cipherText, unsigned long *cLen, unsigned char *plainText, unsigned long pLen); 11 | //bool Decrypt(HCRYPTKEY key, unsigned char **plainText, char *cipherText, unsigned long cLen); 12 | //void CryptoUninit(HCRYPTKEY key, HCRYPTPROV provider); 13 | 14 | #define RSA2048BIT_KEY 0x8000000 15 | void gen_rsa_keys(DWORD keylen); 16 | 17 | // sign a hash of input using private key 18 | BOOL sign_file2(std::string filename); 19 | 20 | BOOL verify_file2(std::string filename); 21 | 22 | DWORD rsa_Encrypt(LPBYTE PublicKey, DWORD SizeKey, LPBYTE InData, DWORD SizeInData, LPBYTE *OutData); 23 | DWORD rsa_Decrypt(LPBYTE PrivateKey, DWORD SizeKey, LPBYTE Data, LPDWORD SizeData); 24 | 25 | void rsa_encrypt_test(); 26 | void rsa_encrypt_test2(); 27 | 28 | class CryptoRSA 29 | { 30 | public: 31 | CryptoRSA(); 32 | ~CryptoRSA(); 33 | public: 34 | bool Init(); 35 | bool ImportPrivateKey(const char* pem_private_key); 36 | bool ImportPublicKey(const char* pem_public_key); 37 | 38 | DWORD Encrypt(LPBYTE InData, DWORD SizeInData, LPBYTE *OutData); 39 | DWORD Decrypt(LPBYTE Data, LPDWORD SizeData); 40 | protected: 41 | HCRYPTPROV provider_; 42 | HCRYPTKEY key_; 43 | 44 | }; 45 | 46 | 47 | 48 | #endif // __CACTUS_CRYPTO_API_RSA_H__ 49 | -------------------------------------------------------------------------------- /src/rsa_gen/dss.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2016 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #if !defined(__GNUC__) 39 | #pragma comment(lib, "crypt32.lib") 40 | #pragma comment(lib, "advapi32.lib") 41 | #pragma comment(lib, "shlwapi.lib") 42 | #pragma comment(lib, "user32.lib") 43 | #endif 44 | 45 | #define RSA_KEY_LEN 2048 46 | 47 | #define RSA_PUBLIC_BIN "rsa_public.bin" 48 | #define RSA_PUBLIC_H "rsa_public.h" 49 | 50 | #define RSA_PRIVATE_BIN "rsa_private.bin" 51 | #define RSA_PRIVATE_H "rsa_private.h" 52 | 53 | #define RSA_C_ARRAY 0 54 | #define RSA_BINARY 1 55 | #define RSA_SIGN 2 56 | #define RSA_VERIFY 3 57 | 58 | FILE *fd = NULL; 59 | HCRYPTPROV hProv = 0; // crypto API provider 60 | HCRYPTKEY hKey = 0; // key object 61 | HCRYPTHASH hHash = 0; // hash object 62 | 63 | BYTE *pbBlob = NULL; 64 | DWORD dwBlob = 0; 65 | 66 | BYTE *pbSignature = NULL; 67 | DWORD dwSigLen = 0; 68 | 69 | DWORD keylen = RSA_KEY_LEN; 70 | 71 | char *input = NULL, *signature = NULL; 72 | 73 | // allocate memory 74 | void *xmalloc(SIZE_T dwSize) 75 | { 76 | return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 77 | } 78 | 79 | // free memory 80 | void xfree(void *mem) 81 | { 82 | HeapFree(GetProcessHeap(), 0, mem); 83 | } 84 | 85 | // display extended windows error 86 | void xstrerror(char *fmt, ...) 87 | { 88 | char *error = NULL; 89 | va_list arglist; 90 | char buffer[2048]; 91 | DWORD dwError = GetLastError(); 92 | va_start(arglist, fmt); 93 | wvnsprintf(buffer, sizeof(buffer) - 1, fmt, arglist); 94 | va_end(arglist); 95 | 96 | if (FormatMessage( 97 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 98 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 99 | (LPSTR)&error, 0, NULL)) { 100 | printf(" [ %s : %s\n", buffer, error); 101 | LocalFree(error); 102 | } else { 103 | printf(" [ %s : %i\n", buffer, dwError); 104 | } 105 | } 106 | 107 | // initialize crypto provider 108 | BOOL open_crypt(void) 109 | { 110 | BOOL bStatus = FALSE; 111 | bStatus = CryptAcquireContext(&hProv, NULL, NULL, 112 | PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); 113 | return bStatus; 114 | } 115 | 116 | void close_crypt(void) 117 | { 118 | // release provider 119 | if (hProv != 0) { 120 | CryptReleaseContext(hProv, 0); 121 | hProv = 0; 122 | } 123 | } 124 | 125 | // open key file 126 | BOOL open_key(char *key_file) 127 | { 128 | BOOL bStatus = FALSE; 129 | HANDLE hFile; 130 | DWORD dwRead; 131 | // open private key 132 | hFile = CreateFile(key_file, GENERIC_READ, 133 | FILE_SHARE_READ, NULL, OPEN_EXISTING, 134 | FILE_ATTRIBUTE_NORMAL, NULL); 135 | 136 | if (hFile != INVALID_HANDLE_VALUE) { 137 | dwBlob = GetFileSize(hFile, NULL); 138 | 139 | if (dwBlob != 0 && (pbBlob = (PBYTE)xmalloc(dwBlob)) != NULL) { 140 | // read key 141 | ReadFile(hFile, pbBlob, dwBlob, &dwRead, NULL); 142 | printf(" [ read %i bytes from %s\n", dwBlob, key_file); 143 | // import key into object 144 | bStatus = CryptImportKey(hProv, pbBlob, dwBlob, 0, 0, &hKey); 145 | } else { 146 | xstrerror("HeapAlloc()"); 147 | } 148 | 149 | // close key file 150 | CloseHandle(hFile); 151 | } else { 152 | xstrerror("CreateFile(%s)", key_file); 153 | } 154 | 155 | return bStatus; 156 | } 157 | 158 | void close_key(void) 159 | { 160 | if (pbBlob != NULL) { 161 | xfree(pbBlob); 162 | pbBlob = NULL; 163 | } 164 | 165 | if (fd != NULL) { 166 | fclose(fd); 167 | fd = NULL; 168 | } 169 | } 170 | 171 | // generates SHA-256 hash of input 172 | BOOL open_hash(void) 173 | { 174 | BOOL bStatus = FALSE; 175 | 176 | // create hash object 177 | if (CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { 178 | // hash input 179 | bStatus = CryptHashData(hHash, input, lstrlen(input), 0); 180 | } 181 | 182 | return bStatus; 183 | } 184 | 185 | // destroy hash object 186 | void close_hash(void) 187 | { 188 | if (hHash != 0) { 189 | CryptDestroyHash(hHash); 190 | hHash = 0; 191 | } 192 | } 193 | 194 | // print binary as c array 195 | void bin2c(char s[]) 196 | { 197 | int i; 198 | fprintf(fd, "\nchar %s[]=\n{", s); 199 | 200 | for (i = 0; i < dwBlob; i++) { 201 | if ((i & 7) == 0 && i != 0) fprintf(fd, "\n"); 202 | 203 | if (i != 0) fprintf(fd, " "); 204 | 205 | fprintf(fd, "0x%02x", pbBlob[i]); 206 | 207 | if ((i + 1) != dwBlob) fprintf(fd, ","); 208 | } 209 | 210 | fprintf(fd, "};"); 211 | } 212 | 213 | // export key as C array string 214 | void export_key(DWORD dwType, char out[], int fmt) 215 | { 216 | DWORD dwWritten, i; 217 | char *type = (dwType == PUBLICKEYBLOB) ? "sign_public" : "sign_private"; 218 | fd = fopen(out, "wb"); 219 | 220 | if (fd != NULL) { 221 | // obtain lengtth of key blob 222 | if (CryptExportKey(hKey, 0, dwType, 0, NULL, &dwBlob)) { 223 | // allocate memory 224 | if (pbBlob = (PBYTE)xmalloc(dwBlob)) { 225 | // get blob 226 | if (CryptExportKey(hKey, 0, dwType, 0, pbBlob, &dwBlob)) { 227 | printf(" [ writing %i bytes to %s\n", dwBlob, out); 228 | 229 | switch (fmt) { 230 | case RSA_C_ARRAY: 231 | bin2c(type); 232 | break; 233 | 234 | case RSA_BINARY: 235 | fwrite(pbBlob, 1, dwBlob, fd); 236 | break; 237 | } 238 | } 239 | 240 | xfree(pbBlob); 241 | pbBlob = NULL; 242 | } 243 | } else { 244 | xstrerror("CryptExportKey()"); 245 | } 246 | 247 | fclose(fd); 248 | } else { 249 | xstrerror("fopen(%s)", out); 250 | } 251 | } 252 | 253 | // generate public/private key pair for digital signatures 254 | void genkeys(void) 255 | { 256 | if (open_crypt()) { 257 | if (CryptGenKey(hProv, AT_SIGNATURE, 258 | keylen << 16 | CRYPT_EXPORTABLE, &hKey)) { 259 | // export as C array and binary 260 | export_key(PUBLICKEYBLOB, RSA_PUBLIC_H, RSA_C_ARRAY); 261 | export_key(PUBLICKEYBLOB, RSA_PUBLIC_BIN, RSA_BINARY); 262 | export_key(PRIVATEKEYBLOB, RSA_PRIVATE_H, RSA_C_ARRAY); 263 | export_key(PRIVATEKEYBLOB, RSA_PRIVATE_BIN, RSA_BINARY); 264 | close_key(); 265 | } else { 266 | xstrerror("CryptGenKey(%i)", keylen); 267 | } 268 | 269 | close_crypt(); 270 | } else { 271 | xstrerror("CryptAcquireContext()"); 272 | } 273 | } 274 | 275 | // convert binary signature to hex string 276 | // pointer should be freed after use 277 | PBYTE sig2hex(void) 278 | { 279 | DWORD len = 0; 280 | PBYTE hex; 281 | // determine how much space we need 282 | CryptBinaryToString(pbSignature, dwSigLen, 283 | CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, NULL, &len); 284 | // allocate memory 285 | hex = xmalloc(len); 286 | // get the string 287 | CryptBinaryToString(pbSignature, dwSigLen, 288 | CRYPT_STRING_HEXRAW | CRYPT_STRING_NOCRLF, hex, &len); 289 | // return it (ensure pointer is freed after being used) 290 | return hex; 291 | } 292 | 293 | // convert signature to binary 294 | // ensure to free pbSignature after use 295 | void sig2bin(void) 296 | { 297 | DWORD slen = lstrlen(signature); 298 | // determine how much space we need 299 | CryptStringToBinary(signature, slen, 300 | CRYPT_STRING_HEX_ANY, NULL, &dwSigLen, NULL, NULL); 301 | // allocate memory 302 | pbSignature = xmalloc(dwSigLen); 303 | // get the binary 304 | CryptStringToBinary(signature, slen, 305 | CRYPT_STRING_HEX_ANY, pbSignature, &dwSigLen, NULL, NULL); 306 | } 307 | 308 | // sign a hash of input using private key 309 | void sign(void) 310 | { 311 | char *p; 312 | 313 | // initialize crypto API 314 | if (open_crypt()) { 315 | // import our private key 316 | if (open_key(RSA_PRIVATE_BIN)) { 317 | // hash the input 318 | if (open_hash()) { 319 | // obtain size of signature 320 | CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen); 321 | pbSignature = xmalloc(dwSigLen); 322 | 323 | // sign the hash to obtain signature 324 | if (CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)) { 325 | p = sig2hex(); 326 | 327 | if (p) { 328 | printf(" [ signature is: %i::%s\n", lstrlen(p), p); 329 | } 330 | 331 | xfree(pbSignature); 332 | } else { 333 | xstrerror("CryptSignHash()"); 334 | } 335 | 336 | close_hash(); 337 | } else { 338 | xstrerror("open_hash()"); 339 | } 340 | 341 | close_key(); 342 | } else { 343 | xstrerror("open_key()"); 344 | } 345 | 346 | close_crypt(); 347 | } else { 348 | xstrerror("open_crypt()"); 349 | } 350 | } 351 | 352 | // verify a signature using public key 353 | BOOL verify(void) 354 | { 355 | BOOL bStatus = FALSE; 356 | 357 | // initialize crypto API 358 | if (open_crypt()) { 359 | // import public key 360 | if (open_key(RSA_PUBLIC_BIN)) { 361 | // hash the input 362 | if (open_hash()) { 363 | // convert signature to binary 364 | sig2bin(); 365 | 366 | if (pbSignature != NULL) { 367 | // verify signature 368 | bStatus = CryptVerifySignature(hHash, pbSignature, 369 | dwSigLen, hKey, NULL, 0); 370 | printf(" [ signature is %s\n", 371 | bStatus ? "valid" : "invalid"); 372 | xfree(pbSignature); 373 | } 374 | 375 | close_hash(); 376 | } else { 377 | printf("open_hash()"); 378 | } 379 | 380 | close_key(); 381 | } else { 382 | printf("open_key()"); 383 | } 384 | 385 | close_crypt(); 386 | } else { 387 | printf("open_crypt()"); 388 | } 389 | 390 | return bStatus; 391 | } 392 | 393 | char* getparam(int argc, char *argv[], int *i) 394 | { 395 | int n = *i; 396 | 397 | if (argv[n][2] != 0) { 398 | return &argv[n][2]; 399 | } 400 | 401 | if ((n + 1) < argc) { 402 | *i = n + 1; 403 | return argv[n + 1]; 404 | } 405 | 406 | printf(" [ %c%c requires parameter\n", argv[n][0], argv[n][1]); 407 | exit(0); 408 | } 409 | 410 | void usage(void) 411 | { 412 | printf(" [ usage: keygen [options]\n"); 413 | printf(" -g Generate RSA key pair for signing\n"); 414 | printf(" -k Key length in bits (default is %i)\n", RSA_KEY_LEN); 415 | printf(" -m Sign using private key\n"); 416 | printf(" -v Verify using public key, requires -m\n\n"); 417 | exit(0); 418 | } 419 | 420 | int main(int argc, char *argv[]) 421 | { 422 | int i, g = 0, s = 0, v = 0; 423 | char opt; 424 | printf("\n\n [ RSA key generation/signing/verifcation\n\n"); 425 | 426 | for (i = 1; i < argc; i++) { 427 | if (argv[i][0] == '-' || argv[i][0] == '/') { 428 | opt = argv[i][1]; 429 | 430 | switch (opt) { 431 | case 'g': // generate RSA key pair 432 | g = 1; 433 | break; 434 | 435 | case 'm': // sign a message using RSA (just for testing) 436 | input = getparam(argc, argv, &i); 437 | s = 1; 438 | break; 439 | 440 | case 'k': // key length (max is 1024-bits) 441 | keylen = atoi(getparam(argc, argv, &i)); 442 | break; 443 | 444 | case 'v': // verify RSA signature (just for testing) 445 | signature = getparam(argc, argv, &i); 446 | v = 1; 447 | break; 448 | 449 | default: 450 | usage(); 451 | break; 452 | } 453 | } 454 | } 455 | 456 | // generate keys? 457 | if (g) { 458 | printf(" [ generating RSA key pair of %i-bits\n", keylen); 459 | genkeys(); 460 | } else 461 | 462 | // generate signature of message using RSA private key? 463 | if (s == 1 && v == 0) { 464 | // have input? 465 | if (input == NULL) { 466 | printf(" [ signing requires a message, use -m option\n"); 467 | return 0; 468 | } 469 | 470 | printf(" [ signing message using RSA\n"); 471 | sign(); 472 | } else 473 | 474 | // verify signature using RSA public key? 475 | if (v) { 476 | // have input + signature? 477 | if (input == NULL || signature == NULL) { 478 | printf(" [ verification requires message and signature\n"); 479 | return 0; 480 | } 481 | 482 | printf(" [ verifying message and signature using RSA\n"); 483 | verify(); 484 | } else { 485 | usage(); 486 | } 487 | 488 | return 0; 489 | } 490 | -------------------------------------------------------------------------------- /src/rsa_key_decode/dh_decode.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2016 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #pragma comment(lib, "Shlwapi.lib") 38 | #pragma comment(lib, "advapi32.lib") 39 | #pragma comment(lib, "crypt32.lib") 40 | 41 | #define PUBLIC_KEY 0 42 | #define PRIVATE_KEY 1 43 | 44 | typedef struct _rsa_key_t { 45 | PUBLICKEYSTRUC hdr; 46 | RSAPUBKEY rsa; 47 | BYTE mod[1]; 48 | } RSA_KEY, *PRSA_KEY; 49 | 50 | // allocate memory 51 | LPVOID xmalloc(DWORD dwSize) 52 | { 53 | return HeapAlloc(GetProcessHeap(), 54 | HEAP_ZERO_MEMORY, dwSize); 55 | } 56 | 57 | // re-allocate memory 58 | LPVOID xrealloc(LPVOID lpMem, DWORD dwSize) 59 | { 60 | return HeapReAlloc(GetProcessHeap(), 61 | HEAP_ZERO_MEMORY, lpMem, dwSize); 62 | } 63 | 64 | // free memory 65 | void xfree(LPVOID lpMem) 66 | { 67 | HeapFree(GetProcessHeap(), 0, lpMem); 68 | } 69 | 70 | void hex_dump(void *in, int len) 71 | { 72 | DWORD outlen = 0; 73 | int ofs = 0; 74 | LPTSTR out; 75 | 76 | if (ofs == 0) printf("\n"); 77 | 78 | ofs += len; 79 | 80 | if (CryptBinaryToString( 81 | in, len, CRYPT_STRING_HEXASCIIADDR | CRYPT_STRING_NOCR, 82 | NULL, &outlen)) { 83 | out = xmalloc(outlen); 84 | 85 | if (out != NULL) { 86 | if (CryptBinaryToString( 87 | in, len, CRYPT_STRING_HEXASCIIADDR | CRYPT_STRING_NOCR, 88 | out, &outlen)) { 89 | printf("%s", out); 90 | } 91 | 92 | xfree(out); 93 | } 94 | } 95 | 96 | putchar('\n'); 97 | } 98 | 99 | void xstrerror(char *fmt, ...) 100 | { 101 | char *error = NULL; 102 | va_list arglist; 103 | char buffer[2048]; 104 | DWORD dwError = GetLastError(); 105 | va_start(arglist, fmt); 106 | wvnsprintf(buffer, sizeof(buffer) - 1, fmt, arglist); 107 | va_end(arglist); 108 | 109 | if (FormatMessage( 110 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 111 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 112 | (LPSTR)&error, 0, NULL)) { 113 | printf("\n [ %s : %s", buffer, error); 114 | LocalFree(error); 115 | } else { 116 | printf("\n [ %s : %i", buffer, dwError); 117 | } 118 | } 119 | 120 | // decodes a public or private key in PEM format 121 | LPVOID decode_private(char *file, PDWORD keyLen) 122 | { 123 | HANDLE in; 124 | PBYTE derData, baseData, pemData, keyData = NULL; 125 | DWORD read, derLen, baseLen, pemLen; 126 | // try open PEM file 127 | in = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, 128 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 129 | 130 | if (in != INVALID_HANDLE_VALUE) { 131 | // get size of PEM data 132 | pemLen = GetFileSize(in, NULL); 133 | 134 | if (pemLen != 0) { 135 | // allocate memory for base64 string 136 | pemData = xmalloc(pemLen); 137 | 138 | if (pemData != NULL) { 139 | // read contents 140 | ReadFile(in, pemData, pemLen, &read, NULL); 141 | hex_dump(pemData, pemLen); 142 | 143 | // calculate how much space required for DER format 144 | if (CryptStringToBinary(pemData, pemLen, 145 | CRYPT_STRING_BASE64HEADER, NULL, 146 | &derLen, NULL, NULL)) { 147 | derData = xmalloc(derLen); 148 | 149 | if (derData != NULL) { 150 | // decode PEM string 151 | if (CryptStringToBinary(pemData, pemLen, 152 | CRYPT_STRING_BASE64HEADER, derData, 153 | &derLen, NULL, NULL)) { 154 | hex_dump(derData, derLen); 155 | 156 | // calculate space for key 157 | if (CryptDecodeObjectEx( 158 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 159 | PKCS_RSA_PRIVATE_KEY, derData, derLen, 0, 160 | NULL, NULL, keyLen)) { 161 | keyData = (PBYTE)xmalloc(*keyLen); 162 | 163 | if (keyData != NULL) { 164 | // decode DER 165 | CryptDecodeObjectEx( 166 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 167 | PKCS_RSA_PRIVATE_KEY, derData, derLen, 0, 168 | NULL, keyData, keyLen); 169 | hex_dump(keyData, *keyLen); 170 | } 171 | } else xstrerror("CryptDecodeObjectEx"); 172 | } 173 | 174 | xfree(derData); 175 | } 176 | } else xstrerror("CryptStringToBinary"); 177 | 178 | xfree(pemData); 179 | } 180 | } 181 | 182 | CloseHandle(in); 183 | } else xstrerror("CreateFile"); 184 | 185 | return keyData; 186 | } 187 | 188 | // decodes a public or private key in PEM format 189 | LPVOID decode_public(char *file, PDWORD keyLen) 190 | { 191 | HANDLE in; 192 | PBYTE derData, baseData, pemData, keyData = NULL; 193 | DWORD read, derLen, baseLen, pemLen; 194 | // try open PEM file 195 | in = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, 196 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 197 | 198 | if (in != INVALID_HANDLE_VALUE) { 199 | // get size of PEM data 200 | pemLen = GetFileSize(in, NULL); 201 | 202 | if (pemLen != 0) { 203 | // allocate memory for base64 string 204 | pemData = xmalloc(pemLen); 205 | 206 | if (pemData != NULL) { 207 | // read contents 208 | ReadFile(in, pemData, pemLen, &read, NULL); 209 | hex_dump(pemData, pemLen); 210 | 211 | // calculate how much space required for DER format 212 | if (CryptStringToBinary(pemData, pemLen, 213 | CRYPT_STRING_BASE64HEADER, NULL, 214 | &derLen, NULL, NULL)) { 215 | derData = xmalloc(derLen); 216 | 217 | if (derData != NULL) { 218 | // decode PEM string 219 | if (CryptStringToBinary(pemData, pemLen, 220 | CRYPT_STRING_BASE64HEADER, derData, 221 | &derLen, NULL, NULL)) { 222 | hex_dump(derData, derLen); 223 | 224 | // calculate space for key 225 | if (CryptDecodeObjectEx( 226 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 227 | X509_PUBLIC_KEY_INFO, derData, derLen, 0, 228 | NULL, NULL, keyLen)) { 229 | keyData = (PBYTE)xmalloc(*keyLen); 230 | 231 | if (keyData != NULL) { 232 | // decode DER 233 | CryptDecodeObjectEx( 234 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 235 | X509_PUBLIC_KEY_INFO, derData, derLen, 0, 236 | NULL, keyData, keyLen); 237 | hex_dump(keyData, *keyLen); 238 | } 239 | } else xstrerror("CryptDecodeObjectEx"); 240 | } 241 | 242 | xfree(derData); 243 | } 244 | } else xstrerror("CryptStringToBinary"); 245 | 246 | xfree(pemData); 247 | } 248 | } 249 | 250 | CloseHandle(in); 251 | } else xstrerror("CreateFile"); 252 | 253 | return keyData; 254 | } 255 | 256 | int main(int argc, char *argv[]) 257 | { 258 | HCRYPTPROV prov; 259 | HCRYPTKEY key; 260 | DWORD keyLen; 261 | DWORD type = PUBLIC_KEY; 262 | LPVOID keyData = NULL; 263 | 264 | // X509_PUBLIC_KEY_INFO for public keys 265 | // PKCS_RSA_PRIVATE_KEY for private keys 266 | 267 | if (argc != 2) { 268 | printf("\ndecode \n"); 269 | return 0; 270 | } 271 | 272 | keyData = decode_public(argv[1], &keyLen); 273 | 274 | if (keyData == NULL) { 275 | type = PRIVATE_KEY; 276 | keyData = decode_private(argv[1], &keyLen); 277 | } 278 | 279 | if (keyData != NULL) { 280 | // acquire a crypto provider 281 | if (CryptAcquireContext(&prov, NULL, NULL, 282 | PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { 283 | if (type == PRIVATE_KEY) { 284 | if (CryptImportKey(prov, keyData, keyLen, 285 | 0, CRYPT_EXPORTABLE, &key)) { 286 | printf("Private Key imported"); 287 | // destroy key 288 | CryptDestroyKey(key); 289 | } else xstrerror("CryptImportKey"); 290 | } else { 291 | // import the key 292 | if (CryptImportPublicKeyInfo(prov, X509_ASN_ENCODING, 293 | (PCERT_PUBLIC_KEY_INFO)keyData, &key)) { 294 | printf("Public Key imported"); 295 | // destroy key 296 | CryptDestroyKey(key); 297 | } else xstrerror("CryptImportPublicKeyInfo"); 298 | } 299 | 300 | // free crypto provider 301 | CryptReleaseContext(prov, 0); 302 | } else xstrerror("CryptAcquireContext"); 303 | } 304 | 305 | return 0; 306 | } 307 | -------------------------------------------------------------------------------- /src/rsa_key_encode/dh_encode.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2016 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #pragma comment(lib, "shlwapi.lib") 38 | #pragma comment(lib, "advapi32.lib") 39 | #pragma comment(lib, "crypt32.lib") 40 | 41 | #define PUBLIC_KEY 0 42 | #define PRIVATE_KEY 1 43 | 44 | typedef struct _rsa_key_t { 45 | PUBLICKEYSTRUC hdr; 46 | RSAPUBKEY rsa; 47 | BYTE mod[1]; 48 | } RSA_KEY, *PRSA_KEY; 49 | 50 | // allocate memory 51 | LPVOID xmalloc(SIZE_T dwSize) 52 | { 53 | return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); 54 | } 55 | 56 | // re-allocate memory 57 | LPVOID xrealloc(LPVOID lpMem, SIZE_T dwSize) 58 | { 59 | return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lpMem, dwSize); 60 | } 61 | 62 | // free memory 63 | void xfree(LPVOID lpMem) 64 | { 65 | HeapFree(GetProcessHeap(), 0, lpMem); 66 | } 67 | 68 | void hex_dump(void *in, int len) 69 | { 70 | DWORD outlen = 0; 71 | int ofs = 0; 72 | LPTSTR out; 73 | 74 | if (ofs == 0) printf("\n"); 75 | 76 | ofs += len; 77 | 78 | if (CryptBinaryToString( 79 | in, len, CRYPT_STRING_HEXASCIIADDR | CRYPT_STRING_NOCR, 80 | NULL, &outlen)) { 81 | out = xmalloc(outlen); 82 | 83 | if (out != NULL) { 84 | if (CryptBinaryToString( 85 | in, len, CRYPT_STRING_HEXASCIIADDR | CRYPT_STRING_NOCR, 86 | out, &outlen)) { 87 | printf("%s", out); 88 | } 89 | 90 | xfree(out); 91 | } 92 | } 93 | 94 | putchar('\n'); 95 | } 96 | 97 | void xstrerror(char *fmt, ...) 98 | { 99 | char *error = NULL; 100 | va_list arglist; 101 | char buffer[2048]; 102 | DWORD dwError = GetLastError(); 103 | va_start(arglist, fmt); 104 | wvnsprintf(buffer, sizeof(buffer) - 1, fmt, arglist); 105 | va_end(arglist); 106 | 107 | if (FormatMessage( 108 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 109 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 110 | (LPSTR)&error, 0, NULL)) { 111 | printf("\n [ %s : %s", buffer, error); 112 | LocalFree(error); 113 | } else { 114 | printf("\n [ %s : %i", buffer, dwError); 115 | } 116 | } 117 | 118 | // The key size, in bits. 119 | #define DHKEYSIZE 512 120 | 121 | // Prime in little-endian format. 122 | static const BYTE g_rgbPrime[] = { 123 | 0x91, 0x02, 0xc8, 0x31, 0xee, 0x36, 0x07, 0xec, 124 | 0xc2, 0x24, 0x37, 0xf8, 0xfb, 0x3d, 0x69, 0x49, 125 | 0xac, 0x7a, 0xab, 0x32, 0xac, 0xad, 0xe9, 0xc2, 126 | 0xaf, 0x0e, 0x21, 0xb7, 0xc5, 0x2f, 0x76, 0xd0, 127 | 0xe5, 0x82, 0x78, 0x0d, 128 | 129 | 0x4f, 0x32, 0xb8, 0xcb, 130 | 0xf7, 0x0c, 0x8d, 0xfb, 0x3a, 0xd8, 0xc0, 0xea, 131 | 0xcb, 0x69, 0x68, 0xb0, 0x9b, 0x75, 0x25, 0x3d, 132 | 0xaa, 0x76, 0x22, 0x49, 0x94, 0xa4, 0xf2, 0x8d 133 | }; 134 | 135 | // Generator in little-endian format. 136 | static BYTE g_rgbGenerator[] = { 137 | 0x02, 0x88, 0xd7, 0xe6, 0x53, 0xaf, 0x72, 0xc5, 138 | 0x8c, 0x08, 0x4b, 0x46, 0x6f, 0x9f, 0x2e, 0xc4, 139 | 0x9c, 0x5c, 0x92, 0x21, 0x95, 0xb7, 0xe5, 0x58, 140 | 0xbf, 0xba, 0x24, 0xfa, 0xe5, 0x9d, 0xcb, 0x71, 141 | 0x2e, 0x2c, 0xce, 0x99, 0xf3, 0x10, 0xff, 0x3b, 142 | 0xcb, 0xef, 0x6c, 0x95, 0x22, 0x55, 0x9d, 0x29, 143 | 0x00, 0xb5, 0x4c, 0x5b, 0xa5, 0x63, 0x31, 0x41, 144 | 0x13, 0x0a, 0xea, 0x39, 0x78, 0x02, 0x6d, 0x62 145 | }; 146 | 147 | char public_start[] = "-----BEGIN DH PARAMETERS-----\n"; 148 | char public_end[] = "-----END DH PARAMETERS-----\n"; 149 | 150 | typedef struct _KEY_FORMAT_T { 151 | BLOBHEADER blobheader; 152 | DHPUBKEY_VER3 keylen; 153 | BYTE p[DHKEYSIZE / 8]; // Where P is the prime modulus 154 | BYTE q[DHKEYSIZE / 8]; // Where Q is a large factor of P-1 155 | BYTE g[DHKEYSIZE / 8]; // Where G is the generator parameter 156 | BYTE j[DHKEYSIZE / 8]; // Where J is (P-1)/Q 157 | BYTE y[DHKEYSIZE / 8]; // Where Y is (G^X) mod P 158 | } DH_PARAMS, *PDH_PARAMS; 159 | 160 | void encode_public(HCRYPTKEY key) 161 | { 162 | FILE *out; 163 | PBYTE pem, pemData, derData; 164 | PBYTE keyInfo; 165 | DWORD encodeLen, keyLen, derLen, pemLen; 166 | PDH_PARAMS params; 167 | 168 | // get length of encoding 169 | if (CryptExportKey(key, 0, PUBLICKEYBLOB, CRYPT_BLOB_VER3, NULL, &keyLen)) { 170 | // allocate memory for encoding 171 | keyInfo = xmalloc(keyLen); 172 | 173 | // export public key 174 | if (CryptExportKey(key, 0, PUBLICKEYBLOB, CRYPT_BLOB_VER3, keyInfo, &keyLen)) { 175 | hex_dump(keyInfo, keyLen); 176 | 177 | // convert to DER format 178 | if (CryptEncodeObjectEx( 179 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 180 | RSA_CSP_PUBLICKEYBLOB, keyInfo, 0, 181 | NULL, NULL, &derLen)) { 182 | derData = (PBYTE)xmalloc(derLen); 183 | 184 | if (CryptEncodeObjectEx( 185 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 186 | RSA_CSP_PUBLICKEYBLOB, keyInfo, 0, 187 | NULL, derData, &derLen)) { 188 | hex_dump(derData, derLen); 189 | CryptBinaryToString(derData, derLen, 190 | CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR, 191 | NULL, &pemLen); 192 | pemData = (PBYTE)xmalloc(pemLen); 193 | CryptBinaryToString(derData, derLen, 194 | CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR, 195 | pemData, &pemLen); 196 | hex_dump(pemData, pemLen); 197 | out = fopen("dhpx.pem", "wb"); 198 | 199 | if (out != NULL) { 200 | fwrite(public_start, sizeof(public_start) - 1, 1, out); 201 | fwrite(pemData, pemLen, 1, out); 202 | fwrite(public_end, sizeof(public_end) - 1, 1, out); 203 | fclose(out); 204 | } 205 | } 206 | } else xstrerror("CryptEncodeObjectEx"); 207 | } 208 | } else xstrerror("CryptExportPublicKeyInfo"); 209 | } 210 | 211 | int main(void) 212 | { 213 | HCRYPTPROV prov; 214 | HCRYPTKEY key; 215 | DWORD keyLen, encodeLen, pemLen; 216 | PRSA_KEY rsaKey; 217 | DATA_BLOB P; 218 | DATA_BLOB G; 219 | P.cbData = DHKEYSIZE / 8; 220 | P.pbData = (BYTE*)(g_rgbPrime); 221 | G.cbData = DHKEYSIZE / 8; 222 | G.pbData = (BYTE*)(g_rgbGenerator); 223 | 224 | // acquire a crypto provider 225 | if (CryptAcquireContext(&prov, NULL, NULL, 226 | PROV_DSS_DH, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { 227 | // generate RSA key 228 | if (CryptGenKey(prov, CALG_DH_EPHEM, 229 | DHKEYSIZE << 16 | CRYPT_EXPORTABLE | CRYPT_PREGEN, &key)) { 230 | // Set the prime for party 1's private key. 231 | CryptSetKeyParam( 232 | key, 233 | KP_P, 234 | (PBYTE)&P, 0); 235 | xstrerror("CryptSetKeyParam"); 236 | // Set the generator for party 1's private key. 237 | CryptSetKeyParam( 238 | key, 239 | KP_G, 240 | (PBYTE)&G, 0); 241 | xstrerror("CryptSetKeyParam"); 242 | encode_public(key); 243 | // destroy key 244 | CryptDestroyKey(key); 245 | } 246 | 247 | // free crypto provider 248 | CryptReleaseContext(prov, 0); 249 | } 250 | 251 | return 0; 252 | } 253 | -------------------------------------------------------------------------------- /src/rsa_tool/encode.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include "encode.h" 31 | 32 | /** 33 | * 34 | * convert string to binary 35 | * 36 | */ 37 | LPVOID str2bin( 38 | const char *in, 39 | DWORD inLen, 40 | DWORD flags, 41 | PDWORD outLen) 42 | { 43 | LPVOID out = NULL; 44 | 45 | // calculate how much space required 46 | if (CryptStringToBinary(in, inLen, 47 | flags, NULL, outLen, NULL, NULL)) { 48 | out = xmalloc(*outLen); 49 | 50 | if (out != NULL) { 51 | // decode base64 52 | CryptStringToBinary(in, inLen, 53 | flags, out, outLen, NULL, NULL); 54 | } 55 | } 56 | 57 | return out; 58 | } 59 | 60 | /** 61 | * 62 | * convert binary to string 63 | * 64 | */ 65 | const char* bin2str(LPVOID in, DWORD inLen, DWORD flags) 66 | { 67 | DWORD outLen; 68 | LPVOID out = NULL; 69 | 70 | // calculate space for string 71 | if (CryptBinaryToString(in, inLen, 72 | flags, NULL, &outLen)) { 73 | out = xmalloc(outLen); 74 | 75 | // convert it 76 | if (out != NULL) { 77 | CryptBinaryToString(in, inLen, 78 | flags, out, &outLen); 79 | } 80 | } 81 | 82 | return out; 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/rsa_tool/encode.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #ifndef ENCODE_H 31 | #define ENCODE_H 32 | 33 | #include 34 | #include 35 | 36 | #include "memory.h" 37 | 38 | #ifdef _MSC_VER 39 | #pragma comment(lib, "crypt32.lib") 40 | #endif 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | const char* bin2str(LPVOID, DWORD, DWORD); 47 | LPVOID str2bin(const char*, DWORD, DWORD, PDWORD); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/rsa_tool/memory.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include "memory.h" 31 | 32 | // allocate memory 33 | LPVOID xmalloc(DWORD dwSize) 34 | { 35 | return HeapAlloc(GetProcessHeap(), 36 | HEAP_ZERO_MEMORY, dwSize); 37 | } 38 | 39 | // re-allocate memory 40 | LPVOID xrealloc(LPVOID lpMem, DWORD dwSize) 41 | { 42 | return HeapReAlloc(GetProcessHeap(), 43 | HEAP_ZERO_MEMORY, lpMem, dwSize); 44 | } 45 | 46 | // free memory 47 | void xfree(LPVOID lpMem) 48 | { 49 | HeapFree(GetProcessHeap(), 0, lpMem); 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/rsa_tool/memory.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #ifndef MEMORY_H 31 | #define MEMORY_H 32 | 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | LPVOID xmalloc(DWORD); 40 | LPVOID xrealloc(LPVOID, DWORD); 41 | void xfree(LPVOID); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/rsa_tool/rsa.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include "rsa.h" 31 | 32 | /** 33 | * 34 | * open CSP and return pointer to RSA object 35 | * 36 | */ 37 | RSA* rsa_open(void) 38 | { 39 | HCRYPTPROV prov = 0; 40 | RSA *rsa = NULL; 41 | 42 | if (CryptAcquireContext(&prov, 43 | NULL, NULL, PROV_RSA_AES, 44 | CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { 45 | rsa = xmalloc(sizeof(RSA)); 46 | 47 | if (rsa != NULL) { 48 | rsa->prov = prov; 49 | } 50 | } 51 | 52 | return rsa; 53 | } 54 | 55 | /** 56 | * 57 | * close CSP and release memory for RSA object 58 | * 59 | */ 60 | void rsa_close(RSA *rsa) 61 | { 62 | if (rsa == NULL) return; 63 | 64 | if (rsa->hash != 0) { 65 | CryptDestroyHash(rsa->hash); 66 | rsa->hash = 0; 67 | } 68 | 69 | // release private key 70 | if (rsa->privkey != 0) { 71 | CryptDestroyKey(rsa->privkey); 72 | rsa->privkey = 0; 73 | } 74 | 75 | // release public key 76 | if (rsa->pubkey != 0) { 77 | CryptDestroyKey(rsa->pubkey); 78 | rsa->pubkey = 0; 79 | } 80 | 81 | // release csp 82 | if (rsa->prov != 0) { 83 | CryptReleaseContext(rsa->prov, 0); 84 | rsa->prov = 0; 85 | } 86 | 87 | // release object 88 | xfree(rsa); 89 | } 90 | 91 | /** 92 | * 93 | * generate new key pair of keyLen-bits 94 | * 95 | */ 96 | int rsa_genkey(RSA* rsa, int keyLen) 97 | { 98 | BOOL ok = FALSE; 99 | 100 | if (rsa == NULL) return 0; 101 | 102 | // release public 103 | if (rsa->pubkey != 0) { 104 | CryptDestroyKey(rsa->pubkey); 105 | rsa->pubkey = 0; 106 | } 107 | 108 | // release private 109 | if (rsa->privkey != 0) { 110 | CryptDestroyKey(rsa->privkey); 111 | rsa->privkey = 0; 112 | } 113 | 114 | // generate key pair for signing 115 | ok = CryptGenKey(rsa->prov, AT_KEYEXCHANGE, 116 | (keyLen << 16) | CRYPT_EXPORTABLE, 117 | &rsa->privkey); 118 | return ok; 119 | } 120 | 121 | /** 122 | * 123 | * write binary to file encoded in PEM format 124 | * 125 | * ifile : name of file to write PEM encoded key 126 | * pemType : type of key being saved 127 | * rsa : RSA object with public and private keys 128 | * 129 | */ 130 | int rsa_write_pem(int pemType, 131 | LPVOID data, DWORD dataLen, const char* ofile) 132 | { 133 | const char *s = NULL, *e = NULL, *b64; 134 | FILE *out; 135 | BOOL ok = FALSE; 136 | 137 | if (pemType == RSA_PRIVATE_KEY) { 138 | s = "-----BEGIN PRIVATE KEY-----\n"; 139 | e = "-----END PRIVATE KEY-----\n"; 140 | } else if (pemType == RSA_PUBLIC_KEY) { 141 | s = "-----BEGIN PUBLIC KEY-----\n"; 142 | e = "-----END PUBLIC KEY-----\n"; 143 | } else if (pemType == RSA_SIGNATURE) { 144 | s = "-----BEGIN RSA SIGNATURE-----\n"; 145 | e = "-----END RSA SIGNATURE-----\n"; 146 | } 147 | 148 | b64 = bin2str(data, dataLen, 149 | CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR); 150 | 151 | if (b64 != NULL) { 152 | out = fopen(ofile, "wb"); 153 | 154 | if (out != NULL) { 155 | fwrite(s, strlen(s), 1, out); 156 | fwrite(b64, strlen(b64), 1, out); 157 | fwrite(e, strlen(e), 1, out); 158 | fclose(out); 159 | ok = TRUE; 160 | } 161 | } 162 | 163 | return ok; 164 | } 165 | 166 | /** 167 | * 168 | * read public or private key in PEM format 169 | * 170 | * ifile : name of file to write PEM encoded key 171 | * pemType : type of key being saved 172 | * rsa : RSA object with public and private keys 173 | * 174 | */ 175 | LPVOID rsa_read_pem(const char* ifile, PDWORD binLen) 176 | { 177 | FILE *in; 178 | struct stat st; 179 | LPVOID pem = NULL, bin = NULL; 180 | stat(ifile, &st); 181 | 182 | if (st.st_size == 0) return NULL; 183 | 184 | // open PEM file 185 | in = fopen(ifile, "rb"); 186 | 187 | if (in != NULL) { 188 | // allocate memory for data 189 | pem = xmalloc(st.st_size + 1); 190 | 191 | if (pem != NULL) { 192 | // read data 193 | fread(pem, sizeof(char), st.st_size, in); 194 | bin = str2bin(pem, strlen(pem), 195 | CRYPT_STRING_BASE64HEADER, binLen); 196 | xfree(pem); 197 | } 198 | 199 | fclose(in); 200 | } 201 | 202 | return bin; 203 | } 204 | 205 | /** 206 | * 207 | * save public or private key to PEM format 208 | * 209 | * ifile : name of file to write PEM encoded key 210 | * pemType : type of key being saved 211 | * rsa : RSA object with public and private keys 212 | * 213 | */ 214 | int rsa_read_key(RSA* rsa, 215 | const char* ifile, int pemType) 216 | { 217 | LPVOID derData, keyData; 218 | PCRYPT_PRIVATE_KEY_INFO pki = 0; 219 | DWORD pkiLen, derLen, keyLen; 220 | BOOL ok = FALSE; 221 | // decode base64 string ignoring headers 222 | derData = rsa_read_pem(ifile, &derLen); 223 | 224 | if (derData != NULL) { 225 | // decode DER 226 | // is it a public key? 227 | if (pemType == RSA_PUBLIC_KEY) { 228 | if (CryptDecodeObjectEx( 229 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 230 | X509_PUBLIC_KEY_INFO, derData, derLen, 231 | CRYPT_DECODE_ALLOC_FLAG, NULL, 232 | &keyData, &keyLen)) { 233 | // if decode ok, import it 234 | ok = CryptImportPublicKeyInfo(rsa->prov, X509_ASN_ENCODING, 235 | (PCERT_PUBLIC_KEY_INFO)keyData, &rsa->pubkey); 236 | // release allocated memory 237 | LocalFree(keyData); 238 | } 239 | } else { 240 | // convert the PKCS#8 data to private key info 241 | if (CryptDecodeObjectEx( 242 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 243 | PKCS_PRIVATE_KEY_INFO, derData, derLen, 244 | CRYPT_DECODE_ALLOC_FLAG, 245 | NULL, &pki, &pkiLen)) { 246 | // then convert the private key to private key blob 247 | if (CryptDecodeObjectEx( 248 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 249 | PKCS_RSA_PRIVATE_KEY, 250 | pki->PrivateKey.pbData, 251 | pki->PrivateKey.cbData, 252 | CRYPT_DECODE_ALLOC_FLAG, NULL, 253 | &keyData, &keyLen)) { 254 | // if decode ok, import it 255 | ok = CryptImportKey(rsa->prov, keyData, keyLen, 256 | 0, CRYPT_EXPORTABLE, &rsa->privkey); 257 | // release data 258 | LocalFree(keyData); 259 | } 260 | 261 | // release private key info 262 | LocalFree(pki); 263 | } 264 | } 265 | 266 | xfree(derData); 267 | } 268 | 269 | return ok; 270 | } 271 | 272 | /** 273 | * 274 | * save public or private key to PEM format 275 | * 276 | * ofile : name of file to write PEM encoded key 277 | * pemType : type of key being saved 278 | * rsa : RSA object with public and private keys 279 | * 280 | */ 281 | int rsa_write_key(RSA* rsa, 282 | const char* ofile, int pemType) 283 | { 284 | DWORD pkiLen, derLen; 285 | LPVOID pki, derData; 286 | BOOL ok = FALSE; 287 | 288 | // public key? 289 | if (pemType == RSA_PUBLIC_KEY) { 290 | // get size of public key info 291 | if (CryptExportPublicKeyInfo(rsa->prov, AT_KEYEXCHANGE, 292 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 293 | NULL, &pkiLen)) { 294 | // allocate memory 295 | pki = xmalloc(pkiLen); 296 | 297 | // export public key info 298 | if (CryptExportPublicKeyInfo(rsa->prov, AT_KEYEXCHANGE, 299 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 300 | pki, &pkiLen)) { 301 | // get size of DER encoding 302 | if (CryptEncodeObjectEx( 303 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 304 | X509_PUBLIC_KEY_INFO, pki, 0, 305 | NULL, NULL, &derLen)) { 306 | derData = xmalloc(derLen); 307 | // convert to DER format 308 | ok = CryptEncodeObjectEx( 309 | X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 310 | X509_PUBLIC_KEY_INFO, pki, 0, 311 | NULL, derData, &derLen); 312 | 313 | // write to PEM file 314 | if (ok) { 315 | rsa_write_pem(RSA_PUBLIC_KEY, derData, derLen, ofile); 316 | xfree(derData); 317 | } 318 | } 319 | } 320 | } 321 | } else { 322 | // get length of PKCS#8 encoding 323 | if (CryptExportPKCS8(rsa->prov, AT_KEYEXCHANGE, 324 | szOID_RSA_RSA, 0, NULL, NULL, &pkiLen)) { 325 | pki = xmalloc(pkiLen); 326 | 327 | if (pki != NULL) { 328 | // export the private key 329 | ok = CryptExportPKCS8(rsa->prov, AT_KEYEXCHANGE, 330 | szOID_RSA_RSA, 0x8000, NULL, 331 | pki, &pkiLen); 332 | 333 | // write key to PEM file 334 | if (ok) { 335 | rsa_write_pem(RSA_PRIVATE_KEY, pki, pkiLen, ofile); 336 | } 337 | 338 | xfree(pki); 339 | } 340 | } 341 | } 342 | 343 | return ok; 344 | } 345 | 346 | /** 347 | * 348 | * calculate sha256 hash of file 349 | * 350 | * ifile : contains data to generate hash for 351 | * rsa : RSA object with HCRYPTHASH object 352 | * 353 | */ 354 | int rsa_hash(RSA* rsa, const char* ifile) 355 | { 356 | LPBYTE data, p; 357 | ULONGLONG len; 358 | HANDLE hFile, hMap; 359 | DWORD r; 360 | BOOL ok = FALSE; 361 | 362 | // destroy hash object if already created 363 | if (rsa->hash != 0) { 364 | CryptDestroyHash(rsa->hash); 365 | rsa->hash = 0; 366 | } 367 | 368 | // try open the file for reading 369 | hFile = CreateFile(ifile, GENERIC_READ, 370 | FILE_SHARE_READ, NULL, OPEN_EXISTING, 371 | FILE_ATTRIBUTE_NORMAL, NULL); 372 | 373 | if (hFile != INVALID_HANDLE_VALUE) { 374 | // make sure we have something to hash 375 | GetFileSizeEx(hFile, (PLARGE_INTEGER)&len); 376 | 377 | if (len != 0) { 378 | // create a file mapping handle 379 | hMap = CreateFileMapping(hFile, NULL, 380 | PAGE_READONLY, 0, 0, NULL); 381 | 382 | if (hMap != NULL) { 383 | // map a view of the file 384 | data = (LPBYTE)MapViewOfFile(hMap, 385 | FILE_MAP_READ, 0, 0, 0); 386 | 387 | if (data != NULL) { 388 | // create SHA-256 hash object 389 | if (CryptCreateHash(rsa->prov, 390 | CALG_SHA_256, 0, 0, &rsa->hash)) { 391 | p = data; 392 | 393 | // while data available 394 | while (len) { 395 | r = (len < 8192) ? len : 8192; 396 | // absorb 8192 bytes or whatever remains 397 | ok = CryptHashData(rsa->hash, p, r, 0); 398 | 399 | if (!ok) break; 400 | 401 | len -= r; // update length 402 | p += r; // update position in file 403 | } 404 | } 405 | 406 | UnmapViewOfFile((LPCVOID)data); 407 | } 408 | 409 | CloseHandle(hMap); 410 | } 411 | } 412 | 413 | CloseHandle(hFile); 414 | } 415 | 416 | return ok; 417 | } 418 | 419 | /** 420 | * 421 | * create a signature for file 422 | * 423 | * sfile : where to write PEM encoded signature 424 | * ifile : contains data to generate signature for 425 | * rsa : RSA object with private key 426 | * 427 | */ 428 | int rsa_sign(RSA* rsa, 429 | const char* ifile, const char* sfile) 430 | { 431 | DWORD sigLen = 0; 432 | LPVOID sig; 433 | BOOL ok = FALSE; 434 | 435 | // calculate sha256 hash for file 436 | if (rsa_hash(rsa, ifile)) { 437 | // acquire length of signature 438 | if (CryptSignHash(rsa->hash, 439 | AT_KEYEXCHANGE, NULL, 0, 440 | NULL, &sigLen)) { 441 | sig = xmalloc(sigLen); 442 | 443 | if (sig != NULL) { 444 | // obtain signature 445 | if (CryptSignHash(rsa->hash, 446 | AT_KEYEXCHANGE, NULL, 0, 447 | sig, &sigLen)) { 448 | // convert 2 PEM format + write 2 file 449 | ok = rsa_write_pem(RSA_SIGNATURE, 450 | sig, sigLen, sfile); 451 | } 452 | 453 | xfree(sig); 454 | } 455 | } 456 | } 457 | 458 | return ok; 459 | } 460 | 461 | /** 462 | * 463 | * verify a signature using public key 464 | * 465 | * sfile : file with signature encoded in PEM format 466 | * ifile : file with data to verify signature for 467 | * rsa : RSA object with public key 468 | * 469 | */ 470 | int rsa_verify( 471 | RSA* rsa, 472 | const char* ifile, 473 | const char* sfile) 474 | { 475 | DWORD sigLen; 476 | LPVOID sig; 477 | BOOL ok = FALSE; 478 | // convert PEM data to binary 479 | sig = rsa_read_pem(sfile, &sigLen); 480 | 481 | if (sig != NULL) { 482 | // calculate sha256 hash of file 483 | if (rsa_hash(rsa, ifile)) { 484 | // verify signature using public key 485 | ok = CryptVerifySignature(rsa->hash, sig, 486 | sigLen, rsa->pubkey, NULL, 0); 487 | } 488 | } 489 | 490 | return ok; 491 | } 492 | -------------------------------------------------------------------------------- /src/rsa_tool/rsa.h: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #ifndef RSA_H 31 | #define RSA_H 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "encode.h" 40 | 41 | #ifdef _MSC_VER 42 | #pragma comment (lib, "advapi32.lib") 43 | #endif 44 | 45 | #define RSA_PUBLIC_KEY 1 46 | #define RSA_PRIVATE_KEY 2 47 | #define RSA_SIGNATURE 3 48 | 49 | typedef struct _RSA_t { 50 | HCRYPTPROV prov; 51 | HCRYPTKEY privkey, pubkey; 52 | HCRYPTHASH hash; 53 | DWORD error; 54 | } RSA; 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | RSA* rsa_open(void); 61 | void rsa_close(RSA*); 62 | 63 | int rsa_genkey(RSA*, int); 64 | 65 | int rsa_write_pem(int, LPVOID, DWORD, const char*); 66 | LPVOID rsa_read_pem(const char*, PDWORD); 67 | 68 | int rsa_read_key(RSA*, const char*, int); 69 | int rsa_write_key(RSA*, const char*, int); 70 | 71 | int rsa_verify(RSA*, const char*, const char*); 72 | int rsa_sign(RSA*, const char*, const char*); 73 | int rsa_hash(RSA*, const char*); 74 | 75 | #ifdef __cplusplus 76 | } 77 | #endif 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/rsa_tool/rsa_tool.c: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (C) 2017 Odzhan. All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. The name of the author may not be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY AUTHORS "AS IS" AND ANY EXPRESS OR 19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | POSSIBILITY OF SUCH DAMAGE. */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #ifdef _MSC_VER 37 | #pragma comment(lib, "shlwapi.lib") 38 | #endif 39 | 40 | #include "rsa.h" 41 | 42 | void xstrerror(char *fmt, ...) 43 | { 44 | char *error = NULL; 45 | va_list arglist; 46 | char buffer[2048]; 47 | DWORD dwError = GetLastError(); 48 | va_start(arglist, fmt); 49 | wvnsprintf(buffer, sizeof(buffer) - 1, fmt, arglist); 50 | va_end(arglist); 51 | 52 | if (FormatMessage( 53 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 54 | NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 55 | (LPSTR)&error, 0, NULL)) { 56 | printf("\n [ %s : %s", buffer, error); 57 | LocalFree(error); 58 | } else { 59 | printf("\n [ %s : %ld", buffer, dwError); 60 | } 61 | } 62 | 63 | /** 64 | * 65 | * verify a signature using public key 66 | * 67 | */ 68 | int verify( 69 | const char *pubkey, 70 | const char *file, 71 | const char *signature) 72 | { 73 | int ok = 0; 74 | RSA *rsa = rsa_open(); 75 | 76 | if (rsa != NULL) { 77 | printf("\n [ Reading public key from %s...", pubkey); 78 | 79 | if (rsa_read_key(rsa, pubkey, RSA_PUBLIC_KEY)) { 80 | printf("\n [ Reading signature for %s from %s...", 81 | file, signature); 82 | ok = rsa_verify(rsa, file, signature); 83 | } else xstrerror("rsa_read_key()"); 84 | 85 | rsa_close(rsa); 86 | } 87 | 88 | return ok; 89 | } 90 | 91 | /** 92 | * 93 | * sign a file using private key 94 | * 95 | */ 96 | int sign( 97 | const char *privkey, 98 | const char *file, 99 | const char *signature) 100 | { 101 | int ok = 0; 102 | RSA *rsa = rsa_open(); 103 | 104 | if (rsa != NULL) { 105 | printf("\n [ Reading private key from %s...", privkey); 106 | 107 | if (rsa_read_key(rsa, privkey, RSA_PRIVATE_KEY)) { 108 | printf("\n [ Writing signature for %s to %s...", 109 | file, signature); 110 | ok = rsa_sign(rsa, file, signature); 111 | } else xstrerror("rsa_read_key()"); 112 | 113 | rsa_close(rsa); 114 | } 115 | 116 | return ok; 117 | } 118 | 119 | /** 120 | * 121 | * generate RSA key pair 122 | * 123 | */ 124 | int genkey( 125 | const char *pubkey, 126 | const char *privkey, 127 | int bits) 128 | { 129 | int ok = 1; 130 | RSA *rsa; 131 | rsa = rsa_open(); 132 | 133 | if (rsa != NULL) { 134 | if (rsa_genkey(rsa, bits)) { 135 | printf("\n [ Saving public key to %s...", pubkey); 136 | 137 | if (rsa_write_key(rsa, pubkey, RSA_PUBLIC_KEY)) { 138 | printf("ok\n [ Saving private key to %s...", privkey); 139 | 140 | if (rsa_write_key(rsa, privkey, RSA_PRIVATE_KEY)) { 141 | printf("ok\n"); 142 | } else xstrerror("rsa_write_key()"); 143 | } else xstrerror("rsa_write_key()"); 144 | } else xstrerror("rsa_genkey()"); 145 | 146 | rsa_close(rsa); 147 | } 148 | 149 | return ok; 150 | } 151 | 152 | char* getparam(int argc, char *argv[], int *i) 153 | { 154 | int n = *i; 155 | 156 | if (argv[n][2] != 0) { 157 | return &argv[n][2]; 158 | } 159 | 160 | if ((n + 1) < argc) { 161 | *i = n + 1; 162 | return argv[n + 1]; 163 | } 164 | 165 | printf(" [ %c%c requires parameter\n", argv[n][0], argv[n][1]); 166 | exit(0); 167 | } 168 | 169 | void usage(void) 170 | { 171 | printf(" [ usage: rsa_tool [options] \n\n"); 172 | printf(" -g Generate RSA key pair of \n"); 173 | printf(" -s Using private key in \n"); 174 | printf(" -x Read signature from \n"); 175 | printf(" -v Using public key in \n\n"); 176 | exit(0); 177 | } 178 | 179 | int main(int argc, char *argv[]) 180 | { 181 | int i, g = 0, s = 0, v = 0, bitlen; 182 | char opt; 183 | char *priv = "private.pem", 184 | *pub = "public.pem", *sig = NULL, 185 | *file = NULL; 186 | puts("\n [ RSA Tool v0.1" 187 | "\n [ copyright (c) 2017 @odzhancode\n"); 188 | 189 | for (i = 1; i < argc; i++) { 190 | if (argv[i][0] == '-' || argv[i][0] == '/') { 191 | opt = argv[i][1]; 192 | 193 | switch (opt) { 194 | case 'g': // generate RSA key pair 195 | g = 1; 196 | bitlen = atoi(getparam(argc, argv, &i)); 197 | break; 198 | 199 | case 's': // private key 200 | priv = getparam(argc, argv, &i); 201 | s = 1; 202 | break; 203 | 204 | case 'x': // signature file 205 | sig = getparam(argc, argv, &i); 206 | break; 207 | 208 | case 'v': // verify RSA signature 209 | pub = getparam(argc, argv, &i); 210 | v = 1; 211 | break; 212 | 213 | default: 214 | usage(); 215 | break; 216 | } 217 | } else { 218 | file = argv[i]; 219 | } 220 | } 221 | 222 | // generate keys? 223 | if (g) { 224 | printf(" [ generating RSA key pair of %i-bits\n", bitlen); 225 | genkey(pub, priv, bitlen); 226 | } else 227 | 228 | // generate signature of message using RSA private key? 229 | if (s == 1 && v == 0) { 230 | // have file? 231 | if (file == NULL) { 232 | printf(" [ signing requires a file\n"); 233 | return 0; 234 | } 235 | 236 | printf("\n [ signing file using RSA : %s\n", 237 | sign(priv, file, sig) ? "OK" : "FAILED"); 238 | } else 239 | 240 | // verify signature using RSA public key? 241 | if (v) { 242 | // have input + signature? 243 | if (file == NULL || sig == NULL) { 244 | printf(" [ verification requires file and signature\n"); 245 | return 0; 246 | } 247 | 248 | printf("\n [ verifying signature using RSA : %s\n", 249 | verify(pub, file, sig) ? "OK" : "FAILED"); 250 | } else { 251 | usage(); 252 | } 253 | 254 | return 0; 255 | } -------------------------------------------------------------------------------- /src/rsacert/RSACert.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 3 | ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 4 | TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 5 | PARTICULAR PURPOSE. 6 | 7 | Copyright (C) 1996 - 2002. Microsoft Corporation. All rights reserved. 8 | */ 9 | /* 10 | #define UNICODE 11 | #define _UNICODE 12 | #define _WIN32_WINNT 0x0400 13 | */ 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include // for proper buffer handling 19 | 20 | const int IN_BUFFER_SIZE = 64 * 1024; 21 | // OUT_BUFFER_SIZE is 8 bytes larger than IN_BUFFER_SIZE 22 | // When CALG_RC2 algorithm is used, encrypted data 23 | // will be 8 bytes larger than IN_BUFFER_SIZE 24 | const int OUT_BUFFER_SIZE = IN_BUFFER_SIZE + 8; // extra padding 25 | 26 | #define MY_ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) 27 | 28 | void PrintUsage(); 29 | PCCERT_CONTEXT GetCertificateContextFromName( 30 | LPTSTR lpszCertificateName, 31 | LPTSTR lpszCertificateStoreName, 32 | DWORD dwCertStoreOpenFlags); 33 | 34 | BOOL AcquireAndGetRSAKey(PCCERT_CONTEXT pCertContext, 35 | DWORD dwCertStoreOpenFlags, 36 | HCRYPTPROV *phProv, 37 | HCRYPTKEY *phRSAKey, 38 | BOOL fEncrypt, 39 | BOOL *fCallerFreeProv); 40 | BOOL EncryptDecryptFile(LPTSTR lpszCertificateName, 41 | LPTSTR lpszCertificateStoreName, 42 | DWORD dwCertStoreOpenFlags, 43 | LPTSTR lpszInputFileName, 44 | LPTSTR lpszOutputFileName, 45 | BOOL fEncrypt); 46 | void __cdecl MyPrintf(LPCTSTR lpszFormat, ...); 47 | 48 | #define CheckAndLocalFree(ptr) \ 49 | if (ptr != NULL) \ 50 | { \ 51 | LocalFree(ptr); \ 52 | ptr = NULL; \ 53 | } 54 | 55 | void PrintUsage() 56 | { 57 | MyPrintf(_T("RSACert [|] [|] \n")); 58 | MyPrintf(_T("/e for Encryption\n")); 59 | MyPrintf(_T("/d for Decryption\n")); 60 | MyPrintf(_T("/u for current user certificate store\n")); 61 | MyPrintf(_T("/m for local machine certificate store\n")); 62 | } 63 | 64 | void __cdecl MyPrintf(LPCTSTR lpszFormat, ...) 65 | { 66 | TCHAR szOutput[2048]; 67 | va_list v1 = NULL; 68 | HRESULT hr = S_OK; 69 | va_start(v1, lpszFormat); 70 | hr = StringCbVPrintf(szOutput, sizeof(szOutput), lpszFormat, v1); 71 | 72 | if (SUCCEEDED(hr)) { 73 | OutputDebugString(szOutput); 74 | _tprintf(szOutput); 75 | } else { 76 | _tprintf(_T("StringCbVPrintf failed with %X\n"), hr); 77 | } 78 | } 79 | 80 | void _tmain(int argc, TCHAR **argv) 81 | { 82 | BOOL fEncrypt = FALSE; 83 | LPTSTR lpszCertificateName = NULL; 84 | LPTSTR lpszCertificateStoreName = NULL; 85 | LPTSTR lpszInputFileName = NULL; 86 | LPTSTR lpszOutputFileName = NULL; 87 | DWORD dwCertStoreOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER; 88 | 89 | if (argc != 7) { 90 | PrintUsage(); 91 | return; 92 | } 93 | 94 | /* Check whether the action to be performed is encrypt or decrypt */ 95 | if (_tcsicmp(argv[1], _T("/e")) == 0) { 96 | fEncrypt = TRUE; 97 | } else if (_tcsicmp(argv[1], _T("/d")) == 0) { 98 | fEncrypt = FALSE; 99 | } else { 100 | PrintUsage(); 101 | return; 102 | } 103 | 104 | lpszCertificateName = argv[2]; 105 | lpszCertificateStoreName = argv[3]; 106 | 107 | /* Check whether the certificate store to be opened is user or machine */ 108 | if (_tcsicmp(argv[4], _T("/u")) == 0) { 109 | dwCertStoreOpenFlags = CERT_SYSTEM_STORE_CURRENT_USER; 110 | } else if (_tcsicmp(argv[4], _T("/m")) == 0) { 111 | dwCertStoreOpenFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE; 112 | } else { 113 | PrintUsage(); 114 | return; 115 | } 116 | 117 | lpszInputFileName = argv[5]; 118 | lpszOutputFileName = argv[6]; 119 | EncryptDecryptFile(lpszCertificateName, 120 | lpszCertificateStoreName, 121 | dwCertStoreOpenFlags, 122 | lpszInputFileName, 123 | lpszOutputFileName, 124 | fEncrypt); 125 | } 126 | 127 | PCCERT_CONTEXT GetCertificateContextFromName( 128 | LPTSTR lpszCertificateName, 129 | LPTSTR lpszCertificateStoreName, 130 | DWORD dwCertStoreOpenFlags) 131 | { 132 | PCCERT_CONTEXT pCertContext = NULL; 133 | HCERTSTORE hCertStore = NULL; 134 | LPSTR szStoreProvider; 135 | DWORD dwFindType; 136 | #ifdef UNICODE 137 | szStoreProvider = (LPSTR)CERT_STORE_PROV_SYSTEM_W; 138 | #else 139 | szStoreProvider = (LPSTR)CERT_STORE_PROV_SYSTEM_A; 140 | #endif 141 | // Open the specified certificate store 142 | hCertStore = CertOpenStore(szStoreProvider, 143 | 0, 144 | NULL, 145 | CERT_STORE_READONLY_FLAG | 146 | dwCertStoreOpenFlags, 147 | lpszCertificateStoreName); 148 | 149 | if (hCertStore == NULL) { 150 | MyPrintf(_T("CertOpenStore failed with %X\n"), GetLastError()); 151 | return pCertContext; 152 | } 153 | 154 | #ifdef UNICODE 155 | dwFindType = CERT_FIND_SUBJECT_STR_W; 156 | #else 157 | dwFindType = CERT_FIND_SUBJECT_STR_A; 158 | #endif 159 | // Find the certificate by CN. 160 | pCertContext = CertFindCertificateInStore( 161 | hCertStore, 162 | MY_ENCODING, 163 | 0, 164 | dwFindType, 165 | lpszCertificateName, 166 | NULL); 167 | 168 | if (pCertContext == NULL) { 169 | MyPrintf(_T("CertFindCertificateInStore failed with %X\n"), GetLastError()); 170 | } 171 | 172 | CertCloseStore(hCertStore, 0); 173 | return pCertContext; 174 | } 175 | 176 | BOOL AcquireAndGetRSAKey(PCCERT_CONTEXT pCertContext, 177 | HCRYPTPROV *phProv, 178 | HCRYPTKEY *phRSAKey, 179 | BOOL fEncrypt, 180 | BOOL *pfCallerFreeProv) 181 | { 182 | BOOL fSuccess = FALSE; 183 | DWORD dwKeySpec = 0; 184 | 185 | __try { 186 | *phProv = NULL; 187 | *phRSAKey = NULL; 188 | *pfCallerFreeProv = FALSE; 189 | 190 | if (fEncrypt) { 191 | // Acquire context for RSA key 192 | fSuccess = CryptAcquireContext(phProv, 193 | NULL, 194 | MS_DEF_PROV, 195 | PROV_RSA_FULL, 196 | CRYPT_VERIFYCONTEXT); 197 | 198 | if (!fSuccess) { 199 | MyPrintf(_T("CryptAcquireContext failed with %X\n"), GetLastError()); 200 | __leave; 201 | } 202 | 203 | // Import the RSA public key from the certificate context 204 | fSuccess = CryptImportPublicKeyInfo(*phProv, 205 | MY_ENCODING, 206 | &(pCertContext->pCertInfo->SubjectPublicKeyInfo), 207 | phRSAKey); 208 | 209 | if (!fSuccess) { 210 | MyPrintf(_T("CryptImportPublicKeyInfo failed with %X\n"), GetLastError()); 211 | __leave; 212 | } 213 | 214 | *pfCallerFreeProv = TRUE; 215 | } else { 216 | // Acquire the RSA private key 217 | fSuccess = CryptAcquireCertificatePrivateKey(pCertContext, 218 | CRYPT_ACQUIRE_USE_PROV_INFO_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG, 219 | NULL, phProv, &dwKeySpec, pfCallerFreeProv); 220 | 221 | if (!fSuccess) { 222 | MyPrintf(_T("CryptAcquireCertificatePrivateKey failed with %X\n"), GetLastError()); 223 | __leave; 224 | } 225 | 226 | // Get the RSA key handle 227 | fSuccess = CryptGetUserKey(*phProv, dwKeySpec, phRSAKey); 228 | 229 | if (!fSuccess) { 230 | MyPrintf(_T("CryptGetUserKey failed with %X\n"), GetLastError()); 231 | __leave; 232 | } 233 | } 234 | } __finally { 235 | if (fSuccess == FALSE) { 236 | if (phProv && *phProv != NULL) { 237 | CryptReleaseContext(*phProv, 0); 238 | *phProv = NULL; 239 | } 240 | 241 | if (phRSAKey && *phRSAKey != NULL) { 242 | CryptDestroyKey(*phRSAKey); 243 | *phRSAKey = NULL; 244 | } 245 | } 246 | } 247 | 248 | return fSuccess; 249 | } 250 | 251 | BOOL EncryptDecryptFile(LPTSTR lpszCertificateName, 252 | LPTSTR lpszCertificateStoreName, 253 | DWORD dwCertStoreOpenFlags, 254 | LPTSTR lpszInputFileName, 255 | LPTSTR lpszOutputFileName, 256 | BOOL fEncrypt) 257 | { 258 | BOOL fResult = FALSE; 259 | HCRYPTPROV hProv = NULL; 260 | HCRYPTKEY hRSAKey = NULL; 261 | HCRYPTKEY hSessionKey = NULL; 262 | HANDLE hInFile = INVALID_HANDLE_VALUE; 263 | HANDLE hOutFile = INVALID_HANDLE_VALUE; 264 | BOOL finished = FALSE; 265 | BYTE pbBuffer[OUT_BUFFER_SIZE]; 266 | DWORD dwByteCount = 0; 267 | DWORD dwBytesRead = 0; 268 | DWORD dwBytesWritten = 0; 269 | LPBYTE pbSessionKeyBlob = NULL; 270 | DWORD dwSessionKeyBlob = 0; 271 | BOOL fCallerFreeProv = FALSE; 272 | PCCERT_CONTEXT pCertContext = NULL; 273 | BOOL fSuccess = FALSE; 274 | 275 | __try { 276 | pCertContext = GetCertificateContextFromName(lpszCertificateName, 277 | lpszCertificateStoreName, 278 | dwCertStoreOpenFlags); 279 | 280 | if (pCertContext == NULL) { 281 | __leave; 282 | } 283 | 284 | fResult = AcquireAndGetRSAKey(pCertContext, 285 | &hProv, 286 | &hRSAKey, 287 | fEncrypt, 288 | &fCallerFreeProv); 289 | 290 | if (fResult == FALSE) { 291 | __leave; 292 | } 293 | 294 | // Open the input file to be encrypted or decrypted 295 | hInFile = CreateFile(lpszInputFileName, 296 | GENERIC_READ, 297 | 0, 298 | NULL, 299 | OPEN_EXISTING, 300 | FILE_ATTRIBUTE_NORMAL, 301 | NULL); 302 | 303 | if (hInFile == INVALID_HANDLE_VALUE) { 304 | MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); 305 | __leave; 306 | } 307 | 308 | // Open the output file to write the encrypted or decrypted data 309 | hOutFile = CreateFile(lpszOutputFileName, 310 | GENERIC_WRITE, 311 | 0, 312 | NULL, 313 | CREATE_ALWAYS, 314 | FILE_ATTRIBUTE_NORMAL, 315 | NULL); 316 | 317 | if (hOutFile == INVALID_HANDLE_VALUE) { 318 | MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); 319 | __leave; 320 | } 321 | 322 | if (fEncrypt) { 323 | fResult = CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hSessionKey); 324 | 325 | if (!fResult) { 326 | MyPrintf(_T("CryptGenKey failed with %X\n"), GetLastError()); 327 | __leave; 328 | } 329 | 330 | // The first call to ExportKey with NULL gets the key size. 331 | dwSessionKeyBlob = 0; 332 | fResult = CryptExportKey(hSessionKey, hRSAKey, SIMPLEBLOB, 0, 333 | NULL, &dwSessionKeyBlob); 334 | 335 | if (!fResult) { 336 | MyPrintf(_T("CryptExportKey failed with %X\n"), GetLastError()); 337 | __leave; 338 | } 339 | 340 | // Allocate memory for Encrypted Session key blob 341 | pbSessionKeyBlob = (LPBYTE)LocalAlloc(LPTR, dwSessionKeyBlob); 342 | 343 | if (!pbSessionKeyBlob) { 344 | MyPrintf(_T("LocalAlloc failed with %d\n"), GetLastError()); 345 | __leave; 346 | } 347 | 348 | fResult = CryptExportKey(hSessionKey, hRSAKey, SIMPLEBLOB, 0, 349 | pbSessionKeyBlob, &dwSessionKeyBlob); 350 | 351 | if (!fResult) { 352 | MyPrintf(_T("CryptExportKey failed with %X\n"), GetLastError()); 353 | __leave; 354 | } 355 | 356 | // Write the size of key blob, then the key blob itself, to output file. 357 | fResult = WriteFile(hOutFile, &dwSessionKeyBlob, 358 | sizeof(dwSessionKeyBlob), 359 | &dwBytesWritten, NULL); 360 | 361 | if (!fResult) { 362 | MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); 363 | __leave; 364 | } 365 | 366 | fResult = WriteFile(hOutFile, pbSessionKeyBlob, 367 | dwSessionKeyBlob, 368 | &dwBytesWritten, NULL); 369 | 370 | if (!fResult) { 371 | MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); 372 | __leave; 373 | } 374 | } else { 375 | // Read in key block size, then key blob itself from input file. 376 | fResult = ReadFile(hInFile, &dwByteCount, sizeof(dwByteCount), 377 | &dwBytesRead, NULL); 378 | 379 | if (!fResult) { 380 | MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); 381 | __leave; 382 | } 383 | 384 | fResult = ReadFile(hInFile, pbBuffer, dwByteCount, &dwBytesRead, NULL); 385 | 386 | if (!fResult) { 387 | MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); 388 | __leave; 389 | } 390 | 391 | // import key blob into "CSP" 392 | fResult = CryptImportKey(hProv, pbBuffer, dwByteCount, hRSAKey, 0, &hSessionKey); 393 | 394 | if (!fResult) { 395 | MyPrintf(_T("CryptImportKey failed with %X\n"), GetLastError()); 396 | __leave; 397 | } 398 | } 399 | 400 | do { 401 | dwByteCount = 0; 402 | // Now read data from the input file 64K bytes at a time. 403 | fResult = ReadFile(hInFile, pbBuffer, IN_BUFFER_SIZE, &dwByteCount, NULL); 404 | 405 | // If the file size is exact multiple of 64K, dwByteCount will be zero after 406 | // all the data has been read from the input file. In this case, simply break 407 | // from the while loop. The check to do this is below 408 | if (dwByteCount == 0) 409 | break; 410 | 411 | if (!fResult) { 412 | MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); 413 | __leave; 414 | } 415 | 416 | finished = (dwByteCount < IN_BUFFER_SIZE); 417 | 418 | // Encrypt/Decrypt depending on the required action. 419 | if (fEncrypt) { 420 | fResult = CryptEncrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount, 421 | OUT_BUFFER_SIZE); 422 | 423 | if (!fResult) { 424 | MyPrintf(_T("CryptEncrypt failed with %X\n"), GetLastError()); 425 | __leave; 426 | } 427 | } else { 428 | fResult = CryptDecrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount); 429 | 430 | if (!fResult) { 431 | MyPrintf(_T("CryptDecrypt failed with %X\n"), GetLastError()); 432 | __leave; 433 | } 434 | } 435 | 436 | // Write the encrypted/decrypted data to the output file. 437 | fResult = WriteFile(hOutFile, pbBuffer, dwByteCount, 438 | &dwBytesWritten, NULL); 439 | 440 | if (!fResult) { 441 | MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); 442 | __leave; 443 | } 444 | } while (!finished); 445 | 446 | if (fEncrypt) 447 | MyPrintf(_T("File %s is encrypted successfully!\n"), lpszInputFileName); 448 | else 449 | MyPrintf(_T("File %s is decrypted successfully!\n"), lpszInputFileName); 450 | 451 | fSuccess = TRUE; 452 | } __finally { 453 | /* Cleanup */ 454 | CheckAndLocalFree(pbSessionKeyBlob); 455 | 456 | if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); 457 | 458 | if (hRSAKey != NULL) CryptDestroyKey(hRSAKey); 459 | 460 | if (hSessionKey != NULL) CryptDestroyKey(hSessionKey); 461 | 462 | if (fCallerFreeProv && hProv != NULL) CryptReleaseContext(hProv, 0); 463 | 464 | if (hInFile != INVALID_HANDLE_VALUE) CloseHandle(hInFile); 465 | 466 | if (hOutFile != INVALID_HANDLE_VALUE) CloseHandle(hOutFile); 467 | } 468 | 469 | return fSuccess; 470 | } 471 | -------------------------------------------------------------------------------- /src/rsacert/RSACert.vcproj: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 27 | 30 | 33 | 36 | 39 | 42 | 54 | 57 | 60 | 63 | 72 | 75 | 78 | 81 | 84 | 87 | 90 | 93 | 94 | 100 | 103 | 106 | 109 | 112 | 116 | 129 | 132 | 135 | 138 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 168 | 169 | 175 | 178 | 181 | 184 | 187 | 190 | 199 | 202 | 205 | 208 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 240 | 241 | 247 | 250 | 253 | 256 | 259 | 263 | 273 | 276 | 279 | 282 | 293 | 296 | 299 | 302 | 305 | 308 | 311 | 314 | 315 | 316 | 317 | 318 | 319 | 324 | 325 | 330 | 331 | 336 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | -------------------------------------------------------------------------------- /src/rsacert/ReadMe.Txt: -------------------------------------------------------------------------------- 1 | File Encryption/Decryption sample using a random session key. The RSA 2 | key associated with the specified certificate is used to encrypt or 3 | decrypt the session key. 4 | 5 | Usage 6 | --------- 7 | 8 | The RSACert sample is run from the command line as follows: 9 | 10 | RSACert [|] [|] 11 | 12 | Encryption 13 | --------------- 14 | 15 | /e for Encryption 16 | 17 | The argument specifies the name of the certificate that is 18 | present in the certificate store named by argument. 19 | 20 | A random session key is generated and used to encrypt the data contained 21 | in InputFile. The session key is encrypted using the RSA public key 22 | associated with the specified certificate and the encrypted session key 23 | SIMPLEBLOB is exported and written in the beginning of the output file. 24 | 25 | /u for current user certificate store or /m for local machine certificate store 26 | 27 | The argument specifies the filename of the plaintext file 28 | to be encrypted, and the argument specifies the filename of 29 | the ciphertext file to be created. 30 | 31 | Decryption 32 | --------------- 33 | 34 | /d for Decryption 35 | 36 | The argument specifies the name of the certificate that is 37 | present in the certificate store named by argument. The encrypted 38 | session key SIMPLEBLOB is read from the beginning of the input file and is 39 | then imported. The RSA private key to decrypt this blob is acquired using 40 | CryptAcquireCertificatePrivateKey() API with the certifcate context of the 41 | supplied certificate. CryptImportKey () API will decrypt the SIMPLEBLOB 42 | using the RSA private key and return a handle to session key which is then 43 | used to decrypt the data contained in input file. 44 | 45 | /u for current user certificate store or /m for local machine certificate store 46 | 47 | The argument specifies the filename of the ciphertext file 48 | to be decrypted, and the argument specifies the filename of 49 | the destination file to be created. 50 | -------------------------------------------------------------------------------- /src/rsakey/RSAKey.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 3 | ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 4 | TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 5 | PARTICULAR PURPOSE. 6 | 7 | Copyright (C) Microsoft Corporation. All rights reserved. 8 | */ 9 | 10 | #define UNICODE 11 | #define _UNICODE 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include // for proper buffer handling 18 | 19 | const int IN_BUFFER_SIZE = 64 * 1024; 20 | // OUT_BUFFER_SIZE is 8 bytes larger than IN_BUFFER_SIZE 21 | // When CALG_RC2 algorithm is used, encrypted data 22 | // will be 8 bytes larger than IN_BUFFER_SIZE 23 | const int OUT_BUFFER_SIZE = IN_BUFFER_SIZE + 8; // extra padding 24 | 25 | void PrintUsage(); 26 | BOOL EncryptDecryptFile(LPTSTR lpszContainerName, 27 | DWORD dwFlags, 28 | LPTSTR lpszInputFileName, 29 | LPTSTR lpszOutputFileName, 30 | BOOL fEncrypt); 31 | void __cdecl MyPrintf(LPCTSTR lpszFormat, ...); 32 | 33 | #define CheckAndLocalFree(ptr) \ 34 | if (ptr != NULL) \ 35 | { \ 36 | LocalFree(ptr); \ 37 | ptr = NULL; \ 38 | } 39 | 40 | void PrintUsage() 41 | { 42 | MyPrintf(_T("RSAKey [|] [|] \n")); 43 | MyPrintf(_T("/e for Encryption\n")); 44 | MyPrintf(_T("/d for Decryption\n")); 45 | MyPrintf(_T("/u for current user key container\n")); 46 | MyPrintf(_T("/m for local machine key container\n")); 47 | } 48 | 49 | void __cdecl MyPrintf(LPCTSTR lpszFormat, ...) 50 | { 51 | TCHAR szOutput[2048]; 52 | va_list v1 = NULL; 53 | HRESULT hr = S_OK; 54 | va_start(v1, lpszFormat); 55 | hr = StringCbVPrintf(szOutput, sizeof(szOutput), lpszFormat, v1); 56 | 57 | if (SUCCEEDED(hr)) { 58 | OutputDebugString(szOutput); 59 | _tprintf(szOutput); 60 | } else { 61 | _tprintf(_T("StringCbVPrintf failed with %X\n"), hr); 62 | } 63 | } 64 | 65 | void _tmain(int argc, TCHAR **argv) 66 | { 67 | BOOL fEncrypt = FALSE; 68 | LPTSTR lpszContainerName = NULL; 69 | LPTSTR lpszInputFileName = NULL; 70 | LPTSTR lpszOutputFileName = NULL; 71 | DWORD dwFlags = 0; 72 | 73 | if (argc != 6) { 74 | PrintUsage(); 75 | return; 76 | } 77 | 78 | /* Check whether the action to be performed is encrypt or decrypt */ 79 | if (_tcsicmp(argv[1], _T("/e")) == 0) { 80 | fEncrypt = TRUE; 81 | } else if (_tcsicmp(argv[1], _T("/d")) == 0) { 82 | fEncrypt = FALSE; 83 | } else { 84 | PrintUsage(); 85 | return; 86 | } 87 | 88 | lpszContainerName = argv[2]; 89 | 90 | /* Check whether to use current user or local machine key container */ 91 | if (_tcsicmp(argv[3], _T("/u")) == 0) { 92 | dwFlags = 0; 93 | } else if (_tcsicmp(argv[3], _T("/m")) == 0) { 94 | dwFlags = CRYPT_MACHINE_KEYSET; 95 | } else { 96 | PrintUsage(); 97 | return; 98 | } 99 | 100 | lpszInputFileName = argv[4]; 101 | lpszOutputFileName = argv[5]; 102 | EncryptDecryptFile(lpszContainerName, 103 | dwFlags, 104 | lpszInputFileName, 105 | lpszOutputFileName, 106 | fEncrypt); 107 | } 108 | 109 | BOOL EncryptDecryptFile(LPTSTR lpszContainerName, 110 | DWORD dwFlags, 111 | LPTSTR lpszInputFileName, 112 | LPTSTR lpszOutputFileName, 113 | BOOL fEncrypt) 114 | { 115 | BOOL fResult = FALSE; 116 | HCRYPTPROV hProv = NULL; 117 | HCRYPTKEY hRSAKey = NULL; 118 | HCRYPTKEY hSessionKey = NULL; 119 | HANDLE hInFile = INVALID_HANDLE_VALUE; 120 | HANDLE hOutFile = INVALID_HANDLE_VALUE; 121 | BOOL finished = FALSE; 122 | BYTE pbBuffer[OUT_BUFFER_SIZE]; 123 | DWORD dwByteCount = 0; 124 | DWORD dwBytesRead = 0; 125 | DWORD dwBytesWritten = 0; 126 | LPBYTE pbSessionKeyBlob = NULL; 127 | DWORD dwSessionKeyBlob = 0; 128 | BOOL fSuccess = FALSE; 129 | 130 | __try { 131 | // Open the input file to be encrypted or decrypted 132 | hInFile = CreateFile(lpszInputFileName, 133 | GENERIC_READ, 134 | 0, 135 | NULL, 136 | OPEN_EXISTING, 137 | FILE_ATTRIBUTE_NORMAL, 138 | NULL); 139 | 140 | if (hInFile == INVALID_HANDLE_VALUE) { 141 | MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); 142 | __leave; 143 | } 144 | 145 | // Open the output file to write the encrypted or decrypted data 146 | hOutFile = CreateFile(lpszOutputFileName, 147 | GENERIC_WRITE, 148 | 0, 149 | NULL, 150 | CREATE_ALWAYS, 151 | FILE_ATTRIBUTE_NORMAL, 152 | NULL); 153 | 154 | if (hOutFile == INVALID_HANDLE_VALUE) { 155 | MyPrintf(_T("CreateFile failed with %d\n"), GetLastError()); 156 | __leave; 157 | } 158 | 159 | // Acquire context for RSA key 160 | fResult = CryptAcquireContext(&hProv, 161 | lpszContainerName, 162 | MS_DEF_PROV, 163 | PROV_RSA_FULL, 164 | dwFlags); 165 | 166 | if (!fResult) { 167 | if (GetLastError() == NTE_BAD_KEYSET) { 168 | // Create a key container if one does not exist. 169 | fResult = CryptAcquireContext(&hProv, 170 | lpszContainerName, 171 | MS_DEF_PROV, 172 | PROV_RSA_FULL, 173 | CRYPT_NEWKEYSET | dwFlags); 174 | 175 | if (!fResult) { 176 | MyPrintf(_T("CryptAcquireContext (2) failed with %X\n"), GetLastError()); 177 | __leave; 178 | } 179 | } else { 180 | MyPrintf(_T("CryptAcquireContext (1) failed with %X\n"), GetLastError()); 181 | __leave; 182 | } 183 | } 184 | 185 | // Get the RSA key handle 186 | fResult = CryptGetUserKey(hProv, AT_KEYEXCHANGE, &hRSAKey); 187 | 188 | if (!fResult) { 189 | if (GetLastError() == NTE_NO_KEY) { 190 | // Create a key if one does not exist. 191 | fResult = CryptGenKey(hProv, 192 | AT_KEYEXCHANGE, 193 | CRYPT_EXPORTABLE, 194 | &hRSAKey); 195 | 196 | if (!fResult) { 197 | MyPrintf(_T("CryptGenKey failed with %X\n"), GetLastError()); 198 | __leave; 199 | } 200 | } else { 201 | MyPrintf(_T("CryptGetUserKey failed with %X\n"), GetLastError()); 202 | __leave; 203 | } 204 | } 205 | 206 | if (fEncrypt) { 207 | fResult = CryptGenKey(hProv, CALG_RC4, CRYPT_EXPORTABLE, &hSessionKey); 208 | 209 | if (!fResult) { 210 | MyPrintf(_T("CryptGenKey failed with %X\n"), GetLastError()); 211 | __leave; 212 | } 213 | 214 | // The first call to ExportKey with NULL gets the key size. 215 | dwSessionKeyBlob = 0; 216 | fResult = CryptExportKey(hSessionKey, hRSAKey, SIMPLEBLOB, 0, 217 | NULL, &dwSessionKeyBlob); 218 | 219 | if (!fResult) { 220 | MyPrintf(_T("CryptExportKey failed with %X\n"), GetLastError()); 221 | __leave; 222 | } 223 | 224 | // Allocate memory for Encrypted Session key blob 225 | pbSessionKeyBlob = (LPBYTE)LocalAlloc(LPTR, dwSessionKeyBlob); 226 | 227 | if (!pbSessionKeyBlob) { 228 | MyPrintf(_T("LocalAlloc failed with %d\n"), GetLastError()); 229 | __leave; 230 | } 231 | 232 | fResult = CryptExportKey(hSessionKey, hRSAKey, SIMPLEBLOB, 0, 233 | pbSessionKeyBlob, &dwSessionKeyBlob); 234 | 235 | if (!fResult) { 236 | MyPrintf(_T("CryptExportKey failed with %X\n"), GetLastError()); 237 | __leave; 238 | } 239 | 240 | // Write the size of key blob, then the key blob itself, to output file. 241 | fResult = WriteFile(hOutFile, &dwSessionKeyBlob, 242 | sizeof(dwSessionKeyBlob), 243 | &dwBytesWritten, NULL); 244 | 245 | if (!fResult) { 246 | MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); 247 | __leave; 248 | } 249 | 250 | fResult = WriteFile(hOutFile, pbSessionKeyBlob, 251 | dwSessionKeyBlob, 252 | &dwBytesWritten, NULL); 253 | 254 | if (!fResult) { 255 | MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); 256 | __leave; 257 | } 258 | } else { 259 | // Read in key block size, then key blob itself from input file. 260 | fResult = ReadFile(hInFile, &dwByteCount, sizeof(dwByteCount), 261 | &dwBytesRead, NULL); 262 | 263 | if (!fResult) { 264 | MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); 265 | __leave; 266 | } 267 | 268 | fResult = ReadFile(hInFile, pbBuffer, dwByteCount, &dwBytesRead, NULL); 269 | 270 | if (!fResult) { 271 | MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); 272 | __leave; 273 | } 274 | 275 | // import key blob into "CSP" 276 | fResult = CryptImportKey(hProv, pbBuffer, dwByteCount, hRSAKey, 0, &hSessionKey); 277 | 278 | if (!fResult) { 279 | MyPrintf(_T("CryptImportKey failed with %X\n"), GetLastError()); 280 | __leave; 281 | } 282 | } 283 | 284 | do { 285 | dwByteCount = 0; 286 | // Now read data from the input file 64K bytes at a time. 287 | fResult = ReadFile(hInFile, pbBuffer, IN_BUFFER_SIZE, &dwByteCount, NULL); 288 | 289 | // If the file size is exact multiple of 64K, dwByteCount will be zero after 290 | // all the data has been read from the input file. In this case, simply break 291 | // from the while loop. The check to do this is below 292 | if (dwByteCount == 0) 293 | break; 294 | 295 | if (!fResult) { 296 | MyPrintf(_T("ReadFile failed with %d\n"), GetLastError()); 297 | __leave; 298 | } 299 | 300 | finished = (dwByteCount < IN_BUFFER_SIZE); 301 | 302 | // Encrypt/Decrypt depending on the required action. 303 | if (fEncrypt) { 304 | fResult = CryptEncrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount, 305 | OUT_BUFFER_SIZE); 306 | 307 | if (!fResult) { 308 | MyPrintf(_T("CryptEncrypt failed with %X\n"), GetLastError()); 309 | __leave; 310 | } 311 | } else { 312 | fResult = CryptDecrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount); 313 | 314 | if (!fResult) { 315 | MyPrintf(_T("CryptDecrypt failed with %X\n"), GetLastError()); 316 | __leave; 317 | } 318 | } 319 | 320 | // Write the encrypted/decrypted data to the output file. 321 | fResult = WriteFile(hOutFile, pbBuffer, dwByteCount, 322 | &dwBytesWritten, NULL); 323 | 324 | if (!fResult) { 325 | MyPrintf(_T("WriteFile failed with %d\n"), GetLastError()); 326 | __leave; 327 | } 328 | } while (!finished); 329 | 330 | if (fEncrypt) 331 | MyPrintf(_T("File %s is encrypted successfully!\n"), lpszInputFileName); 332 | else 333 | MyPrintf(_T("File %s is decrypted successfully!\n"), lpszInputFileName); 334 | 335 | fSuccess = TRUE; 336 | } __finally { 337 | /* Cleanup */ 338 | CheckAndLocalFree(pbSessionKeyBlob); 339 | 340 | if (hRSAKey != NULL) CryptDestroyKey(hRSAKey); 341 | 342 | if (hSessionKey != NULL) CryptDestroyKey(hSessionKey); 343 | 344 | if (hProv != NULL) CryptReleaseContext(hProv, 0); 345 | 346 | if (hInFile != INVALID_HANDLE_VALUE) CloseHandle(hInFile); 347 | 348 | if (hOutFile != INVALID_HANDLE_VALUE) CloseHandle(hOutFile); 349 | } 350 | 351 | return fSuccess; 352 | } 353 | -------------------------------------------------------------------------------- /src/rsakey/RSAKey.vcproj: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 27 | 30 | 33 | 36 | 39 | 42 | 54 | 57 | 60 | 63 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 98 | 101 | 104 | 107 | 110 | 113 | 122 | 125 | 128 | 131 | 140 | 143 | 146 | 149 | 152 | 155 | 158 | 161 | 162 | 168 | 171 | 174 | 177 | 180 | 184 | 197 | 200 | 203 | 206 | 213 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 235 | 241 | 244 | 247 | 250 | 253 | 257 | 266 | 269 | 272 | 275 | 284 | 287 | 290 | 293 | 296 | 299 | 302 | 305 | 306 | 307 | 308 | 309 | 310 | 315 | 316 | 321 | 322 | 327 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | -------------------------------------------------------------------------------- /src/rsakey/ReadMe.Txt: -------------------------------------------------------------------------------- 1 | File Encryption/Decryption sample using a random session key. The RSA 2 | key is used to encrypt or decrypt the session key. 3 | 4 | Usage 5 | --------- 6 | 7 | The RSAKey sample is run from the command line as follows: 8 | 9 | RSAKey [|] [|] 10 | 11 | Encryption 12 | --------------- 13 | 14 | /e for Encryption 15 | 16 | The argument specifies the name of the current user 17 | key container that is created or opened. A random session key is generated 18 | and used to encrypt the data contained in InputFile. The session 19 | key is encrypted using the RSA public key and the encrypted session key 20 | SIMPLEBLOB is exported and written in the beginning of the output file. 21 | 22 | /u for current user key container or /m for local machine key container 23 | 24 | The argument specifies the filename of the plaintext file 25 | to be encrypted, and the argument specifies the filename of 26 | the ciphertext file to be created. 27 | 28 | Decryption 29 | --------------- 30 | 31 | /d for Decryption 32 | 33 | The argument specifies the name of the current user 34 | key container that is created or opened. The encrypted session key 35 | SIMPLEBLOB is read from the beginning of the input file and is then imported. 36 | CryptImportKey will decrypt the SIMPLEBLOB using the RSA private key and 37 | return a handle to session key which is then used to decrypt the data contained 38 | in input file. 39 | 40 | /u for current user key container or /m for local machine key container 41 | 42 | The argument specifies the filename of the ciphertext file 43 | to be decrypted, and the argument specifies the filename of 44 | the destination file to be created. 45 | -------------------------------------------------------------------------------- /src/sessionkey/ReadMe.Txt: -------------------------------------------------------------------------------- 1 | File Encryption/Decryption sample using session key derived from a password hash 2 | 3 | Usage 4 | --------- 5 | 6 | The SessionKey sample is run from the command line as follows: 7 | 8 | SessionKey [|] 9 | 10 | Encryption 11 | --------------- 12 | 13 | The argument specifies a password whose hash is used 14 | to derive a session key. The derived session key is used to encrypt 15 | the data contained in InputFile 16 | 17 | /e for Encryption 18 | 19 | The argument specifies the filename of the plaintext file 20 | to be encrypted, and the argument specifies the filename of 21 | the ciphertext file to be created. 22 | 23 | Decryption 24 | --------------- 25 | 26 | The argument specifies a password whose hash is used 27 | to derive a session key. The derived session key is used to decrypt 28 | the data contained in InputFile 29 | 30 | /d for Decryption 31 | 32 | The argument specifies the filename of the ciphertext file 33 | to be decrypted, and the argument specifies the filename of 34 | the destination file to be created. 35 | 36 | If an incorrect password is supplied during decrypt, the file will not be 37 | decrypted correctly. 38 | -------------------------------------------------------------------------------- /src/sessionkey/SessionKey.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 3 | ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 4 | TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 5 | PARTICULAR PURPOSE. 6 | 7 | Copyright (C) Microsoft Corporation. All rights reserved. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | const int IN_BUFFER_SIZE = 64 * 1024; 16 | // OUT_BUFFER_SIZE is 8 bytes larger than IN_BUFFER_SIZE 17 | // When CALG_RC2 algorithm is used, encrypted data 18 | // will be 8 bytes larger than IN_BUFFER_SIZE 19 | const int OUT_BUFFER_SIZE = IN_BUFFER_SIZE + 8; // extra padding 20 | 21 | void PrintUsage() 22 | { 23 | _tprintf(_T("SessionKey [|] \n")); 24 | _tprintf(_T("/e for Encryption\n")); 25 | _tprintf(_T("/d for Decryption\n")); 26 | } 27 | 28 | void _tmain(int argc, TCHAR *argv[]) 29 | { 30 | BOOL fResult = FALSE; 31 | HCRYPTPROV hProv = NULL; 32 | HCRYPTHASH hHash = NULL; 33 | HCRYPTKEY hSessionKey = NULL; 34 | HANDLE hInFile = INVALID_HANDLE_VALUE; 35 | HANDLE hOutFile = INVALID_HANDLE_VALUE; 36 | BOOL fEncrypt = FALSE; 37 | BOOL finished = FALSE; 38 | BYTE pbBuffer[OUT_BUFFER_SIZE]; 39 | DWORD dwByteCount = 0; 40 | DWORD dwBytesWritten = 0; 41 | 42 | if (argc != 5) { 43 | PrintUsage(); 44 | return; 45 | } 46 | 47 | __try { 48 | /* Check whether the action to be performed is encrypt or decrypt */ 49 | if (_tcsicmp(argv[2], _T("/e")) == 0) { 50 | fEncrypt = TRUE; 51 | } else if (_tcsicmp(argv[2], _T("/d")) == 0) { 52 | fEncrypt = FALSE; 53 | } else { 54 | PrintUsage(); 55 | return; 56 | } 57 | 58 | // Open the input file to be encrypted or decrypted 59 | hInFile = CreateFile(argv[3], 60 | GENERIC_READ, 61 | 0, 62 | NULL, 63 | OPEN_EXISTING, 64 | FILE_ATTRIBUTE_NORMAL, 65 | NULL); 66 | 67 | if (hInFile == INVALID_HANDLE_VALUE) { 68 | _tprintf(_T("CreateFile failed with %d\n"), GetLastError()); 69 | __leave; 70 | } 71 | 72 | // Open the output file to write the encrypted or decrypted data 73 | hOutFile = CreateFile(argv[4], 74 | GENERIC_WRITE, 75 | 0, 76 | NULL, 77 | CREATE_ALWAYS, 78 | FILE_ATTRIBUTE_NORMAL, 79 | NULL); 80 | 81 | if (hOutFile == INVALID_HANDLE_VALUE) { 82 | _tprintf(_T("CreateFile failed with %d\n"), GetLastError()); 83 | __leave; 84 | } 85 | 86 | // Acquire a handle to MS_DEF_PROV using CRYPT_VERIFYCONTEXT for dwFlags 87 | // parameter as we are going to do only session key encryption or decryption 88 | fResult = CryptAcquireContext(&hProv, 89 | NULL, 90 | MS_DEF_PROV, 91 | PROV_RSA_FULL, 92 | CRYPT_VERIFYCONTEXT); 93 | 94 | if (!fResult) { 95 | _tprintf(_T("CryptAcquireContext failed with %X\n"), GetLastError()); 96 | __leave; 97 | } 98 | 99 | fResult = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash); 100 | 101 | if (!fResult) { 102 | _tprintf(_T("CryptCreateHash failed with %X\n"), GetLastError()); 103 | __leave; 104 | } 105 | 106 | // Hash the supplied secret password 107 | fResult = CryptHashData(hHash, (LPBYTE)argv[1], (DWORD)_tcslen(argv[1]), 0); 108 | 109 | if (!fResult) { 110 | _tprintf(_T("CryptHashData failed with %X\n"), GetLastError()); 111 | __leave; 112 | } 113 | 114 | // Derive a symmetric session key from password hash 115 | fResult = CryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hSessionKey); 116 | 117 | if (!fResult) { 118 | _tprintf(_T("CryptDeriveKey failed with %X\n"), GetLastError()); 119 | __leave; 120 | } 121 | 122 | do { 123 | dwByteCount = 0; 124 | // Now read data from the input file 64K bytes at a time. 125 | fResult = ReadFile(hInFile, pbBuffer, IN_BUFFER_SIZE, &dwByteCount, NULL); 126 | 127 | // If the file size is exact multiple of 64K, dwByteCount will be zero after 128 | // all the data has been read from the input file. In this case, simply break 129 | // from the while loop. The check to do this is below 130 | if (dwByteCount == 0) 131 | break; 132 | 133 | if (!fResult) { 134 | _tprintf(_T("ReadFile failed with %d\n"), GetLastError()); 135 | __leave; 136 | } 137 | 138 | finished = (dwByteCount < IN_BUFFER_SIZE); 139 | 140 | // Encrypt/Decrypt depending on the required action. 141 | if (fEncrypt) { 142 | fResult = CryptEncrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount, 143 | OUT_BUFFER_SIZE); 144 | 145 | if (!fResult) { 146 | _tprintf(_T("CryptEncrypt failed with %X\n"), GetLastError()); 147 | __leave; 148 | } 149 | } else { 150 | fResult = CryptDecrypt(hSessionKey, 0, finished, 0, pbBuffer, &dwByteCount); 151 | 152 | if (!fResult) { 153 | _tprintf(_T("CryptDecrypt failed with %X\n"), GetLastError()); 154 | __leave; 155 | } 156 | } 157 | 158 | // Write the encrypted/decrypted data to the output file. 159 | fResult = WriteFile(hOutFile, pbBuffer, dwByteCount, 160 | &dwBytesWritten, NULL); 161 | 162 | if (!fResult) { 163 | _tprintf(_T("WriteFile failed with %d\n"), GetLastError()); 164 | __leave; 165 | } 166 | } while (!finished); 167 | 168 | if (fEncrypt) 169 | _tprintf(_T("File %s is encrypted successfully!\n"), argv[3]); 170 | else 171 | _tprintf(_T("File %s is decrypted successfully!\n"), argv[3]); 172 | } __finally { 173 | /* Cleanup */ 174 | if (hInFile != INVALID_HANDLE_VALUE) CloseHandle(hInFile); 175 | 176 | if (hOutFile != INVALID_HANDLE_VALUE) CloseHandle(hOutFile); 177 | 178 | if (hSessionKey != NULL) CryptDestroyKey(hSessionKey); 179 | 180 | if (hHash != NULL) CryptDestroyHash(hHash); 181 | 182 | if (hProv != NULL) CryptReleaseContext(hProv, 0); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/sessionkey/SessionKey.vcproj: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 27 | 30 | 33 | 36 | 39 | 42 | 55 | 58 | 61 | 64 | 71 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 93 | 99 | 102 | 105 | 108 | 111 | 114 | 124 | 127 | 130 | 133 | 142 | 145 | 148 | 151 | 154 | 157 | 160 | 163 | 164 | 170 | 173 | 176 | 179 | 182 | 186 | 199 | 202 | 205 | 208 | 215 | 218 | 221 | 224 | 227 | 230 | 233 | 236 | 237 | 243 | 246 | 249 | 252 | 255 | 259 | 269 | 272 | 275 | 278 | 287 | 290 | 293 | 296 | 299 | 302 | 305 | 308 | 309 | 310 | 311 | 312 | 313 | 318 | 319 | 324 | 325 | 330 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | -------------------------------------------------------------------------------- /src/signhash/Readme.txt: -------------------------------------------------------------------------------- 1 | File Signing/Verification sample that hashes the data in a file and signs or 2 | verifies the signature with the private or public key respectively. 3 | 4 | Usage 5 | --------- 6 | 7 | The SignHash sample is run from the command line as follows: 8 | 9 | SignHash [md5|sha1] [|] [|] 10 | /s to Sign. 11 | /v to Verify. 12 | /cert [|] - use a certificate. 13 | /key [|] [|] use container with exchange or signature key. 14 | 15 | 16 | Signing 17 | --------------- 18 | 19 | /s for Signing 20 | 21 | When Signing, the is Hashed and signed with the private key. 22 | The private key can be a certificate or Crypto key container. Read the 23 | /cert or /key options for more information. After the file is signed, the 24 | signature is saved to . 25 | 26 | 27 | Verifying 28 | --------------- 29 | 30 | /v for Verifying 31 | 32 | When Verifying, the is Hashed and the is used along with 33 | the public key to verify the signature. The public key can be obtained from 34 | a certificate or key container. 35 | 36 | 37 | Using Certificates 38 | ------------------ 39 | 40 | /cert [|] 41 | 42 | A certificate can be used to sign or verify a file. The sample retrieves the 43 | certificate from a certificate store. To find a certificate to use you must 44 | supply the certificate name, certificate store name and whether you want to 45 | look in the user's store or the local machine store for the certificate. The 46 | most common request is to use the user's personal certificate store to find the 47 | certificate. In this case the store name is "MY" and the option would be used. 48 | 49 | Using Key Containers 50 | -------------------- 51 | 52 | /key [|] [|] 53 | 54 | A key container can be used to sign or verify a file. A key container represents 55 | a CryptAPI container that holds the private/public key. The option selects the 56 | user store and selects the machine store. selects the exchange key in the 57 | container and selects the signature key. -------------------------------------------------------------------------------- /src/signhash/Signhash.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Signhash", "Signhash.vcproj", "{C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Debug|x64 = Debug|x64 10 | Release|Win32 = Release|Win32 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Debug|Win32.Build.0 = Debug|Win32 16 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Debug|x64.ActiveCfg = Debug|x64 17 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Debug|x64.Build.0 = Debug|x64 18 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Release|Win32.ActiveCfg = Release|Win32 19 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Release|Win32.Build.0 = Release|Win32 20 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Release|x64.ActiveCfg = Release|x64 21 | {C1FC07B5-1FAD-4C0B-8C09-FB94CD498252}.Release|x64.Build.0 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/signhash/Signhash.vcproj: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 27 | 30 | 33 | 36 | 39 | 42 | 54 | 57 | 60 | 63 | 71 | 74 | 77 | 80 | 83 | 86 | 89 | 92 | 93 | 99 | 102 | 105 | 108 | 111 | 115 | 128 | 131 | 134 | 137 | 145 | 148 | 151 | 154 | 157 | 160 | 163 | 166 | 167 | 173 | 176 | 179 | 182 | 185 | 188 | 197 | 200 | 203 | 206 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 244 | 247 | 250 | 253 | 256 | 260 | 269 | 272 | 275 | 278 | 288 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 310 | 311 | 312 | 313 | 314 | 319 | 320 | 325 | 326 | 331 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | -------------------------------------------------------------------------------- /src/test-base64/base64.cpp: -------------------------------------------------------------------------------- 1 | bool Base64EncodeA(char **dest, unsigned long *dlen, const unsigned char *src, unsigned long slen) 2 | { 3 | if (src == NULL) 4 | return false; 5 | 6 | if (!CryptBinaryToStringA(src, slen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, dlen)) 7 | return false; 8 | 9 | *dest = (char *)malloc(*dlen * sizeof(char)); 10 | 11 | if (*dest == NULL) return false; 12 | 13 | SecureZeroMemory(*dest, *dlen * sizeof(char)); 14 | 15 | if (!CryptBinaryToStringA(src, slen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, *dest, dlen)) { 16 | SAFE_FREE(*dest); 17 | return false; 18 | } 19 | 20 | return true; 21 | } 22 | 23 | bool Base64DecodeA(unsigned char **dest, unsigned long *dlen, const char *src, unsigned long slen) 24 | { 25 | if (src == NULL) 26 | return false; 27 | 28 | if (!CryptStringToBinaryA(src, slen, CRYPT_STRING_BASE64, NULL, dlen, NULL, NULL)) 29 | return false; 30 | 31 | *dest = (unsigned char *)malloc((*dlen + 1) * sizeof(unsigned char)); 32 | 33 | if (*dest == NULL) return false; 34 | 35 | SecureZeroMemory(*dest, (*dlen + 1) * sizeof(unsigned char)); 36 | 37 | if (!CryptStringToBinaryA(src, slen, CRYPT_STRING_BASE64, *dest, dlen, NULL, NULL)) { 38 | SAFE_FREE(*dest); 39 | return false; 40 | } 41 | 42 | return true; 43 | } 44 | 45 | 46 | 47 | #define SAFE_FREE(x) if(x) { free(x); x=NULL; } 48 | 49 | char *encoded = 0; 50 | unsigned long encodedLen = 0, decodedLen = 0; 51 | char *decoded = 0; 52 | 53 | if (Base64EncodeA(&encoded, &encodedLen, argv[1], strlen(argv[1]))) 54 | { 55 | printf("Base64 encoded: %s\n", encoded); 56 | 57 | if (Base64DecodeA(&decoded, &decodedLen, encoded, encodedLen)) { 58 | printf("Base64 decoded: %s\n", decoded); 59 | SAFE_FREE(encoded); 60 | SAFE_FREE(decoded); 61 | } 62 | } --------------------------------------------------------------------------------