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