基于JCA安全体系的封装

所有涵盖的安全算法均在JCA体系结构下,所有算法均由JEC提供,目的是提供方便快捷的使用方式。

目前主要功能包括:

  • 摘要算法
  • RSA密钥
  • 签名算法
  • RSA算法
  • AES算法

1 背景

项目依赖除了JDK1.8自带的JCE外,还依赖了bouncycastle提供的JCE。

本项目需要在JDK1.8_8u161及之后的版本使用,否则需要自行解除限制。

在JDK1.8_8u161之前的版本,由于出口政策限制,AES密钥只能到128位,使用密钥大于128位将出现报错信息,请参考Oracle官方说明:
https://www.oracle.com/java/technologies/javase-jce-all-downloads.html

2 依赖

已发布到Maven中央仓库,坐标地址:

<dependency>
    <groupId>io.feistel</groupId>
    <artifactId>security-common</artifactId>
    <version>1.0.1</version>
</dependency>

引入后可以在IDEA下载源码,源码包括了详细的注释。

源码地址:https://github.com/dirty-damn/security-common

3 使用实例

在test目录下覆盖了所有算法及密钥的测试例子,并且已经测试通过,这里仅做常用演示。

3.1 摘要算法

String digest1 = Digest.use(DigestEnum.SHA256).digest("123");

使用use()指定摘要算法进行计算,结果以Hex十六进行结果输出。方法是线程安全的。
DigestEnum包含了包括openssl 1.1.1m能提供的所有摘要算法,除了mdc2,openssl命令工具如下:

Message Digest commands (see the `dgst' command for more details)
blake2b512        blake2s256        gost              md4
md5               --mdc2            rmd160            sha1
sha224            sha256            sha3-224          sha3-256
sha3-384          sha3-512          sha384            sha512
sha512-224        sha512-256        shake128          shake256
sm3

DigestEnum支持如下:

BLAKE2B512("BLAKE2B-512"),
BLAKE2S512("BLAKE2S-256"),
GOST("GOST3411"),
MD4("MD4"),
MD5("MD5"),
RMD128("RIPEMD128"),
RMD160("RIPEMD160"),
RMD256("RIPEMD256"),
// SHA1
SHA1("SHA-1"),
// SHA2,SHA-224、SHA-256、SHA-384,和SHA-512并称为SHA2
SHA224("SHA-224"),
SHA256("SHA-256"),
SHA384("SHA-384"),
SHA512("SHA-512"),
// SHA3,SHA3-224、SHA3-256、SHA3-384,和SHA3-512并称为SHA3
SHA3_224("SHA3-224"),
SHA3_256("SHA3-256"),
SHA3_384("SHA3-384"),
SHA3_512("SHA3-512"),
// SHA512
SHA512_256("SHA-512/256"),
SHA512_224("SHA-512/224"),
// SHAKE
SHAKE128("SHAKE128-256"),
SHAKE256("SHAKE256-512"),
// 国密hash
SM3("SM3"),

3.2 RSA密钥

长度包括1024和2048。

包含如下功能:

  1. 生成RSA密钥对
  2. 字节数组转为公钥/私钥
  3. 公钥/私钥的PKCS1和PKCS8互转.
  4. 读取PEM格式的公钥/私钥
  5. 公钥/私钥生成PKCS1和PKCS8的PEM格式字符串
  6. 证书提取PKCS8的公钥

以下举例:

生成RSA密钥对

RSAKeyPair rsaKeyPair = RSAKeyPair.generator(RSAKeyEnum.KEY_1024);

获取PKCS8格式的PEM

String pkcs8 = rsaKeyPair.getRsaPvtKey().getPemPKCS8();

读取PKCS1格式公钥,并转为PKCS8的字节数组

String pemPKCS1Pub = "-----BEGIN RSA PUBLIC KEY-----\r\n" +
                "MIGJAoGBAId7rfXopAhYF6EeUkGIUP426+inmWFYLS7lsvgQezmC0CduaQcy4QrR\r\n" +
                "TGi6m/hB0uY6/g0nv2qpq2SQLSpro8EKtG98kxroTsgIeEfEfPpr1cR1FUq4wmbF\r\n" +
                "H2XliwXEXwgtPLp39MMTHQbYVPs36wqIQkxukSBdqt7AHOkw2VdTAgMBAAE=\r\n" +
                "-----END RSA PUBLIC KEY-----" +
                "\r\n";
RSAPubRSAKey rsaPubKey1 = RSAPubRSAKey.instanceFromPem(pemPKCS1Pub);
byte[] bytesPKCS8 = rsaPubKey1.getBytesPKCS8();

3.3 签名算法

签名算法使用到RSA密钥,私钥签名,公钥验签。

RSAPvtRSAKey rsaPvtKey = RSAPvtRSAKey.instanceFromPem(pemPKCS8);
String sign = Sign.sign(SignatureEnum.SHA1WithRSA, "123", rsaPvtKey.getPrivateKey());

RSAPubRSAKey rsaPubKey = RSAPubRSAKey.instanceFromPem(pemPKCS8Pub);
boolean verify = Sign.verify(SignatureEnum.SHA1WithRSA, "123", sign, rsaPubKey.getPublicKey());

Assert.assertTrue(verify);

可支持的签名算法在SignatureEnum枚举类型中,如下:

// SHA1
SHA1WithRSA("SHA1WithRSA"),
// SHA2
SHA224WITHRSA("SHA224WITHRSA"),
SHA256WITHRSA("SHA256WITHRSA"),
SHA384WITHRSA("SHA384WITHRSA"),
SHA512WITHRSA("SHA512WITHRSA"),
// SHA3
SHA3_224WITHRSA("SHA3-224WITHRSA"),
SHA3_384WITHRSA("SHA3-384WITHRSA"),
SHA3_256WITHRSA("SHA3-256WITHRSA"),
SHA3_512WITHRSA("SHA3-512WITHRSA"),
// MD5
MD5WITHRSA("MD5WITHRSA"),
// MD5 SHA1
MD5ANDSHA1WITHRSA("MD5ANDSHA1WITHRSA"),
// RMD
RMD128WITHRSA("RMD128WITHRSA"),
RMD160WITHRSA("RMD160WITHRSA"),
RMD256WITHRSA("RMD256WITHRSA"),

3.4 算法

加密过程共由这些内容组成,密码算法、密钥、密钥填充、加密模式、明文填充、VI初始偏移量和编解码器。

不同算法或不同模式所需要的内容不同,这里不对密码算法理论作过多介绍,在具体算法章节作说明。

3.4.1 AES

AES密钥长度包括128、192以及256位。AESKeyEnum如下:

KEY_128(128, 16),
KEY_192(192, 24),
KEY_256(256, 32),

在JDK1.8_8u161之前的版本,由于出口政策限制,AES密钥只能到128位,使用密钥大于128位将出现报错信息,解除限制参考:
https://www.oracle.com/java/technologies/javase-jce-all-downloads.html

加密模式枚举EncryptModeEnum如下:

// ECB-电码本模式 CBC-密文分组链接方式 CFB-密文反馈模式 OFB-输出反馈模式
ECB("ECB"),
CBC("CBC"),
CFB("CFB"),
OFB("OFB"),

除ECB模式外,其他模式都需要IV初始限量,IV是一个16字节长度的偏移量,可自定或生成。

填充模式枚举PaddingModeEnum如下:

NoPadding("NoPadding"),
PKCS5("PKCS5Padding"),
ISO10126("ISO10126Padding "),

使用说明

默认为256/ECB/PKCS5算法,使用Base64编解码

AESCipher aesCipher = AESCipher.init();
String encrypt = aesCipher.encrypt("123", aesCipher.getKey("123".getBytes()));
String decrypt = aesCipher.decrypt(encrypt, aesCipher.getKey("123".getBytes()));
Assert.assertEquals(decrypt, "123");

指定算法参数,指定Hex十六进制编解码器

AESParam aesParam = new AESParam(AESKeyEnum.KEY_128, EncryptModeEnum.ECB, PaddingModeEnum.PKCS5, "1234567890123456");
AESCipher aesCipher1 = AESCipher.init(aesParam);
String encrypt1 = aesCipher1.encrypt("123", aesCipher1.getKey("123".getBytes()), AbstractCipher.encPostHexHandler);
String decrypt1 = aesCipher1.decrypt(encrypt1, aesCipher1.getKey("123".getBytes()), AbstractCipher.decPreHexHandler);
Assert.assertEquals(decrypt1, "123");
3.4.2 RSA

与AES不同,RSA算法只有ECB模式,JEC没有提供RSA的其他加密模式。
填充模式枚举RSAPaddingModeEnum如下:

NoPadding("NoPadding"),
PKCS1("PKCS1Padding"),
OAEP("OAEPPadding"),

OAEP是PKCS1的v2版,可以看作是升级版本。

RSACipher rsaCipher = RSACipher.init();
String encrypt = rsaCipher.encrypt("123", rsaPubKey.getPublicKey());
String decrypt = rsaCipher.decrypt(encrypt, rsaPvtKey.getPrivateKey());
Assert.assertEquals(decrypt, "123");

RSACipher rsaCipher1 = RSACipher.init(RSAPaddingModeEnum.OAEP);
// 指定编解码器
String encrypt1 = rsaCipher1.encrypt("123", rsaPubKey.getPublicKey(), AbstractCipher.encPostHexHandler);
String decrypt1 = rsaCipher1.decrypt(encrypt1, rsaPvtKey.getPrivateKey(), AbstractCipher.decPreHexHandler);
Assert.assertEquals(decrypt1, "123");

目前项目仅涵盖非常非常基础的功能,如果你想贡献代码,非常期待你的加入,贡献开源力量,共勉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了实现MD5算法,需要使用Java Cryptography Architecture/Java Cryptography Extension (JCA/JCE)提供的相关类和方法。以下是一个实现MD5算法的Java代码示例: ```java import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class MD5Example { public static void main(String[] args) { String input = "hello world"; try { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] messageDigest = md.digest(input.getBytes()); StringBuilder sb = new StringBuilder(); for (byte b : messageDigest) { sb.append(String.format("%02x", b & 0xff)); } System.out.println("MD5 hash of \"" + input + "\" is: " + sb.toString()); } catch (NoSuchAlgorithmException e) { System.out.println("Error while hashing with MD5: " + e.getMessage()); } } } ``` 在上述示例中,我们使用了Java的MessageDigest类和“MD5”算法来计算输入字符串“hello world”的MD5哈希值。运行程序后,控制台输出如下: ``` MD5 hash of "hello world" is: 5eb63bbbe01eeed093cb22bb8f5acdc3 ``` 可以看到,计算得到的MD5哈希值为“5eb63bbbe01eeed093cb22bb8f5acdc3”。 分析实验结果,我们可以发现以下几点: 1. 实现MD5算法的过程中,主要使用了Java Cryptography Architecture/Java Cryptography Extension (JCA/JCE)提供的相关类和方法。 2. 实现MD5算法的Java代码示例可以计算任意输入字符串的MD5哈希值,并且计算结果与其他MD5实现的结果一致。 3. MD5算法是一种单向散列函数,可以将任意长度的输入数据映射为固定长度的输出数据(通常为128位),并且不可逆。因此,MD5算法常用于数据完整性校验、密码存储等场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值