UopenCryptionKit4Java:一个好用的轻量开源加解密器工具包

简介

UopenCryptionKit4Java开源库支持AES/DES/3DES/RSA/SM2/SM4/MD5/HmacSHA1/HmacSHA256/SM3等常见的加解密以及签名算法工具,将常见的加密器,加签器统一封装提供操作,并将密码设置和操作过程分离,欢迎大家fork,如果有更好的主意欢迎完善它。

项目地址

https://github.com/fpleihub/UopenCryptionKit4Java.git

目前Kit中支持的加解密器

1.AES 
2.DES 
3.3DES 
4.国密Sm2  
5.国密Sm4  
6.RSA 

目前Kit中支持的签名器

1.DSA 
2.HmacSHA1 
3.HmacSHA256 
4.Md5  
5.SM3 

快速开始

Maven引用

<dependency>
  <groupId>io.github.fpleihub</groupId>
  <artifactId>UopenCryptionKit4Java</artifactId>
  <version>1.0</version>
</dependency>

Gradle引用

implementation 'io.github.fpleihub:UopenCryptionKit4Java:1.0'

DEMO. AES加解密使用

String value = UEncryptionManager.getInstance().withAes("10---323_哈哈四大时刻18211!@", Op.Encryption, ReturnType.TYPE_HEX);
System.out.println("AES加密后值:" + value);

String value1 = UEncryptionManager.getInstance().withAes(value, Op.Decrypt, ReturnType.TYPE_HEX);
System.out.println("AES解密后值:" + value1);

更详细的使用说明

1). 初始化秘钥管理器

工具为了将加密编码过程秘钥和操作分离,单独管理秘钥,避免每次输入或引用,同时统一管理,因此项目使用到了哪些加密器,即继承KeyCreator实现相关的密码源即可,工具内置了一套默认秘钥,如果没有给到工具你的秘钥,那么这可能导致解密失败等情况,(如果想快速体验,可跳过该步骤)

public class MyEncryptKeySource extends KeyCreator {
    @Override
    public String getAesPass() {
        return "my2020aes!@#_121872";
    }

    @Override
    public String getTriplePass() {
        return "my2020des$#_!1234567890";
    }

    @Override
    public String getRsaPrivatePass() {
        return "xxx";
    }

    @Override
    public String getRsaPublicPass() {
        return "xxx";
    }

    @Override
    public String getHmacShaPass() {
        return "bilibili1219832020";
    }

    @Override
    public String getSm2PublicPass() {
        return "0475658556b7ebff57a95b4da1cfefdb131f22909e2cd3265ace57d67a8033d522d40173db64a78a21d68035148694e01ffd973fb1c1af471c016e59c60c01fc0c";
    }

    @Override
    public String getSm2PrivatePass() {
        return "1eadfb948c582c03819d130837de5a6dcb9d8f6101ea1cf05982c27fb75027a5";
    }

    @Override
    public String getSm4Pass() {
        return "JeF8U9wHFOMfs2Y8";
    }

    @Override
    public String getDasPrivateKey() {
        return "MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUBiCZo7Aw+lPTaXf8an2bdqMVCMo=";
    }

    @Override
    public String getDasPublicKey() {
        return "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGASIyEgiooFat7lb8fIuTir5JyvxDHBZIbwcvFewZ2eb8Fv7VW+z84CsjNswNOu1f81palcFA8vDyp2bv2tP+3OAAEnWbjYJQDNTc29ZZk3r0SwnPlmlFqLXUmBF8ROce991WEI0khGLwTNlNSMynhLljFZnW1fGplKzWMFetL7DQ=";
    }
}

密码管理器有几个地方需要注意
1)3DES秘钥,长度最好固定24个字符,否则不足将会自动追加补0,或超出会自动截断到24个字符
2)RSA秘钥对可通过/utils/RsaKeyHelper.java生成,内置默认使用Base64字符串作为秘钥串,如果需要更换层数据类型(ReturnType中类型列表),并且调整{RsaPrivateCipher.java/RsaPublicCipher.java}加密器的秘钥编码方式 
3)国秘SM2秘钥对可通过/utils/SM2KeyHelper.java}生成,内置默认使用十六进制字符串作为铭文秘钥,如果需要更换成其他的数据类型(ReturnType中类型列表),并且调整{Sm2Cipher.java}加密器的秘钥编码方式。
4)国秘SM4秘钥长度为16个字符.

2).将密码管理器初始化到UopenCryptionKit4

可以使用时初始化,也可以项目启动是初始化,业务使用一定要制定自己的秘钥,切记不要使用工具内置秘钥,工具内置秘钥只是为了大家快速体验

UEncryptionManager.initKey(new MyEncryptKeySource());

3).关于Op操作符的说明

所有的操作入口都在UEncryptionManager中,对于加密还是解密这里只按传的操作符来确定,方法不变

//加密操作符
Encryption
//解密操作符
Decrypt

4).关于方法中的ReturnType数据类型

考虑到不同的业务场景可能会需要不同的数据类型,如A加密场景需要使用Hex数据类型操作,B场景加密数据结果需要Base64类型操作,这里也约定了常见的数据类型HEX,BASE64,STRING,如果您认为都不符合,那么可以直接使用最原始返回Byte自定义数据类型

/**
* 返回或解密传入数据普通字符串类型
*/
TYPE_STRING,
/**
* 返回或解密传入数据普通字Base64类型
*/
TYPE_BASE64,
/**
* 返回或解密传入数据普通字16进制类型
*/
TYPE_HEX

DEMO.1 AES加解密操作

/**
* Aes加解密
* @param content        内容
* @param type           操作类型
* @param returnDataType 返回数据类型(加解密需要统一,内部会对数据做编码)
*/
String value = UEncryptionManager.getInstance().withAes("10---323_哈哈四大时刻18211!@", Op.Encryption, ReturnType.TYPE_HEX);
System.out.println("AES加密后值:" + value);

String value1 = UEncryptionManager.getInstance().withAes(value, Op.Decrypt, ReturnType.TYPE_HEX);
System.out.println("AES解密后值:" + value1);

DEMO.2 3DES加解密操作

String triple1 = UEncryptionManager.getInstance().withTripleDes("测试3des加解密字符串@(*!*@&!__", Op.Encryption, ReturnType.TYPE_BASE64);
System.out.println("3DES加密:" + triple1);

String triple2 = UEncryptionManager.getInstance().withTripleDes(triple1, Op.Decrypt, ReturnType.TYPE_BASE64);
System.out.println("3DES解密:" + triple2);

DEMO.3 RSA加解密操作

//公钥加密--》私钥解密
String rsaPublic = UEncryptionManager.getInstance().withRsaPublic("测试RSA公钥加解密!@823144aas_*!.>", Op.Encryption, ReturnType.TYPE_BASE64);
System.out.println("RSA公钥加密:" + rsaPublic);

String rsaPublic1 = UEncryptionManager.getInstance().withRsaPrivate(rsaPublic, Op.Decrypt, ReturnType.TYPE_BASE64);
System.out.println("RSA私钥解密:" + rsaPublic1);

//私钥加密---》公钥解密
String rsaPrivate = UEncryptionManager.getInstance().withRsaPrivate("测试RSA私钥主导加解密@!@!@!&@*!.>", Op.Encryption, ReturnType.TYPE_HEX);
System.out.println("RSA私钥加密:" + rsaPrivate);

String rsaPrivate1 = UEncryptionManager.getInstance().withRsaPublic(rsaPrivate, Op.Decrypt, ReturnType.TYPE_HEX);
System.out.println("RSA公钥解密:" + rsaPrivate1);

如果你没有秘钥,可以先通过工具{utils/RsaKeyHelper.java}内部提供的秘钥生成器生成秘钥对,然后将生成好的秘钥对在放入秘钥管理器中即可,模式秘钥数据类型为Base64

RsaKeyHelper.KeyPass keyPass= RsaKeyHelper.generateKeyPair();
System.out.println("公钥:"+keyPass.getPublicKey());
System.out.println("私钥:"+keyPass.getPrivateKey());

目前如果需要调整秘钥生成的数据类型,那你可能需要将项目clone到本地进行修改重新打包
修改一,将生成秘钥地方编码方式进行调整

public static synchronized void generateKeyPair() {
            try {
                //KEY_SIZE=2048
                keyPairGenerator.initialize(KEY_SIZE, new SecureRandom(UUID.randomUUID().toString().getBytes()));
                keyPair = keyPairGenerator.generateKeyPair();
            } catch (Exception e) {
                e.printStackTrace();
            }
            RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
            //需要修改秘钥数据类型,调整此处即可
            String publicKeyString = new String(Base64.encode(rsaPublicKey.getEncoded()), Charset.forName("UTF-8"));
            String privateKeyString = new String(Base64.encode(rsaPrivateKey.getEncoded()), Charset.forName("UTF-8"));
            storeKey(publicKeyString, PUBLIC_KEY_NAME, PUBLIC_FILENAME);
            storeKey(privateKeyString, PRIVATE_KEY_NAME, PRIVATE_FILENAME);
        }

修改二,将秘钥解密初地方进行调整
修改RsaPrivateCipher 中静态类 KeyPairHelper 中方法”getPublicKey”与”getPrivateKey”中秘钥编码类型

//私钥 
public static RSAPrivateKey getPrivateKey(String base64KeyPass) throws Exception {
            RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) certMap.get("PrivateKey" + base64KeyPass.hashCode());
            if (rsaPrivateKey != null) {
                return rsaPrivateKey;
            }
            //调整这里
            byte[] keyBytes = Base64.decode(base64KeyPass);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            rsaPrivateKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            certMap.put("PrivateKey" + base64KeyPass.hashCode(), rsaPrivateKey);
            return rsaPrivateKey;
}
//公钥
public static RSAPublicKey getPublicKey(String base64KeyPass) throws Exception {
            RSAPublicKey rsaPublicKey = (RSAPublicKey) certMap.get("PublicKey" + base64KeyPass.hashCode());
            if (rsaPublicKey != null) {
                return rsaPublicKey;
            }
            //调整这里
            byte[] keyBytes = Base64.decode(base64KeyPass);
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            rsaPublicKey = (RSAPublicKey) keyFactory.generatePublic(x509EncodedKeySpec);
            certMap.put("PublicKey" + base64KeyPass.hashCode(), rsaPublicKey);
            return rsaPublicKey;

}

DEMO4. 国秘SM4加解密操作

//SM4加解密-秘钥为16字符长度
String sm4Encry= UEncryptionManager.getInstance().withSm4("测试Sm4对称加密算法——_90a8^$",Op.Encryption,ReturnType.TYPE_BASE64);
System.out.println("国秘SM4加密:" + sm4Encry);

String sm4Decry= UEncryptionManager.getInstance().withSm4(sm4Encry,Op.Decrypt,ReturnType.TYPE_BASE64);
System.out.println("国秘SM4解密:" + sm4Decry);

DEMO5. 国密SM2加解密操作

//客户端公钥加密--》服务端私钥解密
String sm2PublicKeyEncry= UEncryptionManager.getInstance().withSm2PublicKey("这是测试Sm2公钥加密私钥解密的内容)*(*&*&",Op.Encryption,ReturnType.TYPE_HEX);
System.out.println("SM2公钥加密:" + sm2PublicKeyEncry);

String sm2PrivateKeyDecry= UEncryptionManager.getInstance().withSm2PrivateKey(sm2PublicKeyEncry,Op.Decrypt,ReturnType.TYPE_HEX);
System.out.println("SM2私钥解密:" + sm2PrivateKeyDecry);

DEMO6.DSA加签与验证

用于数据签名和验证,校验数据是否完整,或者被篡改,使用说明:
1 生成加签和验证的公私钥 (详细见:DSAKeyHelper.genKeyPair()函数)
2 客户端通过公钥进行加签
3 服务端通过私钥进行签名验证

String dasResult= UEncryptionManager.getInstance().withDasSign("等待Das加签的数据",ReturnType.TYPE_BASE64);
System.out.println("DSA加签:" + dasResult);

Boolean dasFlag= UEncryptionManager.getInstance().withDasVerify("等待Das加签的数据",dasResult,ReturnType.TYPE_BASE64);
System.out.println("DSA公钥签名验证:" + dasFlag);

DEMO7.国密SM3杂凑签名

//SM3签名
String sm3Sign= UEncryptionManager.getInstance().withSm3("测试Sm3签名算法",ReturnType.TYPE_HEX);
System.out.println("国秘SM3签名:" + sm3Sign);

DEMO8.HMacSHA1/HMacSHA256 签名

String sign256Base64 = UEncryptionManager.getInstance().withHmacSh256("测试字符串asa@!_a", ReturnType.TYPE_HEX);
System.out.println("HmacSh256 指纹:" + sign256Base64);

String sign1Base64 = UEncryptionManager.getInstance().withHmacSha1("测试字符串asa@!_a", ReturnType.TYPE_HEX);
System.out.println("HmacSha1 指纹:" + sign1Base64);

DEMO9.MD5 指纹

String md5 = UEncryptionManager.getInstance().withMd5("哈哈杀a123456", ReturnType.TYPE_BASE64);
System.out.println("md5 指纹:" + md5);

依赖的第三方包

项目依赖了 bcprov-jdk16-1.46 包,主要是未了统一使用的编码工具,避免不同环境使用导致编码数据异常,也使用了内部的底层加密算法。

下一个版本规划

1. 优化密码管理器,使密码管理私有化更灵活。

2.制定Android版本Kit。

3.实现内部注解自动对数据进行加解密操作。

最后

欢迎大家使用,改进建议可以再公众号留言或者GitHub题issue都可,如果可以的话希望一起完善这个库!