github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/cybozu/crypto.hpp (about) 1 #pragma once 2 /** 3 @file 4 @brief wrap openssl 5 @author MITSUNARI Shigeo(@herumi) 6 */ 7 8 #include <cybozu/exception.hpp> 9 #ifdef __APPLE__ 10 #pragma GCC diagnostic push 11 #pragma GCC diagnostic ignored "-Wdeprecated-declarations" 12 #endif 13 #if 0 //#ifdef __APPLE__ 14 #define COMMON_DIGEST_FOR_OPENSSL 15 #include <CommonCrypto/CommonDigest.h> 16 #include <CommonCrypto/CommonHMAC.h> 17 #define SHA1 CC_SHA1 18 #define SHA224 CC_SHA224 19 #define SHA256 CC_SHA256 20 #define SHA384 CC_SHA384 21 #define SHA512 CC_SHA512 22 #else 23 #include <openssl/hmac.h> 24 #include <openssl/evp.h> 25 #include <openssl/sha.h> 26 #endif 27 #ifdef _MSC_VER 28 #include <cybozu/link_libeay32.hpp> 29 #endif 30 31 namespace cybozu { 32 33 namespace crypto { 34 35 class Hash { 36 public: 37 enum Name { 38 N_SHA1, 39 N_SHA224, 40 N_SHA256, 41 N_SHA384, 42 N_SHA512 43 }; 44 private: 45 Name name_; 46 size_t hashSize_; 47 union { 48 SHA_CTX sha1; 49 SHA256_CTX sha256; 50 SHA512_CTX sha512; 51 } ctx_; 52 public: 53 static inline size_t getSize(Name name) 54 { 55 switch (name) { 56 case N_SHA1: return SHA_DIGEST_LENGTH; 57 case N_SHA224: return SHA224_DIGEST_LENGTH; 58 case N_SHA256: return SHA256_DIGEST_LENGTH; 59 case N_SHA384: return SHA384_DIGEST_LENGTH; 60 case N_SHA512: return SHA512_DIGEST_LENGTH; 61 default: 62 throw cybozu::Exception("crypto:Hash:getSize") << name; 63 } 64 } 65 static inline const char *getName(Name name) 66 { 67 switch (name) { 68 case N_SHA1: return "sha1"; 69 case N_SHA224: return "sha224"; 70 case N_SHA256: return "sha256"; 71 case N_SHA384: return "sha384"; 72 case N_SHA512: return "sha512"; 73 default: 74 throw cybozu::Exception("crypto:Hash:getName") << name; 75 } 76 } 77 static inline Name getName(const std::string& nameStr) 78 { 79 static const struct { 80 const char *nameStr; 81 Name name; 82 } tbl[] = { 83 { "sha1", N_SHA1 }, 84 { "sha224", N_SHA224 }, 85 { "sha256", N_SHA256 }, 86 { "sha384", N_SHA384 }, 87 { "sha512", N_SHA512 }, 88 }; 89 for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) { 90 if (nameStr == tbl[i].nameStr) return tbl[i].name; 91 } 92 throw cybozu::Exception("crypto:Hash:getName") << nameStr; 93 } 94 explicit Hash(Name name = N_SHA1) 95 : name_(name) 96 , hashSize_(getSize(name)) 97 { 98 reset(); 99 } 100 void update(const void *buf, size_t bufSize) 101 { 102 switch (name_) { 103 case N_SHA1: SHA1_Update(&ctx_.sha1, buf, bufSize); break; 104 case N_SHA224: SHA224_Update(&ctx_.sha256, buf, bufSize); break; 105 case N_SHA256: SHA256_Update(&ctx_.sha256, buf, bufSize); break; 106 case N_SHA384: SHA384_Update(&ctx_.sha512, buf, bufSize); break; 107 case N_SHA512: SHA512_Update(&ctx_.sha512, buf, bufSize); break; 108 } 109 } 110 void update(const std::string& buf) 111 { 112 update(buf.c_str(), buf.size()); 113 } 114 void reset() 115 { 116 switch (name_) { 117 case N_SHA1: SHA1_Init(&ctx_.sha1); break; 118 case N_SHA224: SHA224_Init(&ctx_.sha256); break; 119 case N_SHA256: SHA256_Init(&ctx_.sha256); break; 120 case N_SHA384: SHA384_Init(&ctx_.sha512); break; 121 case N_SHA512: SHA512_Init(&ctx_.sha512); break; 122 default: 123 throw cybozu::Exception("crypto:Hash:rset") << name_; 124 } 125 } 126 /* 127 md must have hashSize byte 128 @note clear inner buffer after calling digest 129 */ 130 void digest(void *out, const void *buf, size_t bufSize) 131 { 132 update(buf, bufSize); 133 unsigned char *md = reinterpret_cast<unsigned char*>(out); 134 switch (name_) { 135 case N_SHA1: SHA1_Final(md, &ctx_.sha1); break; 136 case N_SHA224: SHA224_Final(md, &ctx_.sha256); break; 137 case N_SHA256: SHA256_Final(md, &ctx_.sha256); break; 138 case N_SHA384: SHA384_Final(md, &ctx_.sha512); break; 139 case N_SHA512: SHA512_Final(md, &ctx_.sha512); break; 140 default: 141 throw cybozu::Exception("crypto:Hash:digest") << name_; 142 } 143 reset(); 144 } 145 std::string digest(const void *buf, size_t bufSize) 146 { 147 std::string ret; 148 ret.resize(hashSize_); 149 digest(&ret[0], buf, bufSize); 150 return ret; 151 } 152 std::string digest(const std::string& buf = "") 153 { 154 return digest(buf.c_str(), buf.size()); 155 } 156 /* 157 out must have necessary size 158 @note return written size 159 */ 160 static inline size_t digest(void *out, Name name, const void *buf, size_t bufSize) 161 { 162 unsigned char *md = (unsigned char*)out; 163 const unsigned char *src = cybozu::cast<const unsigned char *>(buf); 164 switch (name) { 165 case N_SHA1: SHA1(src, bufSize, md); return 160 / 8; 166 case N_SHA224: SHA224(src, bufSize, md); return 224 / 8; 167 case N_SHA256: SHA256(src, bufSize, md); return 256 / 8; 168 case N_SHA384: SHA384(src, bufSize, md); return 384 / 8; 169 case N_SHA512: SHA512(src, bufSize, md); return 512 / 8; 170 default: 171 return 0; 172 } 173 } 174 static inline std::string digest(Name name, const void *buf, size_t bufSize) 175 { 176 char md[128]; 177 size_t size = digest(md, name, buf, bufSize); 178 if (size == 0) throw cybozu::Exception("crypt:Hash:digest") << name; 179 return std::string(md, size); 180 } 181 static inline std::string digest(Name name, const std::string& buf) 182 { 183 return digest(name, buf.c_str(), buf.size()); 184 } 185 }; 186 187 class Hmac { 188 const EVP_MD *evp_; 189 public: 190 explicit Hmac(Hash::Name name = Hash::N_SHA1) 191 { 192 switch (name) { 193 case Hash::N_SHA1: evp_ = EVP_sha1(); break; 194 case Hash::N_SHA224: evp_ = EVP_sha224(); break; 195 case Hash::N_SHA256: evp_ = EVP_sha256(); break; 196 case Hash::N_SHA384: evp_ = EVP_sha384(); break; 197 case Hash::N_SHA512: evp_ = EVP_sha512(); break; 198 default: 199 throw cybozu::Exception("crypto:Hmac:") << name; 200 } 201 } 202 std::string eval(const std::string& key, const std::string& data) 203 { 204 std::string out(EVP_MD_size(evp_) + 1, 0); 205 unsigned int outLen = 0; 206 if (HMAC(evp_, key.c_str(), static_cast<int>(key.size()), 207 cybozu::cast<const uint8_t *>(data.c_str()), data.size(), cybozu::cast<uint8_t *>(&out[0]), &outLen)) { 208 out.resize(outLen); 209 return out; 210 } 211 throw cybozu::Exception("crypto::Hamc::eval"); 212 } 213 }; 214 215 class Cipher { 216 const EVP_CIPHER *cipher_; 217 EVP_CIPHER_CTX *ctx_; 218 public: 219 enum Name { 220 N_AES128_CBC, 221 N_AES192_CBC, 222 N_AES256_CBC, 223 N_AES128_ECB, // be carefull to use 224 N_AES192_ECB, // be carefull to use 225 N_AES256_ECB, // be carefull to use 226 }; 227 static inline size_t getSize(Name name) 228 { 229 switch (name) { 230 case N_AES128_CBC: return 128; 231 case N_AES192_CBC: return 192; 232 case N_AES256_CBC: return 256; 233 case N_AES128_ECB: return 128; 234 case N_AES192_ECB: return 192; 235 case N_AES256_ECB: return 256; 236 default: 237 throw cybozu::Exception("crypto:Cipher:getSize") << name; 238 } 239 } 240 enum Mode { 241 Decoding, 242 Encoding 243 }; 244 explicit Cipher(Name name = N_AES128_CBC) 245 : cipher_(0) 246 , ctx_(0) 247 { 248 ctx_ = EVP_CIPHER_CTX_new(); 249 if (ctx_ == 0) throw cybozu::Exception("crypto:Cipher:EVP_CIPHER_CTX_new"); 250 switch (name) { 251 case N_AES128_CBC: cipher_ = EVP_aes_128_cbc(); break; 252 case N_AES192_CBC: cipher_ = EVP_aes_192_cbc(); break; 253 case N_AES256_CBC: cipher_ = EVP_aes_256_cbc(); break; 254 case N_AES128_ECB: cipher_ = EVP_aes_128_ecb(); break; 255 case N_AES192_ECB: cipher_ = EVP_aes_192_ecb(); break; 256 case N_AES256_ECB: cipher_ = EVP_aes_256_ecb(); break; 257 default: 258 throw cybozu::Exception("crypto:Cipher:Cipher:name") << (int)name; 259 } 260 } 261 ~Cipher() 262 { 263 if (ctx_) EVP_CIPHER_CTX_free(ctx_); 264 } 265 /* 266 @note don't use padding = true 267 */ 268 void setup(Mode mode, const std::string& key, const std::string& iv, bool padding = false) 269 { 270 const int keyLen = static_cast<int>(key.size()); 271 const int expectedKeyLen = EVP_CIPHER_key_length(cipher_); 272 if (keyLen != expectedKeyLen) { 273 throw cybozu::Exception("crypto:Cipher:setup:keyLen") << keyLen << expectedKeyLen; 274 } 275 276 int ret = EVP_CipherInit_ex(ctx_, cipher_, NULL, cybozu::cast<const uint8_t*>(key.c_str()), cybozu::cast<const uint8_t*>(iv.c_str()), mode == Encoding ? 1 : 0); 277 if (ret != 1) { 278 throw cybozu::Exception("crypto:Cipher:setup:EVP_CipherInit_ex") << ret; 279 } 280 ret = EVP_CIPHER_CTX_set_padding(ctx_, padding ? 1 : 0); 281 if (ret != 1) { 282 throw cybozu::Exception("crypto:Cipher:setup:EVP_CIPHER_CTX_set_padding") << ret; 283 } 284 /* 285 const int ivLen = static_cast<int>(iv.size()); 286 const int expectedIvLen = EVP_CIPHER_CTX_iv_length(&ctx_); 287 if (ivLen != expectedIvLen) { 288 throw cybozu::Exception("crypto:Cipher:setup:ivLen") << ivLen << expectedIvLen; 289 } 290 */ 291 } 292 /* 293 the size of outBuf must be larger than inBufSize + blockSize 294 @retval positive or 0 : writeSize(+blockSize) 295 @retval -1 : error 296 */ 297 int update(char *outBuf, const char *inBuf, int inBufSize) 298 { 299 int outLen = 0; 300 int ret = EVP_CipherUpdate(ctx_, cybozu::cast<uint8_t*>(outBuf), &outLen, cybozu::cast<const uint8_t*>(inBuf), inBufSize); 301 if (ret != 1) return -1; 302 return outLen; 303 } 304 /* 305 return -1 if padding 306 @note don't use 307 */ 308 int finalize(char *outBuf) 309 { 310 int outLen = 0; 311 int ret = EVP_CipherFinal_ex(ctx_, cybozu::cast<uint8_t*>(outBuf), &outLen); 312 if (ret != 1) return -1; 313 return outLen; 314 } 315 }; 316 317 } } // cybozu::crypto 318 319 #ifdef __APPLE__ 320 #pragma GCC diagnostic pop 321 #endif