Jelajahi Sumber

首次推送

kinve 4 tahun lalu
melakukan
ffd8edbab7
33 mengubah file dengan 5500 tambahan dan 0 penghapusan
  1. TEMPAT SAMPAH
      PC工具/SM2_3_4_CALC/Asist.dll
  2. TEMPAT SAMPAH
      PC工具/SM2_3_4_CALC/SM2_3_4_CALC.exe
  3. 1 0
      README.md
  4. 68 0
      SM2_SM3_SM4_C语言实现/SM2/kdf.h
  5. 785 0
      SM2_SM3_SM4_C语言实现/SM2/sm2.c
  6. 100 0
      SM2_SM3_SM4_C语言实现/SM2/sm2.dsp
  7. 29 0
      SM2_SM3_SM4_C语言实现/SM2/sm2.dsw
  8. 25 0
      SM2_SM3_SM4_C语言实现/SM2/sm2.h
  9. 446 0
      SM2_SM3_SM4_C语言实现/SM2/sm2test.c
  10. 441 0
      SM2_SM3_SM4_C语言实现/SM3/sm3.c
  11. 120 0
      SM2_SM3_SM4_C语言实现/SM3/sm3.h
  12. 45 0
      SM2_SM3_SM4_C语言实现/SM3/sm3test.c
  13. 98 0
      SM2_SM3_SM4_C语言实现/SM3/sm3test.dsp
  14. 29 0
      SM2_SM3_SM4_C语言实现/SM3/sm3test.dsw
  15. 344 0
      SM2_SM3_SM4_C语言实现/SM4/sm4.c
  16. 96 0
      SM2_SM3_SM4_C语言实现/SM4/sm4.dsp
  17. 29 0
      SM2_SM3_SM4_C语言实现/SM4/sm4.dsw
  18. 75 0
      SM2_SM3_SM4_C语言实现/SM4/sm4.h
  19. 45 0
      SM2_SM3_SM4_C语言实现/SM4/sm4test.c
  20. 382 0
      SM2_SM3_SM4_C语言实现/SM4/sms4.c
  21. 105 0
      java源码+jar包/com/security/cipher/sm/Cipher.java
  22. 182 0
      java源码+jar包/com/security/cipher/sm/SM2.java
  23. 25 0
      java源码+jar包/com/security/cipher/sm/SM2Result.java
  24. 289 0
      java源码+jar包/com/security/cipher/sm/SM2Utils.java
  25. 359 0
      java源码+jar包/com/security/cipher/sm/SM3.java
  26. 145 0
      java源码+jar包/com/security/cipher/sm/SM3Digest.java
  27. 344 0
      java源码+jar包/com/security/cipher/sm/SM4.java
  28. 211 0
      java源码+jar包/com/security/cipher/sm/SM4Utils.java
  29. 17 0
      java源码+jar包/com/security/cipher/sm/SM4_Context.java
  30. 662 0
      java源码+jar包/com/security/cipher/sm/Util.java
  31. TEMPAT SAMPAH
      java源码+jar包/libs/bcprov-jdk14-143.jar
  32. TEMPAT SAMPAH
      java源码+jar包/libs/sun.misc.BASE64Decoder.jar
  33. 3 0
      java源码+jar包/说明.txt

TEMPAT SAMPAH
PC工具/SM2_3_4_CALC/Asist.dll


TEMPAT SAMPAH
PC工具/SM2_3_4_CALC/SM2_3_4_CALC.exe


+ 1 - 0
README.md

@@ -0,0 +1 @@
+国密SM2-SM4算法

+ 68 - 0
SM2_SM3_SM4_C语言实现/SM2/kdf.h

@@ -0,0 +1,68 @@
+
+#include <memory.h>
+#include <openssl/evp.h>
+
+// ----- KDF FUNCTIONS START -----
+//typedef void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen);
+
+int x9_63_kdf(const EVP_MD *md, const unsigned char *share, size_t sharelen, size_t keylen, unsigned char *outkey)
+{
+	int ret = 0;
+
+	EVP_MD_CTX ctx;
+	unsigned char counter[4] = {0, 0, 0, 1};
+	unsigned char dgst[EVP_MAX_MD_SIZE];
+	unsigned int dgstlen;
+	int rlen = (int)keylen;
+	unsigned char * pp;
+
+	pp = outkey;
+
+	if (keylen > (size_t)EVP_MD_size(md)*255)
+	{
+		fprintf(stderr, "%s(%d):", __FILE__, __LINE__);
+		goto end;
+	}
+
+	while (rlen > 0)
+	{
+		EVP_MD_CTX_init(&ctx);
+
+		if (!EVP_DigestInit(&ctx, md))
+		{
+			fprintf(stderr, "%s(%d):", __FILE__, __LINE__);
+			goto end;
+		}
+
+		if (!EVP_DigestUpdate(&ctx, share, sharelen))
+		{
+			fprintf(stderr, "%s(%d):", __FILE__, __LINE__);
+			goto end;
+		}
+		if (!EVP_DigestUpdate(&ctx, counter, 4))
+		{
+			fprintf(stderr, "%s(%d):", __FILE__, __LINE__);
+			goto end;
+		}
+		if (!EVP_DigestFinal(&ctx, dgst, &dgstlen))
+		{
+			fprintf(stderr, "%s(%d):", __FILE__, __LINE__);
+			goto end;
+		}
+
+		EVP_MD_CTX_cleanup(&ctx);
+
+		memcpy(pp, dgst, keylen>=dgstlen ? dgstlen:keylen);
+
+		rlen -= dgstlen;
+		pp += dgstlen;
+		counter[3]++;
+	}
+
+	ret = 1;
+
+end:
+	return ret;
+}
+
+// ----- KDF FUNCTIONS END -----

+ 785 - 0
SM2_SM3_SM4_C语言实现/SM2/sm2.c

@@ -0,0 +1,785 @@
+// \file:sm2.c
+//SM2 Algorithm
+//2011-11-10
+//author:goldboar
+//email:[email protected]
+//depending:opnessl library
+
+//SM2 Standards: http://www.oscca.gov.cn/News/201012/News_1197.htm
+
+#include <limits.h>
+#include <openssl/ec.h>
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ecdh.h>
+#include "kdf.h"
+
+#define  NID_X9_62_prime_field 406
+static void BNPrintf(BIGNUM* bn)
+{
+	char *p=NULL;
+	p=BN_bn2hex(bn);
+	printf("%s",p);
+	OPENSSL_free(p);
+}
+
+
+static int sm2_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kp, BIGNUM **rp)
+{
+	BN_CTX   *ctx = NULL;
+	BIGNUM	 *k = NULL, *r = NULL, *order = NULL, *X = NULL;
+	EC_POINT *tmp_point=NULL;
+	const EC_GROUP *group;
+	int 	 ret = 0;
+
+	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER);
+		return 0;
+	}
+
+	if (ctx_in == NULL) 
+	{
+		if ((ctx = BN_CTX_new()) == NULL)
+		{
+			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_MALLOC_FAILURE);
+			return 0;
+		}
+	}
+	else
+		ctx = ctx_in;
+
+	k     = BN_new();	/* this value is later returned in *kp */
+	r     = BN_new();	/* this value is later returned in *rp */
+	order = BN_new();
+	X     = BN_new();
+	if (!k || !r || !order || !X)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if ((tmp_point = EC_POINT_new(group)) == NULL)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+		goto err;
+	}
+	if (!EC_GROUP_get_order(group, order, ctx))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+		goto err;
+	}
+	
+	do
+	{
+		/* get random k */	
+		do
+			if (!BN_rand_range(k, order))
+			{
+				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);	
+				goto err;
+			}
+		while (BN_is_zero(k));
+
+		/* compute r the x-coordinate of generator * k */
+		if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
+			goto err;
+		}
+		if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
+		{
+			if (!EC_POINT_get_affine_coordinates_GFp(group,
+				tmp_point, X, NULL, ctx))
+			{
+				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB);
+				goto err;
+			}
+		}
+		else /* NID_X9_62_characteristic_two_field */
+		{
+			if (!EC_POINT_get_affine_coordinates_GF2m(group,
+				tmp_point, X, NULL, ctx))
+			{
+				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,ERR_R_EC_LIB);
+				goto err;
+			}
+		}
+		if (!BN_nnmod(r, X, order, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
+			goto err;
+		}
+	}
+	while (BN_is_zero(r));
+
+	/* compute the inverse of k */
+// 	if (!BN_mod_inverse(k, k, order, ctx))
+// 	{
+// 		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
+// 		goto err;	
+// 	}
+	/* clear old values if necessary */
+	if (*rp != NULL)
+		BN_clear_free(*rp);
+	if (*kp != NULL) 
+		BN_clear_free(*kp);
+	/* save the pre-computed values  */
+	*rp = r;
+	*kp = k;
+	ret = 1;
+err:
+	if (!ret)
+	{
+		if (k != NULL) BN_clear_free(k);
+		if (r != NULL) BN_clear_free(r);
+	}
+	if (ctx_in == NULL) 
+		BN_CTX_free(ctx);
+	if (order != NULL)
+		BN_free(order);
+	if (tmp_point != NULL) 
+		EC_POINT_free(tmp_point);
+	if (X)
+		BN_clear_free(X);
+	return(ret);
+}
+
+
+static ECDSA_SIG *sm2_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_k, const BIGNUM *in_r, EC_KEY *eckey)
+{
+	int     ok = 0, i;
+	BIGNUM *k=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL;
+	const BIGNUM *ck;
+	BN_CTX     *ctx = NULL;
+	const EC_GROUP   *group;
+	ECDSA_SIG  *ret;
+	//ECDSA_DATA *ecdsa;
+	const BIGNUM *priv_key;
+    BIGNUM *r,*x=NULL,*a=NULL;	//new added
+	//ecdsa    = ecdsa_check(eckey);
+	group    = EC_KEY_get0_group(eckey);
+	priv_key = EC_KEY_get0_private_key(eckey);
+	
+	if (group == NULL || priv_key == NULL /*|| ecdsa == NULL*/)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
+		return NULL;
+	}
+
+	ret = ECDSA_SIG_new();
+	if (!ret)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	s = ret->s;
+	r = ret->r;
+
+	if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
+		(tmp = BN_new()) == NULL || (m = BN_new()) == NULL || 
+		(x = BN_new()) == NULL || (a = BN_new()) == NULL)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (!EC_GROUP_get_order(group, order, ctx))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+		goto err;
+	}
+// 	for(i=0;i<dgst_len;i++)
+// 		printf("%02X",dgst[i]);
+//  	printf("\n");
+	i = BN_num_bits(order);
+	/* Need to truncate digest if it is too long: first truncate whole
+	 * bytes.
+	 */
+	if (8 * dgst_len > i)
+		dgst_len = (i + 7)/8;
+	if (!BN_bin2bn(dgst, dgst_len, m))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+		goto err;
+	}
+	/* If still too long truncate remaining bits with a shift */
+	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+		goto err;
+	}
+// 	fprintf(stdout,"m: ");
+// 	BNPrintf(m);
+// 	fprintf(stdout,"\n");
+	do
+	{
+		if (in_k == NULL || in_r == NULL)
+		{
+			if (!sm2_sign_setup(eckey, ctx, &k, &x))
+			{
+				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
+				goto err;
+			}
+			ck = k;
+		}
+		else
+		{
+			ck  = in_k;
+			if (BN_copy(x, in_r) == NULL)
+			{
+				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
+				goto err;
+			}
+		}
+		
+		//r=(e+x1) mod n
+		if (!BN_mod_add_quick(r, m, x, order))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+			goto err;
+		}
+
+// 	    BNPrintf(r);
+// 		fprintf(stdout,"\n");
+
+		if(BN_is_zero(r) )
+			continue;
+
+		BN_add(tmp,r,ck);
+		if(BN_ucmp(tmp,order) == 0)
+			continue;
+		
+		if (!BN_mod_mul(tmp, priv_key, r, order, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+			goto err;
+		}
+		if (!BN_mod_sub_quick(s, ck, tmp, order))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+			goto err;
+		}
+		BN_one(a);
+		//BN_set_word((a),1);
+
+		if (!BN_mod_add_quick(tmp, priv_key, a, order))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+			goto err;
+		}
+		/* compute the inverse of 1+dA */
+		if (!BN_mod_inverse(tmp, tmp, order, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
+			goto err;	
+		}
+// 		BNPrintf(tmp);
+// 		fprintf(stdout,"\n");
+
+		if (!BN_mod_mul(s, s, tmp, order, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
+			goto err;
+		}
+		if (BN_is_zero(s))
+		{
+			/* if k and r have been supplied by the caller
+			 * don't to generate new k and r values */
+			if (in_k != NULL && in_r != NULL)
+			{
+				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES);
+				goto err;
+			}
+		}
+		else
+			/* s != 0 => we have a valid signature */
+			break;
+	}
+	while (1);
+
+	ok = 1;
+err:
+	if (!ok)
+	{
+		ECDSA_SIG_free(ret);
+		ret = NULL;
+	}
+	if (ctx)
+		BN_CTX_free(ctx);
+	if (m)
+		BN_clear_free(m);
+	if (tmp)
+		BN_clear_free(tmp);
+	if (order)
+		BN_free(order);
+	if (k)
+		BN_clear_free(k);
+	if (x)
+		BN_clear_free(x);
+	if (a)
+		BN_clear_free(a);
+	return ret;
+}
+
+static int sm2_do_verify(const unsigned char *dgst, int dgst_len,
+		const ECDSA_SIG *sig, EC_KEY *eckey)
+{
+	int ret = -1, i;
+	BN_CTX   *ctx;
+	BIGNUM   *order, *R,  *m, *X,*t;
+	EC_POINT *point = NULL;
+	const EC_GROUP *group;
+	const EC_POINT *pub_key;
+
+	/* check input values */
+	if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL ||
+	    (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS);
+		return -1;
+	}
+
+	ctx = BN_CTX_new();
+	if (!ctx)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
+		return -1;
+	}
+	BN_CTX_start(ctx);
+	order = BN_CTX_get(ctx);	
+	R    = BN_CTX_get(ctx);
+	t    = BN_CTX_get(ctx);
+	m     = BN_CTX_get(ctx);
+	X     = BN_CTX_get(ctx);
+	if (!X)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+		goto err;
+	}
+	
+	if (!EC_GROUP_get_order(group, order, ctx))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+		goto err;
+	}
+
+	if (BN_is_zero(sig->r)          || BN_is_negative(sig->r) || 
+	    BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s)  ||
+	    BN_is_negative(sig->s)      || BN_ucmp(sig->s, order) >= 0)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
+		ret = 0;	/* signature is invalid */
+		goto err;
+	}
+
+	//t =(r+s) mod n
+	if (!BN_mod_add_quick(t, sig->s, sig->r,order))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+		goto err;
+	}
+	if (BN_is_zero(t))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE);
+		ret = 0;	/* signature is invalid */
+		goto err;
+	}
+	
+	//point = s*G+t*PA
+	if ((point = EC_POINT_new(group)) == NULL)
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!EC_POINT_mul(group, point, sig->s, pub_key, t, ctx))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+		goto err;
+	}
+	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field)
+	{
+		if (!EC_POINT_get_affine_coordinates_GFp(group,
+			point, X, NULL, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+			goto err;
+		}
+	}
+	else /* NID_X9_62_characteristic_two_field */
+	{
+		if (!EC_POINT_get_affine_coordinates_GF2m(group,
+			point, X, NULL, ctx))
+		{
+			ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB);
+			goto err;
+		}
+	}
+ 	
+	i = BN_num_bits(order);
+	/* Need to truncate digest if it is too long: first truncate whole
+	 * bytes.
+	 */
+	if (8 * dgst_len > i)
+		dgst_len = (i + 7)/8;
+	if (!BN_bin2bn(dgst, dgst_len, m))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+		goto err;
+	}
+	/* If still too long truncate remaining bits with a shift */
+	if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+		goto err;
+	}
+
+	/* R = m + X mod order */
+	if (!BN_mod_add_quick(R, m, X, order))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB);
+		goto err;
+	}
+
+	/*  if the signature is correct R is equal to sig->r */
+	ret = (BN_ucmp(R, sig->r) == 0);
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	if (point)
+		EC_POINT_free(point);
+	return ret;
+}
+
+
+EC_POINT *sm2_compute_key(const EC_POINT *b_pub_key_r, const EC_POINT *b_pub_key, const BIGNUM *a_r,EC_KEY *a_eckey)
+{
+	BN_CTX *ctx;
+	EC_POINT *tmp=NULL;
+	BIGNUM *x=NULL, *y=NULL, *order=NULL,*z=NULL;
+	const BIGNUM *priv_key;
+	const EC_GROUP* group;
+	EC_POINT *ret= NULL;
+/*	size_t buflen, len;*/
+	unsigned char *buf=NULL;
+	int i, j;
+	//char *p=NULL;
+	BIGNUM *x1,*x2,*t,*h;
+
+	if ((ctx = BN_CTX_new()) == NULL) goto err;
+	BN_CTX_start(ctx);
+	x = BN_CTX_get(ctx);
+	y = BN_CTX_get(ctx);
+	order = BN_CTX_get(ctx);
+	z = BN_CTX_get(ctx);
+	x1 = BN_CTX_get(ctx);
+	x2 = BN_CTX_get(ctx);
+	t = BN_CTX_get(ctx);
+	h = BN_CTX_get(ctx);
+
+	
+	priv_key = EC_KEY_get0_private_key(a_eckey);
+	if (priv_key == NULL)
+	{
+		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE);
+		goto err;
+	}
+
+	group = EC_KEY_get0_group(a_eckey);
+	if ((tmp=EC_POINT_new(group)) == NULL)
+	{
+		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+
+	if (!EC_POINT_mul(group, tmp, a_r, NULL, NULL, ctx)) 
+	{
+		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+		goto err;
+	}
+	
+	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) 
+	{
+		if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) 
+		{
+			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+			goto err;
+		}
+	}
+	else
+	{
+		if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, NULL, ctx)) 
+		{
+			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+			goto err;
+		}
+	}
+	
+	if (!EC_GROUP_get_order(group, order, ctx))
+	{
+		ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
+		goto err;
+	}
+		
+	i = BN_num_bits(order);
+	j = i/2 -1;
+	BN_mask_bits(x,j);
+	BN_set_word(y,2);
+	BN_set_word(z,j);
+	BN_exp(y,y,z,ctx);
+	BN_add(x1,x,y);
+	
+// 	fprintf(stdout,"X1=: ");
+// 	BNPrintf(x1);
+// 	fprintf(stdout,"\n");
+
+	BN_mod_mul(t,x1,a_r,order,ctx);
+	BN_mod_add_quick(t,t,priv_key,order);
+// 
+// 	fprintf(stdout,"ta=: ");
+// 	BNPrintf(t);
+// 	fprintf(stdout,"\n");
+
+	
+	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) 
+	{
+		if (!EC_POINT_get_affine_coordinates_GFp(group, b_pub_key_r, x, NULL, ctx)) 
+		{
+			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+			goto err;
+		}
+	}
+	else
+	{
+		if (!EC_POINT_get_affine_coordinates_GF2m(group, b_pub_key_r, x, NULL, ctx)) 
+		{
+			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+			goto err;
+		}
+	}
+
+	i = BN_num_bits(order);
+	j = i/2 -1;
+	BN_mask_bits(x,j);
+	BN_set_word(y,2);
+	BN_set_word(z,j);
+	BN_exp(y,y,z,ctx);
+	BN_add(x2,x,y);
+	
+// 	fprintf(stdout,"X2=: ");
+// 	BNPrintf(x2);
+// 	fprintf(stdout,"\n");
+
+
+	//x2*Rb+Pb;
+	if (!EC_POINT_mul(group, tmp, NULL,b_pub_key_r,x2,ctx) )
+	{
+		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+		goto err;
+	}
+	if ((ret=EC_POINT_new(group)) == NULL)
+	{
+		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
+		goto err;
+	}
+	if (!EC_POINT_add(group, ret, b_pub_key, tmp, ctx))
+	{
+		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+		goto err;
+	}
+	if (!EC_POINT_get_affine_coordinates_GFp(group,ret, x, y, ctx)) 
+	{
+		goto err;
+	}
+// 	fprintf(stdout, "\nTesting x2*Rb+Pb Key Point\n     x = 0x");
+// 	BNPrintf(x);
+// 	fprintf(stdout, "\n     y = 0x");
+// 	BNPrintf( y);
+// 	fprintf(stdout, "\n");
+// 	
+	if(!EC_GROUP_get_cofactor(group, h, ctx))
+	{
+		goto err;
+	}
+    BN_mul(t,t,h,ctx);
+
+	//h*t*(x2*Rb+Pb)
+	if (!EC_POINT_mul(group, ret, NULL,ret,t,ctx) ) 
+	{
+		goto err;
+	}
+	if (!EC_POINT_get_affine_coordinates_GFp(group,ret, x, y, ctx)) 
+	{
+		goto err;
+	}
+// 	fprintf(stdout, "\nTesting ret Key Point\n     x = 0x");
+// 	BNPrintf(x);
+// 	fprintf(stdout, "\n     y = 0x");
+// 	BNPrintf( y);
+// 	fprintf(stdout, "\n");
+
+	
+err:
+	if (tmp) EC_POINT_free(tmp);
+	if (ctx) BN_CTX_end(ctx);
+	if (ctx) BN_CTX_free(ctx);
+	if (buf) OPENSSL_free(buf);
+	return(ret);
+}
+
+/** SM2_sign_setup
+* precompute parts of the signing operation. 
+* \param eckey pointer to the EC_KEY object containing a private EC key
+* \param ctx  pointer to a BN_CTX object (may be NULL)
+* \param k pointer to a BIGNUM pointer for the inverse of k
+* \param rp   pointer to a BIGNUM pointer for x coordinate of k * generator
+* \return 1 on success and 0 otherwise
+ */
+
+int  SM2_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
+{
+// 	ECDSA_DATA *ecdsa = ecdsa_check(eckey);
+// 	if (ecdsa == NULL)
+// 		return 0;
+	return SM2_sign_setup(eckey, ctx_in, kinvp, rp); 
+}
+/** SM2_sign_ex
+ * computes ECDSA signature of a given hash value using the supplied
+ * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+ * \param type this parameter is ignored
+ * \param dgst pointer to the hash value to sign
+ * \param dgstlen length of the hash value
+ * \param sig buffer to hold the DER encoded signature
+ * \param siglen pointer to the length of the returned signature
+ * \param k optional pointer to a pre-computed inverse k
+ * \param rp optional pointer to the pre-computed rp value (see 
+ *        ECDSA_sign_setup
+ * \param eckey pointer to the EC_KEY object containing a private EC key
+ * \return 1 on success and 0 otherwise
+ */
+int	  SM2_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char 
+	*sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, 
+	EC_KEY *eckey)
+{
+	ECDSA_SIG *s;
+	RAND_seed(dgst, dlen);
+	s = sm2_do_sign(dgst, dlen, kinv, r, eckey);
+	if (s == NULL)
+	{
+		*siglen=0;
+		return 0;
+	}
+	*siglen = i2d_ECDSA_SIG(s, &sig);
+	ECDSA_SIG_free(s);
+	return 1;
+}
+
+/** SM2_sign
+  * computes ECDSA signature of a given hash value using the supplied
+  * private key (note: sig must point to ECDSA_size(eckey) bytes of memory).
+  * \param type this parameter is ignored
+  * \param dgst pointer to the hash value to sign
+  * \param dgstlen length of the hash value
+  * \param sig buffer to hold the DER encoded signature
+  * \param siglen pointer to the length of the returned signature
+  * \param eckey pointer to the EC_KEY object containing a private EC key
+  * \return 1 on success and 0 otherwise
+ */
+int	  SM2_sign(int type, const unsigned char *dgst, int dlen, unsigned char 
+		*sig, unsigned int *siglen, EC_KEY *eckey)
+{
+
+	return SM2_sign_ex(type, dgst, dlen, sig, siglen, NULL, NULL, eckey);
+
+}
+
+
+/** SM2_verify
+  * verifies that the given signature is valid ECDSA signature
+  * of the supplied hash value using the specified public key.
+  * \param type this parameter is ignored
+  * \param dgst pointer to the hash value 
+  * \param dgstlen length of the hash value
+  * \param sig  pointer to the DER encoded signature
+  * \param siglen length of the DER encoded signature
+  * \param eckey pointer to the EC_KEY object containing a public EC key
+  * \return 1 if the signature is valid, 0 if the signature is invalid and -1 on error
+  */
+int SM2_verify(int type, const unsigned char *dgst, int dgst_len,
+		const unsigned char *sigbuf, int sig_len, EC_KEY *eckey)
+ {
+	ECDSA_SIG *s;
+	int ret=-1;
+
+	s = ECDSA_SIG_new();
+	if (s == NULL) return(ret);
+	if (d2i_ECDSA_SIG(&s, &sigbuf, sig_len) == NULL) goto err;
+	ret=sm2_do_verify(dgst, dgst_len, s, eckey);
+err:
+	ECDSA_SIG_free(s);
+	return(ret);
+}
+
+int SM2_DH_key(const EC_GROUP * group, const EC_POINT *b_pub_key_r, const EC_POINT *b_pub_key, const BIGNUM *a_r,EC_KEY *a_eckey,
+			   unsigned char *outkey,size_t keylen)
+{
+	EC_POINT *dhpoint = NULL;
+	BN_CTX * ctx;
+	EC_POINT *P;
+	BIGNUM *x, *y;
+	int ret = 0;
+	unsigned char in[128];
+	int inlen;
+	int len;
+
+	P = EC_POINT_new(group);
+	if (!P ) goto err;
+	ctx = BN_CTX_new();
+	x = BN_new();
+	y = BN_new();
+	if (!x || !y ) goto err;
+	
+	dhpoint = sm2_compute_key(b_pub_key_r,b_pub_key,a_r,a_eckey);
+
+	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) 
+	{
+		if (!EC_POINT_get_affine_coordinates_GFp(group,dhpoint, x, y, ctx))
+		{
+			fprintf(stdout, " failed\n");
+			goto err;
+		}
+	}
+	else
+	{
+		if (!EC_POINT_get_affine_coordinates_GF2m(group,dhpoint, x, y, ctx)) 
+		{
+			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
+			goto err;
+		}
+	}
+
+// 	if (!EC_POINT_get_affine_coordinates_GFp(group,dhpoint, x, y, ctx))
+// 	{
+// 		fprintf(stdout, " failed\n");
+// 		goto err;
+// 	}
+	fprintf(stdout, "\nTesting DH Point\n     Xv = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     Yv = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+
+	len = BN_bn2bin(x,in);
+	inlen =BN_bn2bin(y,in+len);
+	inlen = inlen + len;
+	ret = x9_63_kdf(EVP_sha256(),in,inlen,keylen,outkey);
+	//ret  = 1;
+err:
+	EC_POINT_free(P);
+	EC_POINT_free(dhpoint);
+	BN_CTX_free(ctx);
+
+	return ret;
+}
+

+ 100 - 0
SM2_SM3_SM4_C语言实现/SM2/sm2.dsp

@@ -0,0 +1,100 @@
+# Microsoft Developer Studio Project File - Name="sm2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=sm2 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "sm2.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "sm2.mak" CFG="sm2 - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "sm2 - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "sm2 - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "sm2 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x804 /d "NDEBUG"
+# ADD RSC /l 0x804 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "sm2 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0x804 /d "_DEBUG"
+# ADD RSC /l 0x804 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "sm2 - Win32 Release"
+# Name "sm2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\kdf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm2.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm2test.c
+# End Source File
+# End Target
+# End Project

+ 29 - 0
SM2_SM3_SM4_C语言实现/SM2/sm2.dsw

@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sm2"=.\sm2.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

+ 25 - 0
SM2_SM3_SM4_C语言实现/SM2/sm2.h

@@ -0,0 +1,25 @@
+// \file:sm2.h
+//SM2 Algorithm
+//2011-11-09
+//author:goldboar
+//email:[email protected]
+//comment:2011-11-10 sm2-sign-verify sm2-dh
+
+//SM2_sign_setup
+int SM2_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
+
+//SM2_sign_ex
+int	SM2_sign_ex(int type, const unsigned char *dgst, int dlen, unsigned char 
+	*sig, unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *eckey);
+
+//SM2_sign
+int	SM2_sign(int type, const unsigned char *dgst, int dlen, unsigned char 
+		*sig, unsigned int *siglen, EC_KEY *eckey);
+
+//SM2_verify
+int SM2_verify(int type, const unsigned char *dgst, int dgst_len,
+		const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
+
+//SM2 DH, comupting shared point
+int SM2_DH_key(const EC_GROUP * group,const EC_POINT *b_pub_key_r, const EC_POINT *b_pub_key, const BIGNUM *a_r,EC_KEY *a_eckey,
+			   unsigned char *outkey,size_t keylen);

+ 446 - 0
SM2_SM3_SM4_C语言实现/SM2/sm2test.c

@@ -0,0 +1,446 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <openssl/bn.h>
+#include <openssl/ec.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ecdh.h>
+#include "sm2.h"
+
+
+#pragma comment(lib,"libeay32.lib")
+
+#define ABORT do { \
+	fflush(stdout); \
+	fprintf(stderr, "%s:%d: ABORT\n", __FILE__, __LINE__); \
+	ERR_print_errors_fp(stderr); \
+	exit(1); \
+} while (0)
+
+static const char rnd_seed[] = "string to make the random number generator think it has entropy";
+
+void BNPrintf(BIGNUM* bn)
+{
+	char *p=NULL;
+	p=BN_bn2hex(bn);
+	printf("%s",p);
+	OPENSSL_free(p);
+}
+
+
+int SM2_Test_Vecotor()
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *p, *a, *b;
+	EC_GROUP *group;
+	EC_POINT *P, *Q, *R;
+	BIGNUM *x, *y, *z;
+	EC_KEY	*eckey = NULL;
+	unsigned char	digest[20];
+	unsigned char	*signature = NULL; 
+	int	sig_len;
+
+
+	CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+	ERR_load_crypto_strings();
+	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
+	
+	ctx = BN_CTX_new();
+	if (!ctx) ABORT;
+
+	/* Curve SM2 (Chinese National Algorithm) */
+	//http://www.oscca.gov.cn/News/201012/News_1197.htm
+	p = BN_new();
+	a = BN_new();
+	b = BN_new();
+	if (!p || !a || !b) ABORT;
+	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
+ 	                                             * so that the library gets to choose the EC_METHOD */
+	if (!group) ABORT;
+	
+	if (!BN_hex2bn(&p, "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498")) ABORT;
+	if (!BN_hex2bn(&b, "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	P = EC_POINT_new(group);
+	Q = EC_POINT_new(group);
+	R = EC_POINT_new(group);
+	if (!P || !Q || !R) ABORT;
+
+	x = BN_new();
+	y = BN_new();
+	z = BN_new();
+	if (!x || !y || !z) ABORT;
+
+	// sm2 testing P256 Vetor
+	// p£º8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3
+	// a£º787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498
+	// b£º63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A
+	// xG 421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D
+	// yG 0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2
+	// n: 8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7
+
+	if (!BN_hex2bn(&x, "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+	
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nChinese sm2 algorithm test -- Generator:\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+	
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 256) ABORT;
+	fprintf(stdout, " ok\n");
+	
+	fprintf(stdout, "verify group order ...");
+	fflush(stdout);
+	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
+	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
+	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
+ 	fflush(stdout);
+	fprintf(stdout, " ok\n");
+
+	//testing ECDSA for SM2
+	/* create new ecdsa key */
+	if ((eckey = EC_KEY_new()) == NULL)
+		goto builtin_err;
+	if (EC_KEY_set_group(eckey, group) == 0)
+	{
+		fprintf(stdout," failed\n");
+		goto builtin_err;
+	}
+	/* create key */
+	if (!EC_KEY_generate_key(eckey))
+	{
+		fprintf(stdout," failed\n");
+		goto builtin_err;
+	}
+	/* check key */
+	if (!EC_KEY_check_key(eckey))
+	{
+		fprintf(stdout," failed\n");
+		goto builtin_err;
+	}
+	/* create signature */
+	sig_len = ECDSA_size(eckey);
+	fprintf(stdout,"Siglength is: %d \n",sig_len);
+	if (!RAND_pseudo_bytes(digest, 20))
+	{
+		fprintf(stdout," failed\n");
+		goto builtin_err;
+	}
+	if ((signature = OPENSSL_malloc(sig_len)) == NULL)
+		goto builtin_err;
+	if (!SM2_sign(0, digest, 20, signature, &sig_len, eckey))
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	fprintf(stdout, "ECSign OK\n");
+	/* verify signature */
+	if (SM2_verify(0, digest, 20, signature, sig_len, eckey) != 1)
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	fprintf(stdout, "ECVerify OK\n");
+	/* cleanup */
+	OPENSSL_free(signature);
+	signature = NULL;
+	EC_KEY_free(eckey);
+	eckey = NULL;
+	
+builtin_err:	
+	
+	EC_POINT_free(P);
+	EC_POINT_free(Q);
+	EC_POINT_free(R);
+	EC_GROUP_free(group);
+	BN_CTX_free(ctx);
+	return 0;
+
+}
+
+int SM2_Test_Vecotor2()
+{
+	BN_CTX *ctx = NULL;
+	BIGNUM *p, *a, *b;
+	EC_GROUP *group;
+	EC_POINT *P, *Q, *R;
+	BIGNUM *x, *y, *z;
+	EC_KEY	*eckey = NULL;
+	unsigned char	*signature;
+	unsigned char	digest[32] = "\xB5\x24\xF5\x52\xCD\x82\xB8\xB0\x28\x47\x6E\x00\x5C\x37\x7F\xB1\x9A\x87\xE6\xFC\x68\x2D\x48\xBB\x5D\x42\xE3\xD9\xB9\xEF\xFE\x76"; 
+	int	sig_len;
+	BIGNUM *kinv, *rp,*order; 
+	ECDSA_SIG *ecsig = ECDSA_SIG_new();
+	EC_POINT * DHPoint = NULL;
+// 	unsigned char *in="123456";
+// 	size_t inlen = 6;
+ 	size_t outlen = 256;
+	unsigned char outkey[256];
+	size_t keylen = 256;
+
+	size_t i;
+
+	CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+	ERR_load_crypto_strings();
+	RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_generate_prime may fail */
+	
+	ctx = BN_CTX_new();
+	if (!ctx) ABORT;
+
+	/* Curve SM2 (Chinese National Algorithm) */
+	//http://www.oscca.gov.cn/News/201012/News_1197.htm
+	p = BN_new();
+	a = BN_new();
+	b = BN_new();
+	if (!p || !a || !b) ABORT;
+	group = EC_GROUP_new(EC_GFp_mont_method()); /* applications should use EC_GROUP_new_curve_GFp
+ 	                                             * so that the library gets to choose the EC_METHOD */
+	if (!group) ABORT;
+	
+	if (!BN_hex2bn(&p, "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3")) ABORT;
+	if (1 != BN_is_prime_ex(p, BN_prime_checks, ctx, NULL)) ABORT;
+	if (!BN_hex2bn(&a, "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498")) ABORT;
+	if (!BN_hex2bn(&b, "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A")) ABORT;
+	if (!EC_GROUP_set_curve_GFp(group, p, a, b, ctx)) ABORT;
+
+	P = EC_POINT_new(group);
+	Q = EC_POINT_new(group);
+	R = EC_POINT_new(group);
+	if (!P || !Q || !R) ABORT;
+
+	x = BN_new();
+	y = BN_new();
+	z = BN_new();
+	if (!x || !y || !z) ABORT;
+
+	// sm2 testing P256 Vetor
+	// p£º8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3
+	// a£º787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498
+	// b£º63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A
+	// xG 421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D
+	// yG 0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2
+	// n: 8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7
+
+	if (!BN_hex2bn(&x, "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D")) ABORT;
+	if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT;
+	if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT;
+	if (!BN_hex2bn(&z, "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7")) ABORT;
+	if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT;
+	
+	if (!EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nChinese sm2 algorithm test -- Generator:\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+	/* G_y value taken from the standard: */
+	if (!BN_hex2bn(&z, "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2")) ABORT;
+	if (0 != BN_cmp(y, z)) ABORT;
+	
+	fprintf(stdout, "verify degree ...");
+	if (EC_GROUP_get_degree(group) != 256) ABORT;
+	fprintf(stdout, " ok\n");
+	
+	fprintf(stdout, "verify group order ...");
+	fflush(stdout);
+	if (!EC_GROUP_get_order(group, z, ctx)) ABORT;
+	if (!EC_GROUP_precompute_mult(group, ctx)) ABORT;
+	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_is_at_infinity(group, Q)) ABORT;
+ 	fflush(stdout);
+	fprintf(stdout, " ok\n");
+
+	//testing ECDSA for SM2
+	/* create new ecdsa key */
+	if ((eckey = EC_KEY_new()) == NULL)
+		goto builtin_err;
+	if (EC_KEY_set_group(eckey, group) == 0)
+	{
+		fprintf(stdout," failed\n");
+		goto builtin_err;
+	}
+	/* create key */
+	if (!BN_hex2bn(&z, "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263")) ABORT;
+	if (!EC_POINT_mul(group,P, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_get_affine_coordinates_GFp(group,P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nTesting ECKey Point\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+	EC_KEY_set_private_key(eckey,z);
+	EC_KEY_set_public_key(eckey, P);
+
+	/* check key */
+	if (!EC_KEY_check_key(eckey))
+	{
+		fprintf(stdout," failed\n");
+		goto builtin_err;
+	}
+
+	/* create signature */
+	sig_len = ECDSA_size(eckey);
+ 	//fprintf(stdout,"Siglength is: %d \n",sig_len);
+	if ((signature = OPENSSL_malloc(sig_len)) == NULL)
+		goto builtin_err;
+
+	rp    = BN_new();
+	kinv  = BN_new();
+	order = BN_new();
+
+	if (!BN_hex2bn(&z, "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F")) ABORT;
+	if (!EC_POINT_mul(group, Q, z, NULL, NULL, ctx))
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	if (!EC_POINT_get_affine_coordinates_GFp(group,Q, x, y, ctx))
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	fprintf(stdout, "\nTesting K Point\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+
+	EC_GROUP_get_order(group, order, ctx);
+	if (!BN_nnmod(rp, x, order, ctx))
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	if (!BN_copy(kinv, z ))
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+
+// 	for(i=0;i<32;i++)
+// 		printf("%02X",digest[i]);
+// 	printf("\n");
+
+	if (!SM2_sign_ex(1, digest, 32, signature, &sig_len, kinv, rp, eckey))
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	fprintf(stdout, "ECSign OK\n");
+
+	/* verify signature */
+	if (SM2_verify(1, digest, 32, signature, sig_len, eckey) != 1)
+	{
+		fprintf(stdout, " failed\n");
+		goto builtin_err;
+	}
+	fprintf(stdout, "ECVerify OK\n     r = 0x");
+	d2i_ECDSA_SIG(&ecsig, &signature, sig_len);
+	BNPrintf(ecsig->r);
+	fprintf(stdout,"\n     s = 0x");
+	BNPrintf(ecsig->s);
+	fprintf(stdout,"\n");
+
+	//testing SM2DH vector
+	/* create key */
+	if (!BN_hex2bn(&z, "6FCBA2EF9AE0AB902BC3BDE3FF915D44BA4CC78F88E2F8E7F8996D3B8CCEEDEE")) ABORT;
+	if (!EC_POINT_mul(group,P, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_get_affine_coordinates_GFp(group,P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nTesting A Key Point\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+	EC_KEY_set_private_key(eckey,z);
+	EC_KEY_set_public_key(eckey, P);
+
+	if (!BN_hex2bn(&z, "5E35D7D3F3C54DBAC72E61819E730B019A84208CA3A35E4C2E353DFCCB2A3B53")) ABORT;
+	if (!EC_POINT_mul(group,Q, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_get_affine_coordinates_GFp(group,Q, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nTesting B Key Point\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+	//EC_KEY_set_private_key(eckey,z);
+	//EC_KEY_set_public_key(eckey, P);
+
+	if (!BN_hex2bn(&z, "33FE21940342161C55619C4A0C060293D543C80AF19748CE176D83477DE71C80")) ABORT;
+	if (!EC_POINT_mul(group,P, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_get_affine_coordinates_GFp(group,P, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nTesting Rb Key Point\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+
+	if (!BN_hex2bn(&z, "83A2C9C8B96E5AF70BD480B472409A9A327257F1EBB73F5B073354B248668563")) ABORT;
+	if (!EC_POINT_mul(group,R, z, NULL, NULL, ctx)) ABORT;
+	if (!EC_POINT_get_affine_coordinates_GFp(group,R, x, y, ctx)) ABORT;
+	fprintf(stdout, "\nTesting Ra Key Point\n     x = 0x");
+	BNPrintf(x);
+	fprintf(stdout, "\n     y = 0x");
+	BNPrintf( y);
+	fprintf(stdout, "\n");
+    
+	SM2_DH_key(group,P, Q, z,eckey,outkey,keylen);
+
+	fprintf(stdout,"\nExchange key --KDF(Xv||Yv)--  :");
+	for(i=0; i<outlen; i++)
+		printf("%02X",outkey[i]);
+	printf("\n");
+
+
+
+builtin_err:	
+	OPENSSL_free(signature);
+	signature = NULL;
+	EC_POINT_free(P);
+	EC_POINT_free(Q);
+	EC_POINT_free(R);
+	EC_POINT_free(DHPoint);
+	EC_KEY_free(eckey);
+	eckey = NULL;
+	EC_GROUP_free(group);
+	BN_CTX_free(ctx);
+	return 0;
+
+}
+
+int main()
+{
+	CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
+	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+	ERR_load_crypto_strings();
+	RAND_seed(rnd_seed, sizeof rnd_seed); 
+	
+	SM2_Test_Vecotor2();
+	
+	
+	CRYPTO_cleanup_all_ex_data();
+	ERR_free_strings();
+	ERR_remove_state(0);
+	CRYPTO_mem_leaks_fp(stderr);
+	
+	return 0;
+
+}

+ 441 - 0
SM2_SM3_SM4_C语言实现/SM3/sm3.c

@@ -0,0 +1,441 @@
+/*
+ * SM3 Hash alogrith 
+ * thanks to Xyssl
+ * author:goldboar
+ * email:[email protected]
+ * 2011-10-26
+ */
+
+//Testing data from SM3 Standards
+//http://www.oscca.gov.cn/News/201012/News_1199.htm 
+// Sample 1
+// Input:"abc"  
+// Output:66c7f0f4 62eeedd9 d1f2d46b dc10e4e2 4167c487 5cf2f7a2 297da02b 8f4ba8e0
+
+// Sample 2 
+// Input:"abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd"
+// Outpuf:debe9ff9 2275b8a1 38604889 c18e5a4d 6fdb70e5 387e5765 293dcba3 9c0c5732
+
+#include "sm3.h"
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
+        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ * SM3 context setup
+ */
+void sm3_starts( sm3_context *ctx )
+{
+    ctx->total[0] = 0;
+    ctx->total[1] = 0;
+
+    ctx->state[0] = 0x7380166F;
+    ctx->state[1] = 0x4914B2B9;
+    ctx->state[2] = 0x172442D7;
+    ctx->state[3] = 0xDA8A0600;
+    ctx->state[4] = 0xA96F30BC;
+    ctx->state[5] = 0x163138AA;
+    ctx->state[6] = 0xE38DEE4D;
+    ctx->state[7] = 0xB0FB0E4E;
+
+}
+
+static void sm3_process( sm3_context *ctx, unsigned char data[64] )
+{
+    unsigned long SS1, SS2, TT1, TT2, W[68],W1[64];
+    unsigned long A, B, C, D, E, F, G, H;
+	unsigned long T[64];
+	unsigned long Temp1,Temp2,Temp3,Temp4,Temp5;
+	int j;
+#ifdef _DEBUG
+	int i;
+#endif
+
+// 	for(j=0; j < 68; j++)
+// 		W[j] = 0;
+// 	for(j=0; j < 64; j++)
+// 		W1[j] = 0;
+	
+	for(j = 0; j < 16; j++)
+		T[j] = 0x79CC4519;
+	for(j =16; j < 64; j++)
+		T[j] = 0x7A879D8A;
+
+    GET_ULONG_BE( W[ 0], data,  0 );
+    GET_ULONG_BE( W[ 1], data,  4 );
+    GET_ULONG_BE( W[ 2], data,  8 );
+    GET_ULONG_BE( W[ 3], data, 12 );
+    GET_ULONG_BE( W[ 4], data, 16 );
+    GET_ULONG_BE( W[ 5], data, 20 );
+    GET_ULONG_BE( W[ 6], data, 24 );
+    GET_ULONG_BE( W[ 7], data, 28 );
+    GET_ULONG_BE( W[ 8], data, 32 );
+    GET_ULONG_BE( W[ 9], data, 36 );
+    GET_ULONG_BE( W[10], data, 40 );
+    GET_ULONG_BE( W[11], data, 44 );
+    GET_ULONG_BE( W[12], data, 48 );
+    GET_ULONG_BE( W[13], data, 52 );
+    GET_ULONG_BE( W[14], data, 56 );
+    GET_ULONG_BE( W[15], data, 60 );
+
+#ifdef _DEBUG 
+	printf("Message with padding:\n");
+	for(i=0; i< 8; i++)
+		printf("%08x ",W[i]);
+	printf("\n");
+	for(i=8; i< 16; i++)
+		printf("%08x ",W[i]);
+	printf("\n");
+#endif
+
+#define FF0(x,y,z) ( (x) ^ (y) ^ (z)) 
+#define FF1(x,y,z) (((x) & (y)) | ( (x) & (z)) | ( (y) & (z)))
+
+#define GG0(x,y,z) ( (x) ^ (y) ^ (z)) 
+#define GG1(x,y,z) (((x) & (y)) | ( (~(x)) & (z)) )
+
+
+#define  SHL(x,n) (((x) & 0xFFFFFFFF) << n)
+#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
+
+#define P0(x) ((x) ^  ROTL((x),9) ^ ROTL((x),17)) 
+#define P1(x) ((x) ^  ROTL((x),15) ^ ROTL((x),23)) 
+
+	for(j = 16; j < 68; j++ )
+	{
+		//W[j] = P1( W[j-16] ^ W[j-9] ^ ROTL(W[j-3],15)) ^ ROTL(W[j - 13],7 ) ^ W[j-6];
+		//Why thd release's result is different with the debug's ?
+		//Below is okay. Interesting, Perhaps VC6 has a bug of Optimizaiton.
+		
+		Temp1 = W[j-16] ^ W[j-9];
+		Temp2 = ROTL(W[j-3],15);
+		Temp3 = Temp1 ^ Temp2;
+		Temp4 = P1(Temp3);
+		Temp5 =  ROTL(W[j - 13],7 ) ^ W[j-6];
+		W[j] = Temp4 ^ Temp5;
+	}
+
+#ifdef _DEBUG 
+	printf("Expanding message W0-67:\n");
+	for(i=0; i<68; i++)
+	{
+		printf("%08x ",W[i]);
+		if(((i+1) % 8) == 0) printf("\n");
+	}
+	printf("\n");
+#endif
+
+	for(j =  0; j < 64; j++)
+	{
+        W1[j] = W[j] ^ W[j+4];
+	}
+
+#ifdef _DEBUG 
+	printf("Expanding message W'0-63:\n");
+	for(i=0; i<64; i++)
+	{
+		printf("%08x ",W1[i]);
+		if(((i+1) % 8) == 0) printf("\n");
+	}
+	printf("\n");
+#endif
+
+    A = ctx->state[0];
+    B = ctx->state[1];
+    C = ctx->state[2];
+    D = ctx->state[3];
+    E = ctx->state[4];
+    F = ctx->state[5];
+    G = ctx->state[6];
+    H = ctx->state[7];
+#ifdef _DEBUG       
+	printf("j     A       B        C         D         E        F        G       H\n");
+	printf("   %08x %08x %08x %08x %08x %08x %08x %08x\n",A,B,C,D,E,F,G,H);
+#endif
+
+	for(j =0; j < 16; j++)
+	{
+		SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7); 
+		SS2 = SS1 ^ ROTL(A,12);
+		TT1 = FF0(A,B,C) + D + SS2 + W1[j];
+		TT2 = GG0(E,F,G) + H + SS1 + W[j];
+		D = C;
+		C = ROTL(B,9);
+		B = A;
+		A = TT1;
+		H = G;
+		G = ROTL(F,19);
+		F = E;
+		E = P0(TT2);
+#ifdef _DEBUG 
+		printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n",j,A,B,C,D,E,F,G,H);
+#endif
+	}
+	
+	for(j =16; j < 64; j++)
+	{
+		SS1 = ROTL((ROTL(A,12) + E + ROTL(T[j],j)), 7); 
+		SS2 = SS1 ^ ROTL(A,12);
+		TT1 = FF1(A,B,C) + D + SS2 + W1[j];
+		TT2 = GG1(E,F,G) + H + SS1 + W[j];
+		D = C;
+		C = ROTL(B,9);
+		B = A;
+		A = TT1;
+		H = G;
+		G = ROTL(F,19);
+		F = E;
+		E = P0(TT2);
+#ifdef _DEBUG 
+		printf("%02d %08x %08x %08x %08x %08x %08x %08x %08x\n",j,A,B,C,D,E,F,G,H);
+#endif	
+	}
+
+    ctx->state[0] ^= A;
+    ctx->state[1] ^= B;
+    ctx->state[2] ^= C;
+    ctx->state[3] ^= D;
+    ctx->state[4] ^= E;
+    ctx->state[5] ^= F;
+    ctx->state[6] ^= G;
+    ctx->state[7] ^= H;
+#ifdef _DEBUG 
+	   printf("   %08x %08x %08x %08x %08x %08x %08x %08x\n",ctx->state[0],ctx->state[1],ctx->state[2],
+		                          ctx->state[3],ctx->state[4],ctx->state[5],ctx->state[6],ctx->state[7]);
+#endif
+}
+
+/*
+ * SM3 process buffer
+ */
+void sm3_update( sm3_context *ctx, unsigned char *input, int ilen )
+{
+    int fill;
+    unsigned long left;
+
+    if( ilen <= 0 )
+        return;
+
+    left = ctx->total[0] & 0x3F;
+    fill = 64 - left;
+
+    ctx->total[0] += ilen;
+    ctx->total[0] &= 0xFFFFFFFF;
+
+    if( ctx->total[0] < (unsigned long) ilen )
+        ctx->total[1]++;
+
+    if( left && ilen >= fill )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, fill );
+        sm3_process( ctx, ctx->buffer );
+        input += fill;
+        ilen  -= fill;
+        left = 0;
+    }
+
+    while( ilen >= 64 )
+    {
+        sm3_process( ctx, input );
+        input += 64;
+        ilen  -= 64;
+    }
+
+    if( ilen > 0 )
+    {
+        memcpy( (void *) (ctx->buffer + left),
+                (void *) input, ilen );
+    }
+}
+
+static const unsigned char sm3_padding[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/*
+ * SM3 final digest
+ */
+void sm3_finish( sm3_context *ctx, unsigned char output[32] )
+{
+    unsigned long last, padn;
+    unsigned long high, low;
+    unsigned char msglen[8];
+
+    high = ( ctx->total[0] >> 29 )
+         | ( ctx->total[1] <<  3 );
+    low  = ( ctx->total[0] <<  3 );
+
+    PUT_ULONG_BE( high, msglen, 0 );
+    PUT_ULONG_BE( low,  msglen, 4 );
+
+    last = ctx->total[0] & 0x3F;
+    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+
+    sm3_update( ctx, (unsigned char *) sm3_padding, padn );
+    sm3_update( ctx, msglen, 8 );
+
+    PUT_ULONG_BE( ctx->state[0], output,  0 );
+    PUT_ULONG_BE( ctx->state[1], output,  4 );
+    PUT_ULONG_BE( ctx->state[2], output,  8 );
+    PUT_ULONG_BE( ctx->state[3], output, 12 );
+    PUT_ULONG_BE( ctx->state[4], output, 16 );
+    PUT_ULONG_BE( ctx->state[5], output, 20 );
+    PUT_ULONG_BE( ctx->state[6], output, 24 );
+    PUT_ULONG_BE( ctx->state[7], output, 28 );
+}
+
+/*
+ * output = SM3( input buffer )
+ */
+void sm3( unsigned char *input, int ilen,
+           unsigned char output[32] )
+{
+    sm3_context ctx;
+
+    sm3_starts( &ctx );
+    sm3_update( &ctx, input, ilen );
+    sm3_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sm3_context ) );
+}
+
+/*
+ * output = SM3( file contents )
+ */
+int sm3_file( char *path, unsigned char output[32] )
+{
+    FILE *f;
+    size_t n;
+    sm3_context ctx;
+    unsigned char buf[1024];
+
+    if( ( f = fopen( path, "rb" ) ) == NULL )
+        return( 1 );
+
+    sm3_starts( &ctx );
+
+    while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
+        sm3_update( &ctx, buf, (int) n );
+
+    sm3_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sm3_context ) );
+
+    if( ferror( f ) != 0 )
+    {
+        fclose( f );
+        return( 2 );
+    }
+
+    fclose( f );
+    return( 0 );
+}
+
+/*
+ * SM3 HMAC context setup
+ */
+void sm3_hmac_starts( sm3_context *ctx, unsigned char *key, int keylen )
+{
+    int i;
+    unsigned char sum[32];
+
+    if( keylen > 64 )
+    {
+        sm3( key, keylen, sum );
+        keylen = 32;
+		//keylen = ( is224 ) ? 28 : 32;
+        key = sum;
+    }
+
+    memset( ctx->ipad, 0x36, 64 );
+    memset( ctx->opad, 0x5C, 64 );
+
+    for( i = 0; i < keylen; i++ )
+    {
+        ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
+        ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
+    }
+
+    sm3_starts( ctx);
+    sm3_update( ctx, ctx->ipad, 64 );
+
+    memset( sum, 0, sizeof( sum ) );
+}
+
+/*
+ * SM3 HMAC process buffer
+ */
+void sm3_hmac_update( sm3_context *ctx, unsigned char *input, int ilen )
+{
+    sm3_update( ctx, input, ilen );
+}
+
+/*
+ * SM3 HMAC final digest
+ */
+void sm3_hmac_finish( sm3_context *ctx, unsigned char output[32] )
+{
+    int hlen;
+    unsigned char tmpbuf[32];
+
+    //is224 = ctx->is224;
+    hlen =  32;
+
+    sm3_finish( ctx, tmpbuf );
+    sm3_starts( ctx );
+    sm3_update( ctx, ctx->opad, 64 );
+    sm3_update( ctx, tmpbuf, hlen );
+    sm3_finish( ctx, output );
+
+    memset( tmpbuf, 0, sizeof( tmpbuf ) );
+}
+
+/*
+ * output = HMAC-SM#( hmac key, input buffer )
+ */
+void sm3_hmac( unsigned char *key, int keylen,
+                unsigned char *input, int ilen,
+                unsigned char output[32] )
+{
+    sm3_context ctx;
+
+    sm3_hmac_starts( &ctx, key, keylen);
+    sm3_hmac_update( &ctx, input, ilen );
+    sm3_hmac_finish( &ctx, output );
+
+    memset( &ctx, 0, sizeof( sm3_context ) );
+}
+
+
+
+
+
+
+

+ 120 - 0
SM2_SM3_SM4_C语言实现/SM3/sm3.h

@@ -0,0 +1,120 @@
+/**
+ * \file sm3.h
+ * thanks to Xyssl
+ * SM3 standards:http://www.oscca.gov.cn/News/201012/News_1199.htm
+ * author:goldboar
+ * email:[email protected]
+ * 2011-10-26
+ */
+#ifndef XYSSL_SM3_H
+#define XYSSL_SM3_H
+
+
+/**
+ * \brief          SM3 context structure
+ */
+typedef struct
+{
+    unsigned long total[2];     /*!< number of bytes processed  */
+    unsigned long state[8];     /*!< intermediate digest state  */
+    unsigned char buffer[64];   /*!< data block being processed */
+
+    unsigned char ipad[64];     /*!< HMAC: inner padding        */
+    unsigned char opad[64];     /*!< HMAC: outer padding        */
+
+}
+sm3_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SM3 context setup
+ *
+ * \param ctx      context to be initialized
+ */
+void sm3_starts( sm3_context *ctx );
+
+/**
+ * \brief          SM3 process buffer
+ *
+ * \param ctx      SM3 context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sm3_update( sm3_context *ctx, unsigned char *input, int ilen );
+
+/**
+ * \brief          SM3 final digest
+ *
+ * \param ctx      SM3 context
+ */
+void sm3_finish( sm3_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief          Output = SM3( input buffer )
+ *
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   SM3 checksum result
+ */
+void sm3( unsigned char *input, int ilen,
+           unsigned char output[32]);
+
+/**
+ * \brief          Output = SM3( file contents )
+ *
+ * \param path     input file name
+ * \param output   SM3 checksum result
+ *
+ * \return         0 if successful, 1 if fopen failed,
+ *                 or 2 if fread failed
+ */
+int sm3_file( char *path, unsigned char output[32] );
+
+/**
+ * \brief          SM3 HMAC context setup
+ *
+ * \param ctx      HMAC context to be initialized
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ */
+void sm3_hmac_starts( sm3_context *ctx, unsigned char *key, int keylen);
+
+/**
+ * \brief          SM3 HMAC process buffer
+ *
+ * \param ctx      HMAC context
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ */
+void sm3_hmac_update( sm3_context *ctx, unsigned char *input, int ilen );
+
+/**
+ * \brief          SM3 HMAC final digest
+ *
+ * \param ctx      HMAC context
+ * \param output   SM3 HMAC checksum result
+ */
+void sm3_hmac_finish( sm3_context *ctx, unsigned char output[32] );
+
+/**
+ * \brief          Output = HMAC-SM3( hmac key, input buffer )
+ *
+ * \param key      HMAC secret key
+ * \param keylen   length of the HMAC key
+ * \param input    buffer holding the  data
+ * \param ilen     length of the input data
+ * \param output   HMAC-SM3 result
+ */
+void sm3_hmac( unsigned char *key, int keylen,
+                unsigned char *input, int ilen,
+                unsigned char output[32] );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sm3.h */

+ 45 - 0
SM2_SM3_SM4_C语言实现/SM3/sm3test.c

@@ -0,0 +1,45 @@
+
+#include <string.h>
+#include <stdio.h>
+#include "sm3.h"
+
+int main( int argc, char *argv[] )
+{
+	unsigned char *input = "abc";
+	int ilen = 3;
+	unsigned char output[32];
+	int i;
+	sm3_context ctx;
+
+	printf("Message:\n");
+	printf("%s\n",input);
+
+	sm3(input, ilen, output);
+	printf("Hash:\n   ");
+	for(i=0; i<32; i++)
+	{
+		printf("%02x",output[i]);
+		if (((i+1) % 4 ) == 0) printf(" ");
+	} 
+	printf("\n");
+
+	printf("Message:\n");
+	for(i=0; i < 16; i++)
+		printf("abcd");
+	printf("\n");
+
+    sm3_starts( &ctx );
+	for(i=0; i < 16; i++)
+		sm3_update( &ctx, "abcd", 4 );
+    sm3_finish( &ctx, output );
+    memset( &ctx, 0, sizeof( sm3_context ) );
+	
+	printf("Hash:\n   ");
+	for(i=0; i<32; i++)
+	{
+		printf("%02x",output[i]);
+		if (((i+1) % 4 ) == 0) printf(" ");
+	}   
+	printf("\n");
+    //getch();	//VS2008 
+}

+ 98 - 0
SM2_SM3_SM4_C语言实现/SM3/sm3test.dsp

@@ -0,0 +1,98 @@
+# Microsoft Developer Studio Project File - Name="sm3test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=sm3test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "sm3test.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "sm3test.mak" CFG="sm3test - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "sm3test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "sm3test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "sm3test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x804 /d "NDEBUG"
+# ADD RSC /l 0x804 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# SUBTRACT LINK32 /debug
+
+!ELSEIF  "$(CFG)" == "sm3test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x804 /d "_DEBUG"
+# ADD RSC /l 0x804 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "sm3test - Win32 Release"
+# Name "sm3test - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\sm3.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm3.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm3test.c
+# End Source File
+# End Target
+# End Project

+ 29 - 0
SM2_SM3_SM4_C语言实现/SM3/sm3test.dsw

@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sm3test"=".\sm3test.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

+ 344 - 0
SM2_SM3_SM4_C语言实现/SM4/sm4.c

@@ -0,0 +1,344 @@
+/*
+ * SM4 Encryption alogrithm (SMS4 algorithm)
+ * GM/T 0002-2012 Chinese National Standard ref:http://www.oscca.gov.cn/ 
+ * thanks to Xyssl
+ * thnaks and refers to http://hi.baidu.com/numax/blog/item/80addfefddfb93e4cf1b3e61.html
+ * author:goldboar
+ * email:[email protected]
+ * 2012-4-20
+ */
+
+// Test vector 1
+// plain: 01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
+// key:   01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
+// 	   round key and temp computing result:
+// 	   rk[ 0] = f12186f9 X[ 0] = 27fad345
+// 		   rk[ 1] = 41662b61 X[ 1] = a18b4cb2
+// 		   rk[ 2] = 5a6ab19a X[ 2] = 11c1e22a
+// 		   rk[ 3] = 7ba92077 X[ 3] = cc13e2ee
+// 		   rk[ 4] = 367360f4 X[ 4] = f87c5bd5
+// 		   rk[ 5] = 776a0c61 X[ 5] = 33220757
+// 		   rk[ 6] = b6bb89b3 X[ 6] = 77f4c297
+// 		   rk[ 7] = 24763151 X[ 7] = 7a96f2eb
+// 		   rk[ 8] = a520307c X[ 8] = 27dac07f
+// 		   rk[ 9] = b7584dbd X[ 9] = 42dd0f19
+// 		   rk[10] = c30753ed X[10] = b8a5da02
+// 		   rk[11] = 7ee55b57 X[11] = 907127fa
+// 		   rk[12] = 6988608c X[12] = 8b952b83
+// 		   rk[13] = 30d895b7 X[13] = d42b7c59
+// 		   rk[14] = 44ba14af X[14] = 2ffc5831
+// 		   rk[15] = 104495a1 X[15] = f69e6888
+// 		   rk[16] = d120b428 X[16] = af2432c4
+// 		   rk[17] = 73b55fa3 X[17] = ed1ec85e
+// 		   rk[18] = cc874966 X[18] = 55a3ba22
+// 		   rk[19] = 92244439 X[19] = 124b18aa
+// 		   rk[20] = e89e641f X[20] = 6ae7725f
+// 		   rk[21] = 98ca015a X[21] = f4cba1f9
+// 		   rk[22] = c7159060 X[22] = 1dcdfa10
+// 		   rk[23] = 99e1fd2e X[23] = 2ff60603
+// 		   rk[24] = b79bd80c X[24] = eff24fdc
+// 		   rk[25] = 1d2115b0 X[25] = 6fe46b75
+// 		   rk[26] = 0e228aeb X[26] = 893450ad
+// 		   rk[27] = f1780c81 X[27] = 7b938f4c
+// 		   rk[28] = 428d3654 X[28] = 536e4246
+// 		   rk[29] = 62293496 X[29] = 86b3e94f
+// 		   rk[30] = 01cf72e5 X[30] = d206965e
+// 		   rk[31] = 9124a012 X[31] = 681edf34
+// cypher: 68 1e df 34 d2 06 96 5e 86 b3 e9 4f 53 6e 42 46
+// 		
+// test vector 2
+// the same key and plain 1000000 times coumpting 
+// plain:  01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
+// key:    01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10
+// cypher: 59 52 98 c7 c6 fd 27 1f 04 02 f8 04 c3 3d 3f 66
+
+#include "sm4.h"
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_ULONG_BE
+#define GET_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (n) = ( (unsigned long) (b)[(i)    ] << 24 )        \
+        | ( (unsigned long) (b)[(i) + 1] << 16 )        \
+        | ( (unsigned long) (b)[(i) + 2] <<  8 )        \
+        | ( (unsigned long) (b)[(i) + 3]       );       \
+}
+#endif
+
+#ifndef PUT_ULONG_BE
+#define PUT_ULONG_BE(n,b,i)                             \
+{                                                       \
+    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
+    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
+    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
+    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+}
+#endif
+
+/*
+ *rotate shift left marco definition
+ *
+ */
+#define  SHL(x,n) (((x) & 0xFFFFFFFF) << n)
+#define ROTL(x,n) (SHL((x),n) | ((x) >> (32 - n)))
+
+#define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
+
+/*
+ * Expanded SM4 S-boxes
+ /* Sbox table: 8bits input convert to 8 bits output*/
+ 
+static const unsigned char SboxTable[16][16] = 
+{
+{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05},
+{0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99},
+{0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62},
+{0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6},
+{0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8},
+{0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35},
+{0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87},
+{0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e},
+{0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1},
+{0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3},
+{0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f},
+{0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51},
+{0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8},
+{0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0},
+{0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84},
+{0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}
+};
+
+/* System parameter */
+static const unsigned long FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc};
+
+/* fixed parameter */
+static const unsigned long CK[32] =
+{
+0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
+0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
+0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
+0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
+0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
+0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
+0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
+0x10171e25,0x2c333a41,0x484f565d,0x646b7279
+};
+
+
+/*
+ * private function:
+ * look up in SboxTable and get the related value.
+ * args:    [in] inch: 0x00~0xFF (8 bits unsigned value).
+ */
+static unsigned char sm4Sbox(unsigned char inch)
+{
+    unsigned char *pTable = (unsigned char *)SboxTable;
+    unsigned char retVal = (unsigned char)(pTable[inch]);
+    return retVal;
+}
+
+/*
+ * private F(Lt) function:
+ * "T algorithm" == "L algorithm" + "t algorithm".
+ * args:    [in] a: a is a 32 bits unsigned value;
+ * return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
+ */
+static unsigned long sm4Lt(unsigned long ka)
+{
+    unsigned long bb = 0;
+    unsigned long c = 0;
+    unsigned char a[4];
+	unsigned char b[4];
+    PUT_ULONG_BE(ka,a,0)
+    b[0] = sm4Sbox(a[0]);
+    b[1] = sm4Sbox(a[1]);
+    b[2] = sm4Sbox(a[2]);
+    b[3] = sm4Sbox(a[3]);
+	GET_ULONG_BE(bb,b,0)
+    c =bb^(ROTL(bb, 2))^(ROTL(bb, 10))^(ROTL(bb, 18))^(ROTL(bb, 24));
+    return c;
+}
+
+/*
+ * private F function:
+ * Calculating and getting encryption/decryption contents.
+ * args:    [in] x0: original contents;
+ * args:    [in] x1: original contents;
+ * args:    [in] x2: original contents;
+ * args:    [in] x3: original contents;
+ * args:    [in] rk: encryption/decryption key;
+ * return the contents of encryption/decryption contents.
+ */
+static unsigned long sm4F(unsigned long x0, unsigned long x1, unsigned long x2, unsigned long x3, unsigned long rk)
+{
+    return (x0^sm4Lt(x1^x2^x3^rk));
+}
+
+
+/* private function:
+ * Calculating round encryption key.
+ * args:    [in] a: a is a 32 bits unsigned value;
+ * return: sk[i]: i{0,1,2,3,...31}.
+ */
+static unsigned long sm4CalciRK(unsigned long ka)
+{
+    unsigned long bb = 0;
+    unsigned long rk = 0;
+    unsigned char a[4];
+    unsigned char b[4];
+    PUT_ULONG_BE(ka,a,0)
+    b[0] = sm4Sbox(a[0]);
+    b[1] = sm4Sbox(a[1]);
+    b[2] = sm4Sbox(a[2]);
+    b[3] = sm4Sbox(a[3]);
+	GET_ULONG_BE(bb,b,0)
+    rk = bb^(ROTL(bb, 13))^(ROTL(bb, 23));
+    return rk;
+}
+
+static void sm4_setkey( unsigned long SK[32], unsigned char key[16] )
+{
+    unsigned long MK[4];
+    unsigned long k[36];
+    unsigned long i = 0;
+
+    GET_ULONG_BE( MK[0], key, 0 );
+    GET_ULONG_BE( MK[1], key, 4 );
+    GET_ULONG_BE( MK[2], key, 8 );
+    GET_ULONG_BE( MK[3], key, 12 );
+    k[0] = MK[0]^FK[0];
+    k[1] = MK[1]^FK[1];
+    k[2] = MK[2]^FK[2];
+    k[3] = MK[3]^FK[3];
+    for(; i<32; i++)
+    {
+        k[i+4] = k[i] ^ (sm4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i]));
+        SK[i] = k[i+4];
+	}
+
+}
+
+/*
+ * SM4 standard one round processing
+ *
+ */
+static void sm4_one_round( unsigned long sk[32],
+                    unsigned char input[16],
+                    unsigned char output[16] )
+{
+    unsigned long i = 0;
+    unsigned long ulbuf[36];
+
+    memset(ulbuf, 0, sizeof(ulbuf));
+    GET_ULONG_BE( ulbuf[0], input, 0 )
+    GET_ULONG_BE( ulbuf[1], input, 4 )
+    GET_ULONG_BE( ulbuf[2], input, 8 )
+    GET_ULONG_BE( ulbuf[3], input, 12 )
+    while(i<32)
+    {
+        ulbuf[i+4] = sm4F(ulbuf[i], ulbuf[i+1], ulbuf[i+2], ulbuf[i+3], sk[i]);
+// #ifdef _DEBUG
+//        	printf("rk(%02d) = 0x%08x,  X(%02d) = 0x%08x \n",i,sk[i], i, ulbuf[i+4] );
+// #endif
+	    i++;
+    }
+	PUT_ULONG_BE(ulbuf[35],output,0);
+	PUT_ULONG_BE(ulbuf[34],output,4);
+	PUT_ULONG_BE(ulbuf[33],output,8);
+	PUT_ULONG_BE(ulbuf[32],output,12);
+}
+
+/*
+ * SM4 key schedule (128-bit, encryption)
+ */
+void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] )
+{
+    ctx->mode = SM4_ENCRYPT;
+	sm4_setkey( ctx->sk, key );
+}
+
+/*
+ * SM4 key schedule (128-bit, decryption)
+ */
+void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] )
+{
+    int i;
+	ctx->mode = SM4_ENCRYPT;
+    sm4_setkey( ctx->sk, key );
+    for( i = 0; i < 16; i ++ )
+    {
+        SWAP( ctx->sk[ i ], ctx->sk[ 31-i] );
+    }
+}
+
+
+/*
+ * SM4-ECB block encryption/decryption
+ */
+
+void sm4_crypt_ecb( sm4_context *ctx,
+				   int mode,
+				   int length,
+				   unsigned char *input,
+                   unsigned char *output)
+{
+    while( length > 0 )
+    {
+        sm4_one_round( ctx->sk, input, output );
+        input  += 16;
+        output += 16;
+        length -= 16;
+    }
+
+}
+
+/*
+ * SM4-CBC buffer encryption/decryption
+ */
+void sm4_crypt_cbc( sm4_context *ctx,
+                    int mode,
+                    int length,
+                    unsigned char iv[16],
+                    unsigned char *input,
+                    unsigned char *output )
+{
+    int i;
+    unsigned char temp[16];
+
+    if( mode == SM4_ENCRYPT )
+    {
+        while( length > 0 )
+        {
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( input[i] ^ iv[i] );
+
+            sm4_one_round( ctx->sk, output, output );
+            memcpy( iv, output, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+    else /* SM4_DECRYPT */
+    {
+        while( length > 0 )
+        {
+            memcpy( temp, input, 16 );
+            sm4_one_round( ctx->sk, input, output );
+
+            for( i = 0; i < 16; i++ )
+                output[i] = (unsigned char)( output[i] ^ iv[i] );
+
+            memcpy( iv, temp, 16 );
+
+            input  += 16;
+            output += 16;
+            length -= 16;
+        }
+    }
+}

+ 96 - 0
SM2_SM3_SM4_C语言实现/SM4/sm4.dsp

@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="sm4" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=sm4 - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "sm4.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "sm4.mak" CFG="sm4 - Win32 Debug"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "sm4 - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "sm4 - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "sm4 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x804 /d "NDEBUG"
+# ADD RSC /l 0x804 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+
+!ELSEIF  "$(CFG)" == "sm4 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x804 /d "_DEBUG"
+# ADD RSC /l 0x804 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "sm4 - Win32 Release"
+# Name "sm4 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\sm4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm4.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sm4test.c
+# End Source File
+# End Target
+# End Project

+ 29 - 0
SM2_SM3_SM4_C语言实现/SM4/sm4.dsw

@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sm4"=.\sm4.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+

+ 75 - 0
SM2_SM3_SM4_C语言实现/SM4/sm4.h

@@ -0,0 +1,75 @@
+/**
+ * \file sm4.h
+ */
+#ifndef XYSSL_SM4_H
+#define XYSSL_SM4_H
+
+#define SM4_ENCRYPT     1
+#define SM4_DECRYPT     0
+
+/**
+ * \brief          SM4 context structure
+ */
+typedef struct
+{
+    int mode;                   /*!<  encrypt/decrypt   */
+    unsigned long sk[32];       /*!<  SM4 subkeys       */
+}
+sm4_context;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief          SM4 key schedule (128-bit, encryption)
+ *
+ * \param ctx      SM4 context to be initialized
+ * \param key      16-byte secret key
+ */
+void sm4_setkey_enc( sm4_context *ctx, unsigned char key[16] );
+
+/**
+ * \brief          SM4 key schedule (128-bit, decryption)
+ *
+ * \param ctx      SM4 context to be initialized
+ * \param key      16-byte secret key
+ */
+void sm4_setkey_dec( sm4_context *ctx, unsigned char key[16] );
+
+/**
+ * \brief          SM4-ECB block encryption/decryption
+ * \param ctx      SM4 context
+ * \param mode     SM4_ENCRYPT or SM4_DECRYPT
+ * \param length   length of the input data
+ * \param input    input block
+ * \param output   output block
+ */
+void sm4_crypt_ecb( sm4_context *ctx,
+				     int mode,
+					 int length,
+                     unsigned char *input,
+                     unsigned char *output);
+
+/**
+ * \brief          SM4-CBC buffer encryption/decryption
+ * \param ctx      SM4 context
+ * \param mode     SM4_ENCRYPT or SM4_DECRYPT
+ * \param length   length of the input data
+ * \param iv       initialization vector (updated after use)
+ * \param input    buffer holding the input data
+ * \param output   buffer holding the output data
+ */
+void sm4_crypt_cbc( sm4_context *ctx,
+                     int mode,
+                     int length,
+                     unsigned char iv[16],
+                     unsigned char *input,
+                     unsigned char *output );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* sm4.h */

+ 45 - 0
SM2_SM3_SM4_C语言实现/SM4/sm4test.c

@@ -0,0 +1,45 @@
+/*
+ * SM4/SMS4 algorithm test programme
+ * 2012-4-21
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "sm4.h"
+
+int main()
+{
+	unsigned char key[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
+	unsigned char input[16] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10};
+	unsigned char output[16];
+	sm4_context ctx;
+	unsigned long i;
+
+	//encrypt standard testing vector
+	sm4_setkey_enc(&ctx,key);
+	sm4_crypt_ecb(&ctx,1,16,input,output);
+	for(i=0;i<16;i++)
+		printf("%02x ", output[i]);
+	printf("\n");
+
+	//decrypt testing
+	sm4_setkey_dec(&ctx,key);
+	sm4_crypt_ecb(&ctx,0,16,output,output);
+	for(i=0;i<16;i++)
+		printf("%02x ", output[i]);
+	printf("\n");
+
+	//decrypt 1M times testing vector based on standards.
+	i = 0;
+	sm4_setkey_enc(&ctx,key);
+	while (i<1000000) 
+    {
+		sm4_crypt_ecb(&ctx,1,16,input,input);
+		i++;
+    }
+	for(i=0;i<16;i++)
+		printf("%02x ", input[i]);
+	printf("\n");
+	
+    return 0;
+}

+ 382 - 0
SM2_SM3_SM4_C语言实现/SM4/sms4.c

@@ -0,0 +1,382 @@
+/* sms4.c
+** SMS4 Encryption algorithm for wireless networks
+**
+** $Id: sms4.c 2009-12-31 14:41:57 tao.tang <$">[email protected]>$
+**
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public License
+** as published by the Free Software Foundation; either version 2
+** of the License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc.
+**/
+
+#include <string.h>
+#include <stdio.h>
+/*#include "sms4.h"*/
+
+#ifndef unlong
+typedef unsigned long unlong;
+#endif /* unlong */
+
+#ifndef unchar
+typedef unsigned char unchar;
+#endif /* unchar */
+
+/* define SMS4CROL for rotating left */
+#define SMS4CROL(uval, bits) ((uval << bits) | (uval >> (0x20 - bits)))
+
+/* define MASK code for selecting expected bits from a 32 bits value */
+#define SMS4MASK3 0xFF000000
+#define SMS4MASK2 0x00FF0000
+#define SMS4MASK1 0x0000FF00
+#define SMS4MASK0 0x000000FF
+
+/* Sbox table: 8bits input convert to 8 bits output*/
+static unchar SboxTable[16][16] = 
+{
+{0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05},
+{0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99},
+{0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62},
+{0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6},
+{0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8},
+{0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35},
+{0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87},
+{0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e},
+{0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1},
+{0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3},
+{0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f},
+{0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51},
+{0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8},
+{0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0},
+{0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84},
+{0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48}
+};
+
+/* Encryption key: 128bits */
+static unlong MK[4] = {0x01234567,0x89abcdef,0xfedcba98,0x76543210};
+
+/* System parameter */
+static unlong FK[4] = {0xa3b1bac6,0x56aa3350,0x677d9197,0xb27022dc};
+
+/* fixed parameter */
+static unlong CK[32] =
+{
+0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
+0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
+0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
+0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
+0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
+0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
+0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
+0x10171e25,0x2c333a41,0x484f565d,0x646b7279
+};
+
+/* buffer for round encryption key */
+static unlong ENRK[32];
+static unlong DERK[32];
+
+/* original contents for debugging */
+unlong pData[4] = 
+{
+0x01234567,
+0x89abcdef,
+0xfedcba98,
+0x76543210
+};
+
+/* original contents for debugging */
+unlong pData2[9] = 
+{
+0x01234567,
+0x89abcdef,
+0xfedcba98,
+0x76543210,
+0x12121212,
+0x34343434,
+0x56565656,
+0x78787878,
+0x12341234
+};
+
+/*=============================================================================
+** private function:
+**   look up in SboxTable and get the related value.
+** args:    [in] inch: 0x00~0xFF (8 bits unsigned value).
+**============================================================================*/
+static unchar SMS4Sbox(unchar inch)
+{
+    unchar *pTable = (unchar *)SboxTable;
+    unchar retVal = (unchar)(pTable[inch]);
+
+    return retVal;
+}
+
+/*=============================================================================
+** private function:
+**   "T algorithm" == "L algorithm" + "t algorithm".
+** args:    [in] a: a is a 32 bits unsigned value;
+** return: c: c is calculated with line algorithm "L" and nonline algorithm "t"
+**============================================================================*/
+static unlong SMS4Lt(unlong a)
+{
+    unlong b = 0;
+    unlong c = 0;
+    unchar a0 = (unchar)(a & SMS4MASK0);
+    unchar a1 = (unchar)((a & SMS4MASK1) >> 8);
+    unchar a2 = (unchar)((a & SMS4MASK2) >> 16);
+    unchar a3 = (unchar)((a & SMS4MASK3) >> 24);
+    unchar b0 = SMS4Sbox(a0);
+    unchar b1 = SMS4Sbox(a1);
+    unchar b2 = SMS4Sbox(a2);
+    unchar b3 = SMS4Sbox(a3);
+
+    b =b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
+    c =b^(SMS4CROL(b, 2))^(SMS4CROL(b, 10))^(SMS4CROL(b, 18))^(SMS4CROL(b, 24));
+
+    return c;
+}
+
+/*=============================================================================
+** private function:
+**   Calculating round encryption key.
+** args:    [in] a: a is a 32 bits unsigned value;
+** return: ENRK[i]: i{0,1,2,3,...31}.
+**============================================================================*/
+static unlong SMS4CalciRK(unlong a)
+{
+    unlong b = 0;
+    unlong rk = 0;
+    unchar a0 = (unchar)(a & SMS4MASK0);
+    unchar a1 = (unchar)((a & SMS4MASK1) >> 8);
+    unchar a2 = (unchar)((a & SMS4MASK2) >> 16);
+    unchar a3 = (unchar)((a & SMS4MASK3) >> 24);
+    unchar b0 = SMS4Sbox(a0);
+    unchar b1 = SMS4Sbox(a1);
+    unchar b2 = SMS4Sbox(a2);
+    unchar b3 = SMS4Sbox(a3);
+
+    b = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
+    rk = b^(SMS4CROL(b, 13))^(SMS4CROL(b, 23));
+
+    return rk;
+}
+
+/*=============================================================================
+** private function:
+**   Calculating round encryption key.
+** args:    [in] ulflag: if 0: not calculate DERK , else calculate;
+** return: NONE.
+**============================================================================*/
+static void SMS4CalcRK(unlong ulflag)
+{
+    unlong k[36];
+    unlong i = 0;
+
+    k[0] = MK[0]^FK[0];
+    k[1] = MK[1]^FK[1];
+    k[2] = MK[2]^FK[2];
+    k[3] = MK[3]^FK[3];
+
+    for(; i<32; i++)
+    {
+        k[i+4] = k[i] ^ (SMS4CalciRK(k[i+1]^k[i+2]^k[i+3]^CK[i]));
+        ENRK[i] = k[i+4];
+    }
+
+    if (ulflag != 0x00) 
+    {
+        for (i=0; i<32; i++) 
+        {
+            DERK[i] = ENRK[31-i];
+        }
+    }
+}
+
+/*=============================================================================
+** private function:
+**   "T algorithm" == "L algorithm" + "t algorithm".
+** args:    [in] a: a is a 32 bits unsigned value.
+**============================================================================*/
+static unlong SMS4T(unlong a)
+{
+    return (SMS4Lt(a));
+}
+
+/*=============================================================================
+** private function:
+**   Calculating and getting encryption/decryption contents.
+** args:    [in] x0: original contents;
+** args:    [in] x1: original contents;
+** args:    [in] x2: original contents;
+** args:    [in] x3: original contents;
+** args:    [in] rk: encryption/decryption key;
+** return the contents of encryption/decryption contents.
+**============================================================================*/
+static unlong SMS4F(unlong x0, unlong x1, unlong x2, unlong x3, unlong rk)
+{
+    return (x0^SMS4Lt(x1^x2^x3^rk));
+}
+
+/*=============================================================================
+** public function:
+**   "T algorithm" == "L algorithm" + "t algorithm".
+** args:    [in] ulkey: password defined by user(NULL: default encryption key);
+** args:    [in] flag: if 0: not calculate DERK , else calculate;
+** return ulkey: NULL for default encryption key.
+**============================================================================*/
+unlong *SMS4SetKey(unlong *ulkey, unlong flag)
+{
+    if (ulkey != NULL) 
+    {
+        memcpy(MK, ulkey, sizeof(MK));
+    }
+
+    SMS4CalcRK(flag);
+
+    return ulkey;
+}
+
+/*=============================================================================
+** public function:
+**   sms4 encryption algorithm.
+** args:   [in/out] psrc: a pointer point to original contents;
+** args:   [in] lgsrc: the length of original contents;
+** args:   [in] derk: a pointer point to encryption/decryption key;
+** return: pRet: a pointer point to encrypted contents.
+**============================================================================*/
+unlong *SMS4Encrypt(unlong *psrc, unlong lgsrc, unlong rk[])
+{
+    unlong *pRet = NULL;
+    unlong i = 0;
+    
+    unlong ulbuf[36];
+
+    unlong ulCnter = 0;
+    unlong ulTotal = (lgsrc >> 4);
+
+    
+    if(psrc != NULL)
+    {
+        pRet = psrc;
+        
+        /* !!!It's a temporary scheme: start!!! */
+        /*========================================
+        ** 16 bytes(128 bits) is deemed as an unit.
+        **======================================*/
+        while (ulCnter<ulTotal) 
+        {
+            /* reset number counter */
+            i = 0;
+
+            /* filled up with 0*/
+            memset(ulbuf, 0, sizeof(ulbuf));
+            memcpy(ulbuf, psrc, 16);
+#ifdef SMS4DBG0
+            printf("0x%08x, 0x%08x, 0x%08x, 0x%08x, \n", 
+                   ulbuf[0], ulbuf[1], ulbuf[2], ulbuf[3]);
+#endif /* SMS4DBG0 */
+            
+            while(i<32)
+            {
+                ulbuf[i+4] = SMS4F(ulbuf[i], ulbuf[i+1], 
+                                   ulbuf[i+2], ulbuf[i+3], rk[i]);
+#ifdef SMS4DBG0
+                printf("0x%08x, \n", ulbuf[i+4]);
+#endif /* SMS4DBG0 */
+                i++;
+            }
+
+            /* save encrypted contents to original area */
+            psrc[0] = ulbuf[35];
+            psrc[1] = ulbuf[34];
+            psrc[2] = ulbuf[33];
+            psrc[3] = ulbuf[32];
+
+            ulCnter++;
+            psrc += 4;
+        }
+        /* !!!It's a temporary scheme: end!!! */
+    }
+
+    return pRet;
+}
+
+/*=============================================================================
+** public function:
+**   sms4 decryption algorithm.
+** args:   [in/out] psrc: a pointer point to encrypted contents;
+** args:   [in] lgsrc: the length of encrypted contents;
+** args:   [in] derk: a pointer point to decryption key;
+** return: pRet: a pointer point to decrypted contents.
+**============================================================================*/
+unlong *SMS4Decrypt(unlong *psrc, unlong lgsrc, unlong derk[])
+{
+    unlong *pRet = NULL;
+    unlong i = 0;
+
+    if(psrc != NULL)
+    {
+        pRet = psrc;
+
+        /* the same arithmetic, different encryption key sequence. */
+        SMS4Encrypt(psrc, lgsrc, derk);
+    }
+    
+    return pRet;
+}
+
+
+void SMS4Encrypt1M()
+{
+    unlong i = 0;
+
+    while (i<1000000) 
+    {
+        SMS4Encrypt(pData, sizeof(pData), ENRK);
+        i++;
+
+//         if (0 == i%10000) 
+//         {
+//             printf("encrypted times: %d\n", i);
+//         }
+    }
+
+    printf("0x%08x, 0x%08x, 0x%08x, 0x%08x. \n", 
+           pData[0], pData[1], pData[2], pData[3]);
+}
+
+
+/* entry-point for debugging */
+int main()
+{
+    SMS4SetKey(NULL, 1);
+
+    /* cycle1: common test */
+	printf("0x%08x, 0x%08x, 0x%08x, 0x%08x. \n", 
+           pData[0], pData[1], pData[2], pData[3]);
+    SMS4Encrypt(pData, sizeof(pData), ENRK);
+	printf("0x%08x, 0x%08x, 0x%08x, 0x%08x. \n", 
+           pData[0], pData[1], pData[2], pData[3]);
+    SMS4Decrypt(pData, sizeof(pData), DERK);
+	printf("0x%08x, 0x%08x, 0x%08x, 0x%08x. \n", 
+           pData[0], pData[1], pData[2], pData[3]);
+
+    /* cycle2: encrypted 1000000 times */
+    SMS4Encrypt1M();
+
+    /* cycle3: longer contents */
+    SMS4Encrypt(pData2, sizeof(pData2), ENRK);
+    SMS4Decrypt(pData2, sizeof(pData2), DERK);
+
+    return 0;
+}
+

+ 105 - 0
java源码+jar包/com/security/cipher/sm/Cipher.java

@@ -0,0 +1,105 @@
+package com.security.cipher.sm;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
+import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
+import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+import org.bouncycastle.math.ec.ECPoint;
+
+public class Cipher 
+{
+	private int ct;
+	private ECPoint p2;
+	private SM3Digest sm3keybase;
+	private SM3Digest sm3c3;
+	private byte key[];
+	private byte keyOff;
+
+	public Cipher() 
+	{
+		this.ct = 1;
+		this.key = new byte[32];
+		this.keyOff = 0;
+	}
+
+	private void Reset() 
+	{
+		this.sm3keybase = new SM3Digest();
+		this.sm3c3 = new SM3Digest();
+		
+		byte p[] = Util.byteConvert32Bytes(p2.getX().toBigInteger());
+		this.sm3keybase.update(p, 0, p.length);
+		this.sm3c3.update(p, 0, p.length);
+		
+		p = Util.byteConvert32Bytes(p2.getY().toBigInteger());
+		this.sm3keybase.update(p, 0, p.length);
+		this.ct = 1;
+		NextKey();
+	}
+
+	private void NextKey() 
+	{
+		SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
+		sm3keycur.update((byte) (ct >> 24 & 0xff));
+		sm3keycur.update((byte) (ct >> 16 & 0xff));
+		sm3keycur.update((byte) (ct >> 8 & 0xff));
+		sm3keycur.update((byte) (ct & 0xff));
+		sm3keycur.doFinal(key, 0);
+		this.keyOff = 0;
+		this.ct++;
+	}
+
+	public ECPoint Init_enc(SM2 sm2, ECPoint userKey) 
+	{
+		AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.generateKeyPair();
+		ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) key.getPrivate();
+		ECPublicKeyParameters ecpub = (ECPublicKeyParameters) key.getPublic();
+		BigInteger k = ecpriv.getD();
+		ECPoint c1 = ecpub.getQ();
+		this.p2 = userKey.multiply(k);
+		Reset();
+		return c1;
+	}
+
+	public void Encrypt(byte data[]) 
+	{
+		this.sm3c3.update(data, 0, data.length);
+		for (int i = 0; i < data.length; i++) 
+		{
+			if (keyOff == key.length)
+			{
+				NextKey();
+			}
+			data[i] ^= key[keyOff++];
+		}
+	}
+
+	public void Init_dec(BigInteger userD, ECPoint c1)
+	{
+		this.p2 = c1.multiply(userD);
+		Reset();
+	}
+
+	public void Decrypt(byte data[]) 
+	{
+		for (int i = 0; i < data.length; i++)
+		{
+			if (keyOff == key.length)
+			{
+				NextKey();
+			}
+			data[i] ^= key[keyOff++];
+		}
+
+		this.sm3c3.update(data, 0, data.length);
+	}
+
+	public void Dofinal(byte c3[]) 
+	{
+		byte p[] = Util.byteConvert32Bytes(p2.getY().toBigInteger());
+		this.sm3c3.update(p, 0, p.length);
+		this.sm3c3.doFinal(c3, 0);
+		Reset();
+	}
+}

+ 182 - 0
java源码+jar包/com/security/cipher/sm/SM2.java

@@ -0,0 +1,182 @@
+package com.security.cipher.sm;
+
+import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
+import org.bouncycastle.crypto.params.ECDomainParameters;
+import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECFieldElement;
+import org.bouncycastle.math.ec.ECFieldElement.Fp;
+import org.bouncycastle.math.ec.ECPoint;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+public class SM2 
+{
+	/*
+	// 测试参数
+	public static final String[] ecc_param = {
+	    "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3", 
+	    "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498", 
+	    "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A", 
+	    "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7", 
+	    "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D", 
+	    "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2" 
+	};
+	*/
+	// 正式参数
+	public static String[] ecc_param = {
+		"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",
+		"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",
+		"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",
+		"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",
+		"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",
+		"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"
+	};
+
+	public static SM2 Instance() 
+	{
+		return new SM2();
+	}
+
+	public final BigInteger ecc_p;
+	public final BigInteger ecc_a;
+	public final BigInteger ecc_b;
+	public final BigInteger ecc_n;
+	public final BigInteger ecc_gx;
+	public final BigInteger ecc_gy;
+	public final ECCurve ecc_curve;
+	public final ECPoint ecc_point_g;
+	public final ECDomainParameters ecc_bc_spec;
+	public final ECKeyPairGenerator ecc_key_pair_generator;
+	public final ECFieldElement ecc_gx_fieldelement;
+	public final ECFieldElement ecc_gy_fieldelement;
+
+	public SM2() 
+	{
+		this.ecc_p = new BigInteger(ecc_param[0], 16);
+		this.ecc_a = new BigInteger(ecc_param[1], 16);
+		this.ecc_b = new BigInteger(ecc_param[2], 16);
+		this.ecc_n = new BigInteger(ecc_param[3], 16);
+		this.ecc_gx = new BigInteger(ecc_param[4], 16);
+		this.ecc_gy = new BigInteger(ecc_param[5], 16);
+
+		this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);
+		this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);
+
+		this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);
+		this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);
+
+		this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);
+
+		ECKeyGenerationParameters ecc_ecgenparam;
+		ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());
+
+		this.ecc_key_pair_generator = new ECKeyPairGenerator();
+		this.ecc_key_pair_generator.init(ecc_ecgenparam);
+	}
+	
+	public byte[] sm2GetZ(byte[] userId, ECPoint userKey)
+	{
+		SM3Digest sm3 = new SM3Digest();
+		
+		int len = userId.length * 8;
+		sm3.update((byte) (len >> 8 & 0xFF));
+		sm3.update((byte) (len & 0xFF));
+		sm3.update(userId, 0, userId.length);
+		
+		byte[] p = Util.byteConvert32Bytes(ecc_a);
+		sm3.update(p, 0, p.length);
+		
+		p = Util.byteConvert32Bytes(ecc_b);
+		sm3.update(p, 0, p.length);
+		
+		p = Util.byteConvert32Bytes(ecc_gx);
+		sm3.update(p, 0, p.length);
+		
+		p = Util.byteConvert32Bytes(ecc_gy);
+		sm3.update(p, 0, p.length);
+		
+		p = Util.byteConvert32Bytes(userKey.getX().toBigInteger());
+		sm3.update(p, 0, p.length);
+		
+		p = Util.byteConvert32Bytes(userKey.getY().toBigInteger());
+		sm3.update(p, 0, p.length);
+		
+		byte[] md = new byte[sm3.getDigestSize()];
+		sm3.doFinal(md, 0);
+		return md;
+	}
+	
+	public void sm2Sign(byte[] md, BigInteger userD, ECPoint userKey, SM2Result sm2Result) 
+	{
+		BigInteger e = new BigInteger(1, md);
+		BigInteger k = null;
+		ECPoint kp = null;
+		BigInteger r = null;
+		BigInteger s = null;
+		do 
+		{
+			do 
+			{
+				// 正式环境
+				/*AsymmetricCipherKeyPair keypair = ecc_key_pair_generator.generateKeyPair();
+				ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) keypair.getPrivate();
+				ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();
+				k = ecpriv.getD();
+				kp = ecpub.getQ();*/
+				
+				// 国密规范测试 随机数k
+				String kS = "6CB28D99385C175C94F94E934817663FC176D925DD72B727260DBAAE1FB2F96F";
+		        k = new BigInteger(kS, 16);
+		        kp = this.ecc_point_g.multiply(k);
+				
+		        System.out.println("计算曲线点X1: " + kp.getX().toBigInteger().toString(16));
+				System.out.println("计算曲线点Y1: " + kp.getY().toBigInteger().toString(16));
+				System.out.println("");
+
+				// r
+				r = e.add(kp.getX().toBigInteger());
+				r = r.mod(ecc_n);
+			} while (r.equals(BigInteger.ZERO) || r.add(k).equals(ecc_n));
+
+			// (1 + dA)~-1
+			BigInteger da_1 = userD.add(BigInteger.ONE);
+			da_1 = da_1.modInverse(ecc_n);
+			
+			// s
+			s = r.multiply(userD);
+			s = k.subtract(s).mod(ecc_n);
+			s = da_1.multiply(s).mod(ecc_n);
+		} while (s.equals(BigInteger.ZERO));
+		
+		sm2Result.r = r;
+		sm2Result.s = s;
+	}
+
+	public void sm2Verify(byte md[], ECPoint userKey, BigInteger r, BigInteger s, SM2Result sm2Result)
+    {
+        sm2Result.R = null;
+        BigInteger e = new BigInteger(1, md);
+        BigInteger t = r.add(s).mod(ecc_n);
+        if(t.equals(BigInteger.ZERO))
+        {
+            return;
+        } 
+        else
+        {
+            ECPoint x1y1 = ecc_point_g.multiply(sm2Result.s);
+            System.out.println("计算曲线点X0: " + x1y1.getX().toBigInteger().toString(16));
+			System.out.println("计算曲线点Y0: " + x1y1.getY().toBigInteger().toString(16));
+			System.out.println("");
+			
+            x1y1 = x1y1.add(userKey.multiply(t));
+            System.out.println("计算曲线点X1: " + x1y1.getX().toBigInteger().toString(16));
+			System.out.println("计算曲线点Y1: " + x1y1.getY().toBigInteger().toString(16));
+			System.out.println("");
+            sm2Result.R = e.add(x1y1.getX().toBigInteger()).mod(ecc_n);
+            System.out.println("R: " + sm2Result.R.toString(16));
+            return;
+        }
+    }
+}

+ 25 - 0
java源码+jar包/com/security/cipher/sm/SM2Result.java

@@ -0,0 +1,25 @@
+package com.security.cipher.sm;
+
+import java.math.BigInteger;
+
+import org.bouncycastle.math.ec.ECPoint;
+
+public class SM2Result 
+{
+	public SM2Result() {
+	}
+
+	// 签名/验签
+	public BigInteger r;
+	public BigInteger s;
+	public BigInteger R;
+
+	// 密钥交换
+	public byte[] sa;
+	public byte[] sb;
+	public byte[] s1;
+	public byte[] s2;
+
+	public ECPoint keyra;
+	public ECPoint keyrb;
+}

+ 289 - 0
java源码+jar包/com/security/cipher/sm/SM2Utils.java

@@ -0,0 +1,289 @@
+package com.security.cipher.sm;
+
+import org.bouncycastle.asn1.ASN1EncodableVector;
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERInteger;
+import org.bouncycastle.asn1.DERObject;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.math.ec.ECPoint;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+public class SM2Utils 
+{
+	public static byte[] encrypt(byte[] publicKey, byte[] data) throws IOException
+	{
+		if (publicKey == null || publicKey.length == 0)
+		{
+			return null;
+		}
+		
+		if (data == null || data.length == 0)
+		{
+			return null;
+		}
+		
+		byte[] source = new byte[data.length];
+		System.arraycopy(data, 0, source, 0, data.length);
+		
+		Cipher cipher = new Cipher();
+		SM2 sm2 = SM2.Instance();
+		ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
+		
+		ECPoint c1 = cipher.Init_enc(sm2, userKey);
+		cipher.Encrypt(source);
+		byte[] c3 = new byte[32];
+		cipher.Dofinal(c3);
+
+		//     System.out.println("C1 " + Util.byteToHex(c1.getEncoded()));
+		//     System.out.println("C2 " + Util.byteToHex(source));
+		//     System.out.println("C3 " + Util.byteToHex(c3));
+		//C1 C2 C3拼装成加密字串
+		String encryptdata = Util.encodeHexString(c1.getEncoded())+Util.encodeHexString(source)+Util.encodeHexString(c3);
+		return Util.hexStringToBytes(encryptdata);
+
+		/*
+		DERInteger x = new DERInteger(c1.getX().toBigInteger());
+		DERInteger y = new DERInteger(c1.getY().toBigInteger());
+		DEROctetString derDig = new DEROctetString(c3);
+		DEROctetString derEnc = new DEROctetString(source);
+		ASN1EncodableVector v = new ASN1EncodableVector();
+		v.add(x);
+		v.add(y);
+		v.add(derDig);
+		v.add(derEnc);
+		DERSequence seq = new DERSequence(v);
+		ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		DEROutputStream dos = new DEROutputStream(bos);
+		dos.writeObject(seq);
+		return bos.toByteArray();
+		*/
+	}
+	
+	public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException
+	{
+		if (privateKey == null || privateKey.length == 0)
+		{
+			return null;
+		}
+		
+		if (encryptedData == null || encryptedData.length == 0)
+		{
+			return null;
+		}
+		
+		//byte[] enc = new byte[encryptedData.length];
+		//System.arraycopy(encryptedData, 0, enc, 0, encryptedData.length);
+		//加密字节数组转换为十六进制的字符串 长度变为encryptedData.length * 2
+		String data = Util.byteToHex(encryptedData);
+		/***分解加密字串
+		 * (C1 = C1标志位2位 + C1实体部分128位 = 130)
+		 * (C3 = C3实体部分64位  = 64)
+		 * (C2 = encryptedData.length * 2 - C1长度  - C2长度)
+		 */
+		byte[] c1Bytes = Util.hexToByte(data.substring(0,130));
+		int c2Len = encryptedData.length - 97;
+		byte[] c2 = Util.hexToByte(data.substring(130,130 + 2 * c2Len));
+		byte[] c3 = Util.hexToByte(data.substring(130 + 2 * c2Len,194 + 2 * c2Len));
+
+		SM2 sm2 = SM2.Instance();
+		BigInteger userD = new BigInteger(1, privateKey);
+		/*
+		ByteArrayInputStream bis = new ByteArrayInputStream(enc);
+		ASN1InputStream dis = new ASN1InputStream(bis);
+		DERObject derObj = dis.readObject();
+		ASN1Sequence asn1 = (ASN1Sequence) derObj;
+		DERInteger x = (DERInteger) asn1.getObjectAt(0);
+		DERInteger y = (DERInteger) asn1.getObjectAt(1);
+
+		ECPoint c1 = sm2.ecc_curve.createPoint(x.getValue(), y.getValue(), true);
+		
+		Cipher cipher = new Cipher();
+		cipher.Init_dec(userD, c1);
+		DEROctetString data = (DEROctetString) asn1.getObjectAt(3);
+		enc = data.getOctets();
+		cipher.Decrypt(enc);
+		byte[] c3 = new byte[32];
+		cipher.Dofinal(c3);
+		return enc;
+	*/
+		//通过C1实体字节来生成ECPoint
+		ECPoint c1 = sm2.ecc_curve.decodePoint(c1Bytes);
+		Cipher cipher = new Cipher();
+		cipher.Init_dec(userD, c1);
+		cipher.Decrypt(c2);
+		cipher.Dofinal(c3);
+		//返回解密结果
+		return c2;
+	}
+	
+	public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException
+	{
+		if (privateKey == null || privateKey.length == 0)
+		{
+			return null;
+		}
+		
+		if (sourceData == null || sourceData.length == 0)
+		{
+			return null;
+		}
+		
+		SM2 sm2 = SM2.Instance();
+		BigInteger userD = new BigInteger(privateKey);
+		System.out.println("userD: " + userD.toString(16));
+		System.out.println("");
+		
+		ECPoint userKey = sm2.ecc_point_g.multiply(userD);
+		System.out.println("椭圆曲线点X: " + userKey.getX().toBigInteger().toString(16));
+		System.out.println("椭圆曲线点Y: " + userKey.getY().toBigInteger().toString(16));
+		System.out.println("");
+		
+		SM3Digest sm3 = new SM3Digest();
+		byte[] z = sm2.sm2GetZ(userId, userKey);
+		System.out.println("SM3摘要Z: " + Util.getHexString(z));
+	    System.out.println("");
+	    
+	    System.out.println("M: " + Util.getHexString(sourceData));
+		System.out.println("");
+		
+		sm3.update(z, 0, z.length);
+	    sm3.update(sourceData, 0, sourceData.length);
+	    byte[] md = new byte[32];
+	    sm3.doFinal(md, 0);
+	    
+	    System.out.println("SM3摘要值: " + Util.getHexString(md));
+	    System.out.println("");
+	    
+	    SM2Result sm2Result = new SM2Result();
+	    sm2.sm2Sign(md, userD, userKey, sm2Result);
+	    System.out.println("r: " + sm2Result.r.toString(16));
+	    System.out.println("s: " + sm2Result.s.toString(16));
+	    System.out.println("");
+	    
+	    DERInteger d_r = new DERInteger(sm2Result.r);
+	    DERInteger d_s = new DERInteger(sm2Result.s);
+	    ASN1EncodableVector v2 = new ASN1EncodableVector();
+	    v2.add(d_r);
+	    v2.add(d_s);
+	    DERObject sign = new DERSequence(v2);
+	    byte[] signdata = sign.getDEREncoded();
+		return signdata;
+	}
+	
+	@SuppressWarnings("unchecked")
+	public static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException
+	{
+		if (publicKey == null || publicKey.length == 0)
+		{
+			return false;
+		}
+		
+		if (sourceData == null || sourceData.length == 0)
+		{
+			return false;
+		}
+		
+		SM2 sm2 = SM2.Instance();
+		ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);
+		
+		SM3Digest sm3 = new SM3Digest();
+		byte[] z = sm2.sm2GetZ(userId, userKey);
+		sm3.update(z, 0, z.length);
+		sm3.update(sourceData, 0, sourceData.length);
+	    byte[] md = new byte[32];
+	    sm3.doFinal(md, 0);
+	    System.out.println("SM3摘要值: " + Util.getHexString(md));
+	    System.out.println("");
+		
+	    ByteArrayInputStream bis = new ByteArrayInputStream(signData);
+	    ASN1InputStream dis = new ASN1InputStream(bis);
+	    DERObject derObj = dis.readObject();
+	    Enumeration<DERInteger> e = ((ASN1Sequence) derObj).getObjects();
+	    BigInteger r = ((DERInteger)e.nextElement()).getValue();
+	    BigInteger s = ((DERInteger)e.nextElement()).getValue();
+	    SM2Result sm2Result = new SM2Result();
+	    sm2Result.r = r;
+	    sm2Result.s = s;
+	    System.out.println("r: " + sm2Result.r.toString(16));
+	    System.out.println("s: " + sm2Result.s.toString(16));
+	    System.out.println("");
+	    
+	    
+	    sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);
+        return sm2Result.r.equals(sm2Result.R);
+	}
+	/*
+	public static void main(String[] args) throws Exception 
+	{
+		String plainText = "message digest";
+		byte[] sourceData = plainText.getBytes();
+		
+		// 国密规范测试私钥
+		String prik = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263";
+		String prikS = new String(Base64.encode(Util.hexToByte(prik)));
+		System.out.println("prikS: " + prikS);
+		System.out.println("");
+		
+		// 国密规范测试用户ID
+		String userId = "[email protected]";
+		
+		System.out.println("ID: " + Util.getHexString(userId.getBytes()));
+		System.out.println("");
+		
+		System.out.println("签名: ");
+		byte[] c = SM2Utils.sign(userId.getBytes(), Base64.decode(prikS.getBytes()), sourceData);
+		System.out.println("sign: " + Util.getHexString(c));
+		System.out.println("");
+		
+		// 国密规范测试公钥
+		String pubk = "040AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857";
+		String pubkS = new String(Base64.encode(Util.hexToByte(pubk)));
+		System.out.println("pubkS: " + pubkS);
+		System.out.println("");
+
+		System.out.println("验签: ");
+		boolean vs = SM2Utils.verifySign(userId.getBytes(), Base64.decode(pubkS.getBytes()), sourceData, c);
+		System.out.println("验签结果: " + vs);
+		System.out.println("");
+		
+		System.out.println("加密: ");
+		byte[] cipherText = SM2Utils.encrypt(Base64.decode(pubkS.getBytes()), sourceData);
+		System.out.println(new String(Base64.encode(cipherText)));
+		System.out.println("");
+		
+		System.out.println("解密: ");
+		plainText = new String(SM2Utils.decrypt(Base64.decode(prikS.getBytes()), cipherText));
+		System.out.println(plainText);
+		
+	}
+	*/
+	public static void SM2_TEST() throws Exception
+	{
+		String plainText = "1122334455667788";
+		byte[] sourceData = Util.hexStringToBytes(plainText);
+
+		// 国密规范测试私钥
+		String prik = "969FC0F73FA117A040B37D5B5018382A74D40590EAA02809B87FA09196F8276D";
+
+		// 国密规范测试公钥
+		String pubk = "04ABC2230A05A72CEB667B20019C4F2A580E4D0A3BE9D20BF914565AB3B82631E1C0E15803FA3ADE3E6D9EEF293CBD8BAECC51D82B61404A39584198B6985686FB";
+		System.out.println("加密: ");
+		byte[] cipherText = SM2Utils.encrypt(Util.hexStringToBytes(pubk), sourceData);
+		System.out.println(Util.encodeHexString(cipherText));
+		System.out.println("");
+
+		System.out.println("解密: ");
+		String data = "04ADE0AFDD137B5E9B2CF3F4D71D329E06F3E8006598A12BB8B6A4B31F8E1D2266EFB1015812E10DC058940A3C8AB8BA29FFE788F85A5D236C3526BBA8D0E0A10D5806DAE0C2DEFADC1A49CE657D4311CDF65D9F38F1CF5004F2E4BA922EA538C9E75007CA0C7AADD8";
+		plainText = Util.encodeHexString(SM2Utils.decrypt(Util.hexStringToBytes(prik), Util.hexStringToBytes(data)));
+		System.out.println(plainText);
+
+	}
+
+
+
+}

+ 359 - 0
java源码+jar包/com/security/cipher/sm/SM3.java

@@ -0,0 +1,359 @@
+package com.security.cipher.sm;
+
+
+public class SM3 
+{
+	/*public static final byte[] iv = { 0x2C, (byte) 0x91, (byte) 0xB4, 0x01,
+			(byte) 0xFC, 0x64, (byte) 0xB2, (byte) 0xCE, 0x7C, 0x4E,
+			(byte) 0xAE, (byte) 0xFB, (byte) 0xB1, 0x3B, (byte) 0xB6,
+			(byte) 0xD3, 0x17, 0x60, (byte) 0xB6, 0x35, (byte) 0xF3, 0x6F,
+			0x13, (byte) 0xEB, (byte) 0xC8, 0x77, (byte) 0xE9, (byte) 0xA0,
+			(byte) 0xC2, 0x76, (byte) 0xA8, 0x17 };*/
+
+	public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49,
+		0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7,
+		(byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30,
+		(byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3,
+		(byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e,
+		0x4e };
+	
+	public static int[] Tj = new int[64];
+	
+	static 
+	{
+		for (int i = 0; i < 16; i++) 
+		{
+			Tj[i] = 0x79cc4519;
+		}
+	
+		for (int i = 16; i < 64; i++) 
+		{
+			Tj[i] = 0x7a879d8a;
+		}
+	}
+
+	public static byte[] CF(byte[] V, byte[] B) 
+	{
+		int[] v, b;
+		v = convert(V);
+		b = convert(B);
+		return convert(CF(v, b));
+	}
+
+	private static int[] convert(byte[] arr)
+	{
+		int[] out = new int[arr.length / 4];
+		byte[] tmp = new byte[4];
+		for (int i = 0; i < arr.length; i += 4) 
+		{
+			System.arraycopy(arr, i, tmp, 0, 4);
+			out[i / 4] = bigEndianByteToInt(tmp);
+		}
+		return out;
+	}
+
+	private static byte[] convert(int[] arr) 
+	{
+		byte[] out = new byte[arr.length * 4];
+		byte[] tmp = null;
+		for (int i = 0; i < arr.length; i++) 
+		{
+			tmp = bigEndianIntToByte(arr[i]);
+			System.arraycopy(tmp, 0, out, i * 4, 4);
+		}
+		return out;
+	}
+
+	public static int[] CF(int[] V, int[] B) 
+	{
+		int a, b, c, d, e, f, g, h;
+		int ss1, ss2, tt1, tt2;
+		a = V[0];
+		b = V[1];
+		c = V[2];
+		d = V[3];
+		e = V[4];
+		f = V[5];
+		g = V[6];
+		h = V[7];
+		
+		/*System.out.println("IV: "); 
+		System.out.print(Integer.toHexString(a)+" ");
+		System.out.print(Integer.toHexString(b)+" ");
+		System.out.print(Integer.toHexString(c)+" ");
+		System.out.print(Integer.toHexString(d)+" ");
+		System.out.print(Integer.toHexString(e)+" ");
+		System.out.print(Integer.toHexString(f)+" ");
+		System.out.print(Integer.toHexString(g)+" ");
+		System.out.print(Integer.toHexString(h)+" "); 
+		System.out.println("");
+		System.out.println("");
+		 
+		System.out.println("填充后的消息: "); 
+		for(int i=0; i<B.length; i++) 
+		{
+			System.out.print(Integer.toHexString(B[i])+" "); 
+		}
+		System.out.println("");
+		System.out.println("");*/
+		
+		int[][] arr = expand(B);
+		int[] w = arr[0];
+		int[] w1 = arr[1];
+		
+		/*System.out.println("扩展后的消息: ");
+		System.out.println("W0W1...W67"); 
+		print(w); 
+		System.out.println("");
+		System.out.println("W'0W'1...W'67");
+		print(w1);
+		System.out.println("迭代压缩中间值: ");*/
+		
+		for (int j = 0; j < 64; j++)
+		{
+			ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));
+			ss1 = bitCycleLeft(ss1, 7);
+			ss2 = ss1 ^ bitCycleLeft(a, 12);
+			tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];
+			tt2 = GGj(e, f, g, j) + h + ss1 + w[j];
+			d = c;
+			c = bitCycleLeft(b, 9);
+			b = a;
+			a = tt1;
+			h = g;
+			g = bitCycleLeft(f, 19);
+			f = e;
+			e = P0(tt2);
+
+			/*System.out.print(j+" ");
+			System.out.print(Integer.toHexString(a)+" ");
+			System.out.print(Integer.toHexString(b)+" ");
+			System.out.print(Integer.toHexString(c)+" ");
+			System.out.print(Integer.toHexString(d)+" ");
+			System.out.print(Integer.toHexString(e)+" ");
+			System.out.print(Integer.toHexString(f)+" ");
+			System.out.print(Integer.toHexString(g)+" ");
+			System.out.print(Integer.toHexString(h)+" ");
+			System.out.println("");*/
+		}
+//		System.out.println("");
+
+		int[] out = new int[8];
+		out[0] = a ^ V[0];
+		out[1] = b ^ V[1];
+		out[2] = c ^ V[2];
+		out[3] = d ^ V[3];
+		out[4] = e ^ V[4];
+		out[5] = f ^ V[5];
+		out[6] = g ^ V[6];
+		out[7] = h ^ V[7];
+
+		return out;
+	}
+
+	private static int[][] expand(int[] B) 
+	{
+		int W[] = new int[68];
+		int W1[] = new int[64];
+		for (int i = 0; i < B.length; i++)
+		{
+			W[i] = B[i];
+		}
+
+		for (int i = 16; i < 68; i++) 
+		{
+			W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15))
+					^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6];
+		}
+
+		for (int i = 0; i < 64; i++) 
+		{
+			W1[i] = W[i] ^ W[i + 4];
+		}
+
+		int arr[][] = new int[][] { W, W1 };
+		return arr;
+	}
+
+	private static byte[] bigEndianIntToByte(int num) 
+	{
+		return back(Util.intToBytes(num));
+	}
+
+	private static int bigEndianByteToInt(byte[] bytes)
+	{
+		return Util.byteToInt(back(bytes));
+	}
+
+	private static int FFj(int X, int Y, int Z, int j) 
+	{
+		if (j >= 0 && j <= 15) 
+		{
+			return FF1j(X, Y, Z);
+		}
+		else 
+		{
+			return FF2j(X, Y, Z);
+		}
+	}
+
+	private static int GGj(int X, int Y, int Z, int j) 
+	{
+		if (j >= 0 && j <= 15) 
+		{
+			return GG1j(X, Y, Z);
+		}
+		else
+		{
+			return GG2j(X, Y, Z);
+		}
+	}
+
+	// 逻辑位运算函数
+	private static int FF1j(int X, int Y, int Z)
+	{
+		int tmp = X ^ Y ^ Z;
+		return tmp;
+	}
+
+	private static int FF2j(int X, int Y, int Z)
+	{
+		int tmp = ((X & Y) | (X & Z) | (Y & Z));
+		return tmp;
+	}
+
+	private static int GG1j(int X, int Y, int Z) 
+	{
+		int tmp = X ^ Y ^ Z;
+		return tmp;
+	}
+
+	private static int GG2j(int X, int Y, int Z) 
+	{
+		int tmp = (X & Y) | (~X & Z);
+		return tmp;
+	}
+
+	private static int P0(int X) 
+	{
+		int y = rotateLeft(X, 9);
+		y = bitCycleLeft(X, 9);
+		int z = rotateLeft(X, 17);
+		z = bitCycleLeft(X, 17);
+		int t = X ^ y ^ z;
+		return t;
+	}
+
+	private static int P1(int X) 
+	{
+		int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);
+		return t;
+	}
+
+	/**
+	 * 对最后一个分组字节数据padding
+	 * 
+	 * @param in
+	 * @param bLen
+	 *            分组个数
+	 * @return
+	 */
+	public static byte[] padding(byte[] in, int bLen)
+	{
+		int k = 448 - (8 * in.length + 1) % 512;
+		if (k < 0) 
+		{
+			k = 960 - (8 * in.length + 1) % 512;
+		}
+		k += 1;
+		byte[] padd = new byte[k / 8];
+		padd[0] = (byte) 0x80;
+		long n = in.length * 8 + bLen * 512;
+		byte[] out = new byte[in.length + k / 8 + 64 / 8];
+		int pos = 0;
+		System.arraycopy(in, 0, out, 0, in.length);
+		pos += in.length;
+		System.arraycopy(padd, 0, out, pos, padd.length);
+		pos += padd.length;
+		byte[] tmp = back(Util.longToBytes(n));
+		System.arraycopy(tmp, 0, out, pos, tmp.length);
+		return out;
+	}
+
+	/**
+	 * 字节数组逆序
+	 * 
+	 * @param in
+	 * @return
+	 */
+	private static byte[] back(byte[] in) 
+	{
+		byte[] out = new byte[in.length];
+		for (int i = 0; i < out.length; i++) 
+		{
+			out[i] = in[out.length - i - 1];
+		}
+
+		return out;
+	}
+
+	public static int rotateLeft(int x, int n) 
+	{
+		return (x << n) | (x >> (32 - n));
+	}
+
+	private static int bitCycleLeft(int n, int bitLen) 
+	{
+		bitLen %= 32;
+		byte[] tmp = bigEndianIntToByte(n);
+		int byteLen = bitLen / 8;
+		int len = bitLen % 8;
+		if (byteLen > 0)
+		{
+			tmp = byteCycleLeft(tmp, byteLen);
+		}
+
+		if (len > 0) 
+		{
+			tmp = bitSmall8CycleLeft(tmp, len);
+		}
+
+		return bigEndianByteToInt(tmp);
+	}
+
+	private static byte[] bitSmall8CycleLeft(byte[] in, int len) 
+	{
+		byte[] tmp = new byte[in.length];
+		int t1, t2, t3;
+		for (int i = 0; i < tmp.length; i++)
+		{
+			t1 = (byte) ((in[i] & 0x000000ff) << len);
+			t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len));
+			t3 = (byte) (t1 | t2);
+			tmp[i] = (byte) t3;
+		}
+
+		return tmp;
+	}
+
+	private static byte[] byteCycleLeft(byte[] in, int byteLen) 
+	{
+		byte[] tmp = new byte[in.length];
+		System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen);
+		System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen);
+		return tmp;
+	}
+	
+	/*private static void print(int[] arr)
+	{
+		for (int i = 0; i < arr.length; i++)
+		{
+			System.out.print(Integer.toHexString(arr[i]) + " ");
+			if ((i + 1) % 16 == 0) 
+			{
+				System.out.println();
+			}
+		}
+		System.out.println();
+	}*/
+}

+ 145 - 0
java源码+jar包/com/security/cipher/sm/SM3Digest.java

@@ -0,0 +1,145 @@
+package com.security.cipher.sm;
+
+import org.bouncycastle.util.encoders.Hex;
+
+public class SM3Digest
+{
+	/** SM3值的长度 */
+	private static final int BYTE_LENGTH = 32;
+	
+	/** SM3分组长度 */
+	private static final int BLOCK_LENGTH = 64;
+	
+	/** 缓冲区长度 */
+	private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1;
+	
+	/** 缓冲区 */
+	private byte[] xBuf = new byte[BUFFER_LENGTH];
+	
+	/** 缓冲区偏移量 */
+	private int xBufOff;
+	
+	/** 初始向量 */
+	private byte[] V = SM3.iv.clone();
+	
+	private int cntBlock = 0;
+
+	public SM3Digest() {
+	}
+
+	public SM3Digest(SM3Digest t)
+	{
+		System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
+		this.xBufOff = t.xBufOff;
+		System.arraycopy(t.V, 0, this.V, 0, t.V.length);
+	}
+	
+	/**
+	 * SM3结果输出
+	 * 
+	 * @param out 保存SM3结构的缓冲区
+	 * @param outOff 缓冲区偏移量
+	 * @return
+	 */
+	public int doFinal(byte[] out, int outOff) 
+	{
+		byte[] tmp = doFinal();
+		System.arraycopy(tmp, 0, out, 0, tmp.length);
+		return BYTE_LENGTH;
+	}
+
+	public void reset() 
+	{
+		xBufOff = 0;
+		cntBlock = 0;
+		V = SM3.iv.clone();
+	}
+
+	/**
+	 * 明文输入
+	 * 
+	 * @param in
+	 *            明文输入缓冲区
+	 * @param inOff
+	 *            缓冲区偏移量
+	 * @param len
+	 *            明文长度
+	 */
+	public void update(byte[] in, int inOff, int len)
+	{
+		int partLen = BUFFER_LENGTH - xBufOff;
+		int inputLen = len;
+		int dPos = inOff;
+		if (partLen < inputLen) 
+		{
+			System.arraycopy(in, dPos, xBuf, xBufOff, partLen);
+			inputLen -= partLen;
+			dPos += partLen;
+			doUpdate();
+			while (inputLen > BUFFER_LENGTH) 
+			{
+				System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH);
+				inputLen -= BUFFER_LENGTH;
+				dPos += BUFFER_LENGTH;
+				doUpdate();
+			}
+		}
+
+		System.arraycopy(in, dPos, xBuf, xBufOff, inputLen);
+		xBufOff += inputLen;
+	}
+
+	private void doUpdate() 
+	{
+		byte[] B = new byte[BLOCK_LENGTH];
+		for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH) 
+		{
+			System.arraycopy(xBuf, i, B, 0, B.length);
+			doHash(B);
+		}
+		xBufOff = 0;
+	}
+
+	private void doHash(byte[] B)
+	{
+		byte[] tmp = SM3.CF(V, B);
+		System.arraycopy(tmp, 0, V, 0, V.length);
+		cntBlock++;
+	}
+
+	private byte[] doFinal() 
+	{
+		byte[] B = new byte[BLOCK_LENGTH];
+		byte[] buffer = new byte[xBufOff];
+		System.arraycopy(xBuf, 0, buffer, 0, buffer.length);
+		byte[] tmp = SM3.padding(buffer, cntBlock);
+		for (int i = 0; i < tmp.length; i += BLOCK_LENGTH)
+		{
+			System.arraycopy(tmp, i, B, 0, B.length);
+			doHash(B);
+		}
+		return V;
+	}
+
+	public void update(byte in) 
+	{
+		byte[] buffer = new byte[] { in };
+		update(buffer, 0, 1);
+	}
+	
+	public int getDigestSize() 
+	{
+		return BYTE_LENGTH;
+	}
+	
+	public static void main(String[] args) 
+	{
+		byte[] md = new byte[32];
+		byte[] msg1 = "abc".getBytes();
+		SM3Digest sm3 = new SM3Digest();
+		sm3.update(msg1, 0, msg1.length);
+		sm3.doFinal(md, 0);
+		String s = new String(Hex.encode(md));
+		System.out.println(s);
+	}
+}

+ 344 - 0
java源码+jar包/com/security/cipher/sm/SM4.java

@@ -0,0 +1,344 @@
+package com.security.cipher.sm;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+public class SM4 
+{
+	public static final int SM4_ENCRYPT = 1;
+	
+	public static final int SM4_DECRYPT = 0;
+
+	private long GET_ULONG_BE(byte[] b, int i) 
+	{
+		long n = (long)(b[i] & 0xff) << 24 | (long)((b[i + 1] & 0xff) << 16) | (long)((b[i + 2] & 0xff) << 8) | (long)(b[i + 3] & 0xff) & 0xffffffffL;
+		return n;
+	}
+
+	private void PUT_ULONG_BE(long n, byte[] b, int i) 
+	{
+		b[i] = (byte)(int)(0xFF & n >> 24);
+        b[i + 1] = (byte)(int)(0xFF & n >> 16);
+        b[i + 2] = (byte)(int)(0xFF & n >> 8);
+        b[i + 3] = (byte)(int)(0xFF & n);
+	}
+
+	private long SHL(long x, int n) 
+	{
+		return (x & 0xFFFFFFFF) << n;
+	}
+	
+	private long ROTL(long x, int n) 
+	{
+		return SHL(x, n) | x >> (32 - n);
+	}
+	
+	private void SWAP(long[] sk, int i)
+	{
+		long t = sk[i];
+		sk[i] = sk[(31 - i)];
+		sk[(31 - i)] = t;
+	}
+	
+	public static final byte[] SboxTable = { (byte) 0xd6, (byte) 0x90, (byte) 0xe9, (byte) 0xfe,
+		(byte) 0xcc, (byte) 0xe1, 0x3d, (byte) 0xb7, 0x16, (byte) 0xb6,
+		0x14, (byte) 0xc2, 0x28, (byte) 0xfb, 0x2c, 0x05, 0x2b, 0x67,
+		(byte) 0x9a, 0x76, 0x2a, (byte) 0xbe, 0x04, (byte) 0xc3,
+		(byte) 0xaa, 0x44, 0x13, 0x26, 0x49, (byte) 0x86, 0x06,
+		(byte) 0x99, (byte) 0x9c, 0x42, 0x50, (byte) 0xf4, (byte) 0x91,
+		(byte) 0xef, (byte) 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43,
+		(byte) 0xed, (byte) 0xcf, (byte) 0xac, 0x62, (byte) 0xe4,
+		(byte) 0xb3, 0x1c, (byte) 0xa9, (byte) 0xc9, 0x08, (byte) 0xe8,
+		(byte) 0x95, (byte) 0x80, (byte) 0xdf, (byte) 0x94, (byte) 0xfa,
+		0x75, (byte) 0x8f, 0x3f, (byte) 0xa6, 0x47, 0x07, (byte) 0xa7,
+		(byte) 0xfc, (byte) 0xf3, 0x73, 0x17, (byte) 0xba, (byte) 0x83,
+		0x59, 0x3c, 0x19, (byte) 0xe6, (byte) 0x85, 0x4f, (byte) 0xa8,
+		0x68, 0x6b, (byte) 0x81, (byte) 0xb2, 0x71, 0x64, (byte) 0xda,
+		(byte) 0x8b, (byte) 0xf8, (byte) 0xeb, 0x0f, 0x4b, 0x70, 0x56,
+		(byte) 0x9d, 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, (byte) 0xd1,
+		(byte) 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, (byte) 0x87,
+		(byte) 0xd4, 0x00, 0x46, 0x57, (byte) 0x9f, (byte) 0xd3, 0x27,
+		0x52, 0x4c, 0x36, 0x02, (byte) 0xe7, (byte) 0xa0, (byte) 0xc4,
+		(byte) 0xc8, (byte) 0x9e, (byte) 0xea, (byte) 0xbf, (byte) 0x8a,
+		(byte) 0xd2, 0x40, (byte) 0xc7, 0x38, (byte) 0xb5, (byte) 0xa3,
+		(byte) 0xf7, (byte) 0xf2, (byte) 0xce, (byte) 0xf9, 0x61, 0x15,
+		(byte) 0xa1, (byte) 0xe0, (byte) 0xae, 0x5d, (byte) 0xa4,
+		(byte) 0x9b, 0x34, 0x1a, 0x55, (byte) 0xad, (byte) 0x93, 0x32,
+		0x30, (byte) 0xf5, (byte) 0x8c, (byte) 0xb1, (byte) 0xe3, 0x1d,
+		(byte) 0xf6, (byte) 0xe2, 0x2e, (byte) 0x82, 0x66, (byte) 0xca,
+		0x60, (byte) 0xc0, 0x29, 0x23, (byte) 0xab, 0x0d, 0x53, 0x4e, 0x6f,
+		(byte) 0xd5, (byte) 0xdb, 0x37, 0x45, (byte) 0xde, (byte) 0xfd,
+		(byte) 0x8e, 0x2f, 0x03, (byte) 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b,
+		0x51, (byte) 0x8d, 0x1b, (byte) 0xaf, (byte) 0x92, (byte) 0xbb,
+		(byte) 0xdd, (byte) 0xbc, 0x7f, 0x11, (byte) 0xd9, 0x5c, 0x41,
+		0x1f, 0x10, 0x5a, (byte) 0xd8, 0x0a, (byte) 0xc1, 0x31,
+		(byte) 0x88, (byte) 0xa5, (byte) 0xcd, 0x7b, (byte) 0xbd, 0x2d,
+		0x74, (byte) 0xd0, 0x12, (byte) 0xb8, (byte) 0xe5, (byte) 0xb4,
+		(byte) 0xb0, (byte) 0x89, 0x69, (byte) 0x97, 0x4a, 0x0c,
+		(byte) 0x96, 0x77, 0x7e, 0x65, (byte) 0xb9, (byte) 0xf1, 0x09,
+		(byte) 0xc5, 0x6e, (byte) 0xc6, (byte) 0x84, 0x18, (byte) 0xf0,
+		0x7d, (byte) 0xec, 0x3a, (byte) 0xdc, 0x4d, 0x20, 0x79,
+		(byte) 0xee, 0x5f, 0x3e, (byte) 0xd7, (byte) 0xcb, 0x39, 0x48 };
+	
+	public static final int[] FK = { 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc };
+	
+	public static final int[] CK = { 0x00070e15,0x1c232a31,0x383f464d,0x545b6269,
+		0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9,
+		0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,
+		0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9,
+		0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,
+		0x30373e45,0x4c535a61,0x686f767d,0x848b9299,
+		0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,
+		0x10171e25,0x2c333a41,0x484f565d,0x646b7279 };
+
+	private byte sm4Sbox(byte inch)
+	{
+		int i = inch & 0xFF;
+		byte retVal = SboxTable[i];
+		return retVal;
+	}
+
+	private long sm4Lt(long ka) 
+	{
+		long bb = 0L;
+		long c = 0L;
+		byte[] a = new byte[4];
+		byte[] b = new byte[4];
+		PUT_ULONG_BE(ka, a, 0);
+		b[0] = sm4Sbox(a[0]);
+		b[1] = sm4Sbox(a[1]);
+		b[2] = sm4Sbox(a[2]);
+		b[3] = sm4Sbox(a[3]);
+		bb = GET_ULONG_BE(b, 0);
+		c = bb ^ ROTL(bb, 2) ^ ROTL(bb, 10) ^ ROTL(bb, 18) ^ ROTL(bb, 24);
+		return c;
+	}
+
+	private long sm4F(long x0, long x1, long x2, long x3, long rk)
+	{
+		return x0 ^ sm4Lt(x1 ^ x2 ^ x3 ^ rk);
+	}
+
+	private long sm4CalciRK(long ka) 
+	{
+		long bb = 0L;
+		long rk = 0L;
+		byte[] a = new byte[4];
+		byte[] b = new byte[4];
+		PUT_ULONG_BE(ka, a, 0);
+		b[0] = sm4Sbox(a[0]);
+		b[1] = sm4Sbox(a[1]);
+		b[2] = sm4Sbox(a[2]);
+		b[3] = sm4Sbox(a[3]);
+		bb = GET_ULONG_BE(b, 0);
+		rk = bb ^ ROTL(bb, 13) ^ ROTL(bb, 23);
+		return rk;
+	}
+
+	private void sm4_setkey(long[] SK, byte[] key) 
+	{
+		long[] MK = new long[4];
+		long[] k = new long[36];
+		int i = 0;
+		MK[0] = GET_ULONG_BE(key, 0);
+		MK[1] = GET_ULONG_BE(key, 4);
+		MK[2] = GET_ULONG_BE(key, 8);
+		MK[3] = GET_ULONG_BE(key, 12);
+		k[0] = MK[0] ^ (long) FK[0];
+		k[1] = MK[1] ^ (long) FK[1];
+		k[2] = MK[2] ^ (long) FK[2];
+		k[3] = MK[3] ^ (long) FK[3];
+		for (; i < 32; i++) 
+		{
+			k[(i + 4)] = (k[i] ^ sm4CalciRK(k[(i + 1)] ^ k[(i + 2)] ^ k[(i + 3)] ^ (long) CK[i]));
+			SK[i] = k[(i + 4)];
+		}
+	}
+
+	private void sm4_one_round(long[] sk, byte[] input, byte[] output) 
+	{
+		int i = 0;
+		long[] ulbuf = new long[36];
+		ulbuf[0] = GET_ULONG_BE(input, 0);
+		ulbuf[1] = GET_ULONG_BE(input, 4);
+		ulbuf[2] = GET_ULONG_BE(input, 8);
+		ulbuf[3] = GET_ULONG_BE(input, 12);
+		while (i < 32)
+		{
+			ulbuf[(i + 4)] = sm4F(ulbuf[i], ulbuf[(i + 1)], ulbuf[(i + 2)], ulbuf[(i + 3)], sk[i]);
+			i++;
+		}
+		PUT_ULONG_BE(ulbuf[35], output, 0);
+		PUT_ULONG_BE(ulbuf[34], output, 4);
+		PUT_ULONG_BE(ulbuf[33], output, 8);
+		PUT_ULONG_BE(ulbuf[32], output, 12);
+	}
+
+	private byte[] padding(byte[] input, int mode)
+	{
+		if (input == null) 
+		{
+			return null;
+		}
+		
+		byte[] ret = (byte[]) null;
+		if (mode == SM4_ENCRYPT) 
+		{
+			int p = 16 - input.length % 16;
+			ret = new byte[input.length + p];
+			System.arraycopy(input, 0, ret, 0, input.length);
+			for (int i = 0; i < p; i++) 
+			{
+				ret[input.length + i] = (byte) p;
+			}
+		} 
+		else 
+		{
+			int p = input[input.length - 1];
+			ret = new byte[input.length - p];
+			System.arraycopy(input, 0, ret, 0, input.length - p);
+		}
+		return ret;
+	}
+
+	public void sm4_setkey_enc(SM4_Context ctx, byte[] key) throws Exception
+	{
+		if (ctx == null) 
+		{
+			throw new Exception("ctx is null!");
+		}
+		
+		if (key == null || key.length != 16) 
+		{
+			throw new Exception("key error!");
+		}
+		
+		ctx.mode = SM4_ENCRYPT;
+		sm4_setkey(ctx.sk, key);
+	}
+
+	public void sm4_setkey_dec(SM4_Context ctx, byte[] key) throws Exception
+	{
+		if (ctx == null) 
+		{
+			throw new Exception("ctx is null!");
+		}
+		
+		if (key == null || key.length != 16) 
+		{
+			throw new Exception("key error!");
+		}
+		
+		int i = 0;
+		ctx.mode = SM4_DECRYPT;
+		sm4_setkey(ctx.sk, key);
+		for (i = 0; i < 16; i++) 
+		{
+			SWAP(ctx.sk, i);
+		}
+	}
+
+	public byte[] sm4_crypt_ecb(SM4_Context ctx, byte[] input) throws Exception 
+	{
+		if (input == null) 
+		{
+			throw new Exception("input is null!");
+		}
+	
+		if ((ctx.isPadding) && (ctx.mode == SM4_ENCRYPT)) 
+		{
+			input = padding(input, SM4_ENCRYPT);
+		}
+		
+		int length = input.length;
+		ByteArrayInputStream bins = new ByteArrayInputStream(input);
+		ByteArrayOutputStream bous = new ByteArrayOutputStream();
+		for(; length > 0; length -= 16)
+		{
+			byte[] in = new byte[16];
+			byte[] out = new byte[16];
+			bins.read(in);
+			sm4_one_round(ctx.sk, in, out);
+			bous.write(out);
+		}
+		
+		byte[] output = bous.toByteArray();
+		if (ctx.isPadding && ctx.mode == SM4_DECRYPT) 
+		{
+			output = padding(output, SM4_DECRYPT);
+		}
+		bins.close();
+		bous.close();
+		return output;
+	}
+
+	public byte[] sm4_crypt_cbc(SM4_Context ctx, byte[] iv, byte[] input) throws Exception
+	{
+		if (iv == null || iv.length != 16)
+		{
+			throw new Exception("iv error!");
+		}
+		
+		if (input == null) 
+		{
+			throw new Exception("input is null!");
+		}
+		
+		if (ctx.isPadding && ctx.mode == SM4_ENCRYPT) 
+		{
+			input = padding(input, SM4_ENCRYPT);
+		}
+		
+		int i = 0;
+		int length = input.length;
+		ByteArrayInputStream bins = new ByteArrayInputStream(input);
+		ByteArrayOutputStream bous = new ByteArrayOutputStream();
+		if (ctx.mode == SM4_ENCRYPT) 
+		{
+			for(; length > 0; length -= 16)
+			{
+				byte[] in = new byte[16];
+				byte[] out = new byte[16];
+				byte[] out1 = new byte[16];
+				
+				bins.read(in);
+				for (i = 0; i < 16; i++) 
+				{
+					out[i] = ((byte) (in[i] ^ iv[i]));
+				}
+				sm4_one_round(ctx.sk, out, out1);
+				System.arraycopy(out1, 0, iv, 0, 16);
+				bous.write(out1);
+			}
+		} 
+		else 
+		{
+			byte[] temp = new byte[16];
+			for(; length > 0; length -= 16)
+			{
+				byte[] in = new byte[16];
+				byte[] out = new byte[16];
+				byte[] out1 = new byte[16];
+				
+				bins.read(in);
+				System.arraycopy(in, 0, temp, 0, 16);
+				sm4_one_round(ctx.sk, in, out);
+				for (i = 0; i < 16; i++) 
+				{
+					out1[i] = ((byte) (out[i] ^ iv[i]));
+				}
+				System.arraycopy(temp, 0, iv, 0, 16);
+				bous.write(out1);
+			}
+		}
+		
+		byte[] output = bous.toByteArray();
+		if (ctx.isPadding && ctx.mode == SM4_DECRYPT) 
+		{
+			output = padding(output, SM4_DECRYPT);
+		}
+		bins.close();
+		bous.close();
+		return output;
+	}
+}

+ 211 - 0
java源码+jar包/com/security/cipher/sm/SM4Utils.java

@@ -0,0 +1,211 @@
+package com.security.cipher.sm;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import Decoder.BASE64Decoder;
+import Decoder.BASE64Encoder;
+
+public class SM4Utils
+{
+	private String secretKey = "";
+	
+	private String iv = "";
+	
+	private boolean hexString = true;
+	
+	public SM4Utils()
+	{
+	}
+
+	public void SetSecretKey(String Key)
+	{
+		this.secretKey = Key;
+	}
+	
+	public String encryptData_ECB(String plainText)
+	{
+		try 
+		{
+			SM4_Context ctx = new SM4_Context();
+			ctx.isPadding = false;
+			ctx.mode = SM4.SM4_ENCRYPT;
+			
+			byte[] keyBytes;
+			if (hexString)
+			{
+				keyBytes = Util.hexStringToBytes(secretKey);
+			}
+			else
+			{
+				keyBytes = secretKey.getBytes();
+			}
+			
+			SM4 sm4 = new SM4();
+			sm4.sm4_setkey_enc(ctx, keyBytes);
+			byte[] encrypted = sm4.sm4_crypt_ecb(ctx, Util.hexStringToBytes(plainText));
+
+			String cipherText = Util.encodeHexString(encrypted);
+			//String cipherText = new String(encrypted);
+			//Log.e("test1",cipherText);
+			/*
+			String cipherText = new BASE64Encoder().encode(encrypted);
+			if (cipherText != null && cipherText.trim().length() > 0)
+			{
+				Pattern p = Pattern.compile("\\s*|\t|\r|\n");
+				Matcher m = p.matcher(cipherText);
+				cipherText = m.replaceAll("");
+			}*/
+			return cipherText;
+		} 
+		catch (Exception e) 
+		{
+			e.printStackTrace();
+			return null;
+		}
+	}
+	
+	public String decryptData_ECB(String cipherText)
+	{
+		try 
+		{
+			SM4_Context ctx = new SM4_Context();
+			ctx.isPadding = false;
+			ctx.mode = SM4.SM4_DECRYPT;
+			
+			byte[] keyBytes;
+			if (hexString)
+			{
+				keyBytes = Util.hexStringToBytes(secretKey);
+			}
+			else
+			{
+				keyBytes = secretKey.getBytes();
+			}
+			
+			SM4 sm4 = new SM4();
+			sm4.sm4_setkey_dec(ctx, keyBytes);
+			byte[] decrypted = sm4.sm4_crypt_ecb(ctx, Util.hexStringToBytes(cipherText));
+			return Util.encodeHexString(decrypted);
+		} 
+		catch (Exception e) 
+		{
+			e.printStackTrace();
+			return null;
+		}
+	}
+	
+	public String encryptData_CBC(String plainText)
+	{
+		try 
+		{
+			SM4_Context ctx = new SM4_Context();
+			ctx.isPadding = false;
+			ctx.mode = SM4.SM4_ENCRYPT;
+			
+			byte[] keyBytes;
+			byte[] ivBytes;
+			if (hexString)
+			{
+				keyBytes = Util.hexStringToBytes(secretKey);
+				ivBytes = Util.hexStringToBytes(iv);
+			}
+			else
+			{
+				keyBytes = secretKey.getBytes();
+				ivBytes = iv.getBytes();
+			}
+			
+			SM4 sm4 = new SM4();
+			sm4.sm4_setkey_enc(ctx, keyBytes);
+			byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes("GBK"));
+			String cipherText = new BASE64Encoder().encode(encrypted);
+			if (cipherText != null && cipherText.trim().length() > 0)
+			{
+				Pattern p = Pattern.compile("\\s*|\t|\r|\n");
+				Matcher m = p.matcher(cipherText);
+				cipherText = m.replaceAll("");
+			}
+			return cipherText;
+		} 
+		catch (Exception e) 
+		{
+			e.printStackTrace();
+			return null;
+		}
+	}
+	
+	public String decryptData_CBC(String cipherText)
+	{
+		try 
+		{
+			SM4_Context ctx = new SM4_Context();
+			ctx.isPadding = false;
+			ctx.mode = SM4.SM4_DECRYPT;
+			
+			byte[] keyBytes;
+			byte[] ivBytes;
+			if (hexString)
+			{
+				keyBytes = Util.hexStringToBytes(secretKey);
+				ivBytes = Util.hexStringToBytes(iv);
+			}
+			else
+			{
+				keyBytes = secretKey.getBytes();
+				ivBytes = iv.getBytes();
+			}
+			
+			SM4 sm4 = new SM4();
+			sm4.sm4_setkey_dec(ctx, keyBytes);
+			byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, new BASE64Decoder().decodeBuffer(cipherText));
+			return new String(decrypted, "GBK");
+		} 
+		catch (Exception e)
+		{
+			e.printStackTrace();
+			return null;
+		}
+	}
+	/*
+	public static void main(String[] args) throws IOException 
+	{
+		String plainText = "abcd";
+		
+		SM4Utils sm4 = new SM4Utils();
+		sm4.secretKey = "JeF8U9wHFOMfs2Y8";
+		sm4.hexString = false;
+		
+		System.out.println("ECB模式");
+		String cipherText = sm4.encryptData_ECB(plainText);
+		System.out.println("密文: " + cipherText);
+		System.out.println("");
+		
+		plainText = sm4.decryptData_ECB(cipherText);
+		System.out.println("明文: " + plainText);
+		System.out.println("");
+		
+		System.out.println("CBC模式");
+		sm4.iv = "UISwD9fW6cFh9SNS";
+		cipherText = sm4.encryptData_CBC(plainText);
+		System.out.println("密文: " + cipherText);
+		System.out.println("");
+		
+		plainText = sm4.decryptData_CBC(cipherText);
+		System.out.println("明文: " + plainText);
+	}*/
+	public static void SM4_ECB_TEST() throws IOException {
+
+		String plainText = "11223344556677888877665544332211";
+		String sm4_Key = "00000000000000008888888888888888";
+		SM4Utils sm4Utils = new SM4Utils();
+		sm4Utils.SetSecretKey(sm4_Key);
+		String encryptdata = sm4Utils.encryptData_ECB(plainText);
+		//txt.setText(encryptdata);
+		System.out.println("密文: " + encryptdata);
+		String decryptdata = sm4Utils.decryptData_ECB(encryptdata);
+		System.out.println("密文: " + decryptdata);
+	}
+}
+

+ 17 - 0
java源码+jar包/com/security/cipher/sm/SM4_Context.java

@@ -0,0 +1,17 @@
+package com.security.cipher.sm;
+
+public class SM4_Context
+{
+	public int mode;
+	
+	public long[] sk;
+	
+	public boolean isPadding;
+
+	public SM4_Context() 
+	{
+		this.mode = 1;
+		this.isPadding = false;
+		this.sk = new long[32];
+	}
+}

+ 662 - 0
java源码+jar包/com/security/cipher/sm/Util.java

@@ -0,0 +1,662 @@
+package com.security.cipher.sm;
+
+import java.math.BigInteger;
+
+public class Util 
+{
+	/**
+	 * 整形转换成网络传输的字节流(字节数组)型数据
+	 * 
+	 * @param num 一个整型数据
+	 * @return 4个字节的自己数组
+	 */
+	public static byte[] intToBytes(int num)
+	{
+		byte[] bytes = new byte[4];
+		bytes[0] = (byte) (0xff & (num >> 0));
+		bytes[1] = (byte) (0xff & (num >> 8));
+		bytes[2] = (byte) (0xff & (num >> 16));
+		bytes[3] = (byte) (0xff & (num >> 24));
+		return bytes;
+	}
+
+	/**
+	 * 四个字节的字节数据转换成一个整形数据
+	 * 
+	 * @param bytes 4个字节的字节数组
+	 * @return 一个整型数据
+	 */
+	public static int byteToInt(byte[] bytes) 
+	{
+		int num = 0;
+		int temp;
+		temp = (0x000000ff & (bytes[0])) << 0;
+		num = num | temp;
+		temp = (0x000000ff & (bytes[1])) << 8;
+		num = num | temp;
+		temp = (0x000000ff & (bytes[2])) << 16;
+		num = num | temp;
+		temp = (0x000000ff & (bytes[3])) << 24;
+		num = num | temp;
+		return num;
+	}
+
+	/**
+	 * 长整形转换成网络传输的字节流(字节数组)型数据
+	 * 
+	 * @param num 一个长整型数据
+	 * @return 4个字节的自己数组
+	 */
+	public static byte[] longToBytes(long num) 
+	{
+		byte[] bytes = new byte[8];
+		for (int i = 0; i < 8; i++) 
+		{
+			bytes[i] = (byte) (0xff & (num >> (i * 8)));
+		}
+
+		return bytes;
+	}
+
+	/**
+	 * 大数字转换字节流(字节数组)型数据
+	 * 
+	 * @param n
+	 * @return
+	 */
+	public static byte[] byteConvert32Bytes(BigInteger n) 
+	{
+		byte tmpd[] = (byte[])null;
+        if(n == null)
+        {
+        	return null;
+        }
+        
+        if(n.toByteArray().length == 33)
+        {
+            tmpd = new byte[32];
+            System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
+        } 
+        else if(n.toByteArray().length == 32)
+        {
+            tmpd = n.toByteArray();
+        } 
+        else
+        {
+            tmpd = new byte[32];
+            for(int i = 0; i < 32 - n.toByteArray().length; i++)
+            {
+            	tmpd[i] = 0;
+            }
+            System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);
+        }
+        return tmpd;
+	}
+	
+	/**
+	 * 换字节流(字节数组)型数据转大数字
+	 * 
+	 * @param b
+	 * @return
+	 */
+	public static BigInteger byteConvertInteger(byte[] b)
+	{
+	    if (b[0] < 0)
+	    {
+	    	byte[] temp = new byte[b.length + 1];
+	    	temp[0] = 0;
+	    	System.arraycopy(b, 0, temp, 1, b.length);
+	    	return new BigInteger(temp);
+	    }
+	    return new BigInteger(b);
+	}
+	
+	/**
+	 * 根据字节数组获得值(十六进制数字)
+	 * 
+	 * @param bytes
+	 * @return
+	 */
+	public static String getHexString(byte[] bytes) 
+	{
+		return getHexString(bytes, true);
+	}
+	
+	/**
+	 * 根据字节数组获得值(十六进制数字)
+	 * 
+	 * @param bytes
+	 * @param upperCase
+	 * @return
+	 */
+	public static String getHexString(byte[] bytes, boolean upperCase) 
+	{
+		String ret = "";
+		for (int i = 0; i < bytes.length; i++) 
+		{
+			ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
+		}
+		return upperCase ? ret.toUpperCase() : ret;
+	}
+	
+	/**
+	 * 打印十六进制字符串
+	 * 
+	 * @param bytes
+	 */
+	public static void printHexString(byte[] bytes) 
+	{
+		for (int i = 0; i < bytes.length; i++) 
+		{
+			String hex = Integer.toHexString(bytes[i] & 0xFF);
+			if (hex.length() == 1) 
+			{
+				hex = '0' + hex;
+			}
+			System.out.print("0x" + hex.toUpperCase() + ",");
+		}
+		System.out.println("");
+	}
+	
+	/**
+	 * Convert hex string to byte[]
+	 * 
+	 * @param hexString
+	 *            the hex string
+	 * @return byte[]
+	 */
+	public static byte[] hexStringToBytes(String hexString) 
+	{
+		if (hexString == null || hexString.equals("")) 
+		{
+			return null;
+		}
+		
+		hexString = hexString.toUpperCase();
+		int length = hexString.length() / 2;
+		char[] hexChars = hexString.toCharArray();
+		byte[] d = new byte[length];
+		for (int i = 0; i < length; i++) 
+		{
+			int pos = i * 2;
+			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
+		}
+		return d;
+	}
+	
+	/**
+	 * Convert char to byte
+	 * 
+	 * @param c
+	 *            char
+	 * @return byte
+	 */
+	public static byte charToByte(char c) 
+	{
+		return (byte) "0123456789ABCDEF".indexOf(c);
+	}
+	
+	/**
+     * 用于建立十六进制字符的输出的小写字符数组
+     */
+    private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
+            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+ 
+    /**
+     * 用于建立十六进制字符的输出的大写字符数组
+     */
+    private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
+            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ 
+    /**
+     * 将字节数组转换为十六进制字符数组
+     *
+     * @param data byte[]
+     * @return 十六进制char[]
+     */
+    public static char[] encodeHex(byte[] data) {
+        return encodeHex(data, true);
+    }
+ 
+    /**
+     * 将字节数组转换为十六进制字符数组
+     *
+     * @param data        byte[]
+     * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
+     * @return 十六进制char[]
+     */
+    public static char[] encodeHex(byte[] data, boolean toLowerCase) {
+        return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+    }
+ 
+    /**
+     * 将字节数组转换为十六进制字符数组
+     *
+     * @param data     byte[]
+     * @param toDigits 用于控制输出的char[]
+     * @return 十六进制char[]
+     */
+    protected static char[] encodeHex(byte[] data, char[] toDigits) {
+        int l = data.length;
+        char[] out = new char[l << 1];
+        // two characters form the hex value.
+        for (int i = 0, j = 0; i < l; i++) {
+            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
+            out[j++] = toDigits[0x0F & data[i]];
+        }
+        return out;
+    }
+ 
+    /**
+     * 将字节数组转换为十六进制字符串
+     *
+     * @param data byte[]
+     * @return 十六进制String
+     */
+    public static String encodeHexString(byte[] data) {
+        return encodeHexString(data, true);
+    }
+ 
+    /**
+     * 将字节数组转换为十六进制字符串
+     *
+     * @param data        byte[]
+     * @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
+     * @return 十六进制String
+     */
+    public static String encodeHexString(byte[] data, boolean toLowerCase) {
+        return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+    }
+ 
+    /**
+     * 将字节数组转换为十六进制字符串
+     *
+     * @param data     byte[]
+     * @param toDigits 用于控制输出的char[]
+     * @return 十六进制String
+     */
+    protected static String encodeHexString(byte[] data, char[] toDigits) {
+        return new String(encodeHex(data, toDigits));
+    }
+ 
+    /**
+     * 将十六进制字符数组转换为字节数组
+     *
+     * @param data 十六进制char[]
+     * @return byte[]
+     * @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
+     */
+    public static byte[] decodeHex(char[] data) {
+        int len = data.length;
+ 
+        if ((len & 0x01) != 0) {
+            throw new RuntimeException("Odd number of characters.");
+        }
+ 
+        byte[] out = new byte[len >> 1];
+ 
+        // two characters form the hex value.
+        for (int i = 0, j = 0; j < len; i++) {
+            int f = toDigit(data[j], j) << 4;
+            j++;
+            f = f | toDigit(data[j], j);
+            j++;
+            out[i] = (byte) (f & 0xFF);
+        }
+ 
+        return out;
+    }
+ 
+    /**
+     * 将十六进制字符转换成一个整数
+     *
+     * @param ch    十六进制char
+     * @param index 十六进制字符在字符数组中的位置
+     * @return 一个整数
+     * @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
+     */
+    protected static int toDigit(char ch, int index) {
+        int digit = Character.digit(ch, 16);
+        if (digit == -1) {
+            throw new RuntimeException("Illegal hexadecimal character " + ch
+                    + " at index " + index);
+        }
+        return digit;
+    }
+ 
+    /**
+     * 数字字符串转ASCII码字符串
+     * 
+     * @param String
+     *            字符串
+     * @return ASCII字符串
+     */
+    public static String StringToAsciiString(String content) {
+        String result = "";
+        int max = content.length();
+        for (int i = 0; i < max; i++) {
+            char c = content.charAt(i);
+            String b = Integer.toHexString(c);
+            result = result + b;
+        }
+        return result;
+    }
+    
+    /**
+     * 十六进制转字符串
+     * 
+     * @param hexString
+     *            十六进制字符串
+     * @param encodeType
+     *            编码类型4:Unicode,2:普通编码
+     * @return 字符串
+     */
+    public static String hexStringToString(String hexString, int encodeType) {
+        String result = "";
+        int max = hexString.length() / encodeType;
+        for (int i = 0; i < max; i++) {
+            char c = (char) hexStringToAlgorism(hexString
+                    .substring(i * encodeType, (i + 1) * encodeType));
+            result += c;
+        }
+        return result;
+    }
+    
+    /**
+     * 十六进制字符串装十进制
+     * 
+     * @param hex
+     *            十六进制字符串
+     * @return 十进制数值
+     */
+    public static int hexStringToAlgorism(String hex) {
+        hex = hex.toUpperCase();
+        int max = hex.length();
+        int result = 0;
+        for (int i = max; i > 0; i--) {
+            char c = hex.charAt(i - 1);
+            int algorism = 0;
+            if (c >= '0' && c <= '9') {
+                algorism = c - '0';
+            } else {
+                algorism = c - 55;
+            }
+            result += Math.pow(16, max - i) * algorism;
+        }
+        return result;
+    }
+    
+    /**
+     * 十六转二进制
+     * 
+     * @param hex
+     *            十六进制字符串
+     * @return 二进制字符串
+     */
+    public static String hexStringToBinary(String hex) {
+        hex = hex.toUpperCase();
+        String result = "";
+        int max = hex.length();
+        for (int i = 0; i < max; i++) {
+            char c = hex.charAt(i);
+            switch (c) {
+            case '0':
+                result += "0000";
+                break;
+            case '1':
+                result += "0001";
+                break;
+            case '2':
+                result += "0010";
+                break;
+            case '3':
+                result += "0011";
+                break;
+            case '4':
+                result += "0100";
+                break;
+            case '5':
+                result += "0101";
+                break;
+            case '6':
+                result += "0110";
+                break;
+            case '7':
+                result += "0111";
+                break;
+            case '8':
+                result += "1000";
+                break;
+            case '9':
+                result += "1001";
+                break;
+            case 'A':
+                result += "1010";
+                break;
+            case 'B':
+                result += "1011";
+                break;
+            case 'C':
+                result += "1100";
+                break;
+            case 'D':
+                result += "1101";
+                break;
+            case 'E':
+                result += "1110";
+                break;
+            case 'F':
+                result += "1111";
+                break;
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * ASCII码字符串转数字字符串
+     * 
+     * @param String
+     *            ASCII字符串
+     * @return 字符串
+     */
+    public static String AsciiStringToString(String content) {
+        String result = "";
+        int length = content.length() / 2;
+        for (int i = 0; i < length; i++) {
+            String c = content.substring(i * 2, i * 2 + 2);
+            int a = hexStringToAlgorism(c);
+            char b = (char) a;
+            String d = String.valueOf(b);
+            result += d;
+        }
+        return result;
+    }
+    
+    /**
+     * 将十进制转换为指定长度的十六进制字符串
+     * 
+     * @param algorism
+     *            int 十进制数字
+     * @param maxLength
+     *            int 转换后的十六进制字符串长度
+     * @return String 转换后的十六进制字符串
+     */
+    public static String algorismToHexString(int algorism, int maxLength) {
+        String result = "";
+        result = Integer.toHexString(algorism);
+
+        if (result.length() % 2 == 1) {
+            result = "0" + result;
+        }
+        return patchHexString(result.toUpperCase(), maxLength);
+    }
+    
+    /**
+     * 字节数组转为普通字符串(ASCII对应的字符)
+     * 
+     * @param bytearray
+     *            byte[]
+     * @return String
+     */
+    public static String byteToString(byte[] bytearray) {
+        String result = "";
+        char temp;
+
+        int length = bytearray.length;
+        for (int i = 0; i < length; i++) {
+            temp = (char) bytearray[i];
+            result += temp;
+        }
+        return result;
+    }
+    
+    /**
+     * 二进制字符串转十进制
+     * 
+     * @param binary
+     *            二进制字符串
+     * @return 十进制数值
+     */
+    public static int binaryToAlgorism(String binary) {
+        int max = binary.length();
+        int result = 0;
+        for (int i = max; i > 0; i--) {
+            char c = binary.charAt(i - 1);
+            int algorism = c - '0';
+            result += Math.pow(2, max - i) * algorism;
+        }
+        return result;
+    }
+
+    /**
+     * 十进制转换为十六进制字符串
+     * 
+     * @param algorism
+     *            int 十进制的数字
+     * @return String 对应的十六进制字符串
+     */
+    public static String algorismToHEXString(int algorism) {
+        String result = "";
+        result = Integer.toHexString(algorism);
+
+        if (result.length() % 2 == 1) {
+            result = "0" + result;
+
+        }
+        result = result.toUpperCase();
+
+        return result;
+    }
+    
+    /**
+     * HEX字符串前补0,主要用于长度位数不足。
+     * 
+     * @param str
+     *            String 需要补充长度的十六进制字符串
+     * @param maxLength
+     *            int 补充后十六进制字符串的长度
+     * @return 补充结果
+     */
+    static public String patchHexString(String str, int maxLength) {
+        String temp = "";
+        for (int i = 0; i < maxLength - str.length(); i++) {
+            temp = "0" + temp;
+        }
+        str = (temp + str).substring(0, maxLength);
+        return str;
+    }
+    
+    /**
+     * 将一个字符串转换为int
+     * 
+     * @param s
+     *            String 要转换的字符串
+     * @param defaultInt
+     *            int 如果出现异常,默认返回的数字
+     * @param radix
+     *            int 要转换的字符串是什么进制的,如16 8 10.
+     * @return int 转换后的数字
+     */
+    public static int parseToInt(String s, int defaultInt, int radix) {
+        int i = 0;
+        try {
+            i = Integer.parseInt(s, radix);
+        } catch (NumberFormatException ex) {
+            i = defaultInt;
+        }
+        return i;
+    }
+    
+    /**
+     * 将一个十进制形式的数字字符串转换为int
+     * 
+     * @param s
+     *            String 要转换的字符串
+     * @param defaultInt
+     *            int 如果出现异常,默认返回的数字
+     * @return int 转换后的数字
+     */
+    public static int parseToInt(String s, int defaultInt) {
+        int i = 0;
+        try {
+            i = Integer.parseInt(s);
+        } catch (NumberFormatException ex) {
+            i = defaultInt;
+        }
+        return i;
+    }
+    
+    /**
+     * 十六进制串转化为byte数组
+     * 
+     * @return the array of byte
+     */
+    public static byte[] hexToByte(String hex)
+            throws IllegalArgumentException {
+        if (hex.length() % 2 != 0) {
+            throw new IllegalArgumentException();
+        }
+        char[] arr = hex.toCharArray();
+        byte[] b = new byte[hex.length() / 2];
+        for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
+            String swap = "" + arr[i++] + arr[i];
+            int byteint = Integer.parseInt(swap, 16) & 0xFF;
+            b[j] = new Integer(byteint).byteValue();
+        }
+        return b;
+    }
+    
+    /**
+     * 字节数组转换为十六进制字符串
+     * 
+     * @param b
+     *            byte[] 需要转换的字节数组
+     * @return String 十六进制字符串
+     */
+    public static String byteToHex(byte b[]) {
+        if (b == null) {
+            throw new IllegalArgumentException(
+                    "Argument b ( byte array ) is null! ");
+        }
+        String hs = "";
+        String stmp = "";
+        for (int n = 0; n < b.length; n++) {
+            stmp = Integer.toHexString(b[n] & 0xff);
+            if (stmp.length() == 1) {
+                hs = hs + "0" + stmp;
+            } else {
+                hs = hs + stmp;
+            }
+        }
+        return hs.toUpperCase();
+    }
+    
+    public static byte[] subByte(byte[] input, int startIndex, int length) {
+		byte[] bt = new byte[length];
+		for (int i = 0; i < length; i++) {
+			bt[i] = input[i + startIndex];
+		}
+		return bt;
+    }
+}

TEMPAT SAMPAH
java源码+jar包/libs/bcprov-jdk14-143.jar


TEMPAT SAMPAH
java源码+jar包/libs/sun.misc.BASE64Decoder.jar


+ 3 - 0
java源码+jar包/说明.txt

@@ -0,0 +1,3 @@
+调用SM2Utils文件中的SM2_TEST()函数即可验证SM2加解密;
+调用SM4Utils文件中的SM4_ECB_TEST()函数即可验证SM4 ECB模式的加解密;
+本代码在安卓上验证过,能够正常使用;