加密算法小总结

加密算法小总结

参考网址:

https://mp.weixin.qq.com/s?__biz=MzU4ODI1MjA3NQ==&mid=2247495633&idx=2&sn=6277d145ccc3d8df7760eda05f300579&chksm=fddd3915caaab0035bdbd9a44a6f3c21ad2e3309015d8aa7333ba7f25e452b2690fb89a96f9d&mpshare=1&scene=23&srcid=0103JZkF1agE1ncobPsE465W&sharer_sharetime=1609686793091&sharer_shareid=9d1e76e919cc0b2f3ca23ed1f5ef67a8#rd

hutool工具类使用手册

https://www.hutool.cn/docs/#/crypto/%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86-SymmetricCrypto

前言

之前接触过一点加密相关的功能,但是没有总结,知识大概知道有加密算法这个概念,参照一个帖子,总结一下

下面的测试我们借助hutool这个工具库,这个封装了加密算法的操作

加密算法的分类

  • 可逆算法
    • 对称加密
    • 非对称加密
  • 不可逆算法

举例说明:

1.不可逆算法

MD5 , SHA256SHA384SHA512以及HMAC-SHA256HMAC-SHA384HMAC-SHA512等

2.对称加密算法

AES , DES

3.非对称加密算法

RSA

举例说明

一下举例说明基本都用了很火的工具库hutool

maven工程引入hutool

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.5.6</version>
</dependency>

1.MD5

简介

MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。

特点

1、压缩性:无论数据长度是多少,计算出来的MD5值长度相同

2、容易计算性:由原数据容易计算出MD5

3、抗修改性:即便修改一个字节,计算出来的MD5值也会巨大差异

4、抗碰撞性:知道数据和MD5值,很小概率找到相同MD5值相同的原数据。

示例

 @Test
    public void testShiroMd5(){
        //使用md5
        System.out.println("使用md5处理");
        Md5Hash md5Hash = new Md5Hash("123");
        System.out.println(md5Hash.toHex());
        //202cb962ac59075b964b07152d234b70
        //使用md5+salt处理
        System.out.println("使用加盐处理");
        Md5Hash md5Hash1 = new Md5Hash("123", "123!@#");
        System.out.println(md5Hash1.toHex());
        //使用md5+salt+hash散列
        System.out.println("使用md5+salt+hash散列处理");
        Md5Hash md5Hash2 = new Md5Hash("123", "123!@#", 1024);
        System.out.println(md5Hash2.toHex());

    }

2.AES

简介加说明

AES 高级数据加密标准,能够有效抵御已知的针对DES算法的所有攻击,默认密钥长度为128位,还可以供选择192位,256位。这里顺便提一句这个位指的是bit。

示例1

hutool参照文档示例

通用方式


@Test
public void test12(){
    String content = "test中文";

// 随机生成密钥
    byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();

// 构建
    AES aes = SecureUtil.aes(key);
//加密
    byte[] encrypt = aes.encrypt(content);
    System.out.println(encrypt);
//解密
    byte[] decrypt = aes.decrypt(encrypt);
    System.out.println(decrypt);
//加密为16进制表示
    String encryptHex = aes.encryptHex(content);
    System.out.println(encryptHex);
//解密为字符串
    String decryptStr = aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
    System.out.println(decryptStr);
}

示例2

AES封装

@Test
public void test12(){
   String content = "test中文";

// 随机生成密钥
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();

// 构建
AES aes = SecureUtil.aes(key);

// 加密
byte[] encrypt = aes.encrypt(content);
// 解密
byte[] decrypt = aes.decrypt(encrypt);

// 加密为16进制表示
String encryptHex = aes.encryptHex(content);
// 解密为字符串
String decryptStr = aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
}

示例3

自定义模式和偏移

 @Test
    public void encryptTest() {
        // 构建
        AES aes = new AES(Mode.CBC, Padding.PKCS5Padding,
                "1234567890123451".getBytes(), "1234567890123456".getBytes());
        String encryptHex = aes.encryptHex("123456");
        System.out.println(aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8));

    }

3.DES

简介+说明

DES是对称加密算法领域中的典型算法,其密钥默认长度为56位。

示例

参考hutool说明文档的示例

/**
 * DES加密解密单元测试
 */
public class DesTest {

	@Test
	public void encryptDecryptTest(){
		String content = "我是一个测试的test字符串123";
		final DES des = SecureUtil.des();

		final String encryptHex = des.encryptHex(content);
		final String result = des.decryptStr(encryptHex);

		Assert.assertEquals(content, result);
	}

	@Test
	public void encryptDecryptWithCustomTest(){
		String content = "我是一个测试的test字符串123";
		final DES des = new DES(
				Mode.CTS,
				Padding.PKCS5Padding,
				StrUtil.bytes("12345678"),
				StrUtil.bytes("11223344")
		);

		final String encryptHex = des.encryptHex(content);
		final String result = des.decryptStr(encryptHex);

		Assert.assertEquals(content, result);
	}
}

4.RSA

简介+说明

非对称加密算法有两个密钥,这两个密钥完全不同但又完全匹配。只有使用匹配的一对公钥和私钥,才能完成对明文的加密和解密过程。常见的非对称加密有RSASM2等。

/**
 * RSA算法单元测试
 *
 * @author Looly
 */
public class RSATest {

    @Test
    public void generateKeyPairTest() {
        KeyPair pair = KeyUtil.generateKeyPair("RSA");
        Assert.assertNotNull(pair.getPrivate());
        Assert.assertNotNull(pair.getPublic());
    }

    @Test
    public void rsaCustomKeyTest() {
        KeyPair pair = KeyUtil.generateKeyPair("RSA");
        byte[] privateKey = pair.getPrivate().getEncoded();
        byte[] publicKey = pair.getPublic().getEncoded();
//        byte[] privateKey = "1234567890qwerty".getBytes();
//        byte[] publicKey = "1234567890asdfgh".getBytes();

        RSA rsa = SecureUtil.rsa(privateKey, publicKey);

        // 公钥加密,私钥解密
        byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
        byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));

        // 私钥加密,公钥解密
        byte[] encrypt2 = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);
        byte[] decrypt2 = rsa.decrypt(encrypt2, KeyType.PublicKey);
        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt2, CharsetUtil.CHARSET_UTF_8));
    }

    @Test
    public void rsaTest() {
        final RSA rsa = new RSA();

        // 获取私钥和公钥
        Assert.assertNotNull(rsa.getPrivateKey());
        Assert.assertNotNull(rsa.getPrivateKeyBase64());
        Assert.assertNotNull(rsa.getPublicKey());
        Assert.assertNotNull(rsa.getPrivateKeyBase64());

        // 公钥加密,私钥解密
        byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);

        byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));

        // 私钥加密,公钥解密
        byte[] encrypt2 = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);
        byte[] decrypt2 = rsa.decrypt(encrypt2, KeyType.PublicKey);
        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt2, CharsetUtil.CHARSET_UTF_8));
    }

    @Test
    public void rsaWithBlockTest2() {
        final RSA rsa = new RSA();
        rsa.setEncryptBlockSize(3);

        // 获取私钥和公钥
        Assert.assertNotNull(rsa.getPrivateKey());
        Assert.assertNotNull(rsa.getPrivateKeyBase64());
        Assert.assertNotNull(rsa.getPublicKey());
        Assert.assertNotNull(rsa.getPrivateKeyBase64());

        // 公钥加密,私钥解密
        byte[] encrypt = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PublicKey);
        byte[] decrypt = rsa.decrypt(encrypt, KeyType.PrivateKey);
        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));

        // 私钥加密,公钥解密
        byte[] encrypt2 = rsa.encrypt(StrUtil.bytes("我是一段测试aaaa", CharsetUtil.CHARSET_UTF_8), KeyType.PrivateKey);
        byte[] decrypt2 = rsa.decrypt(encrypt2, KeyType.PublicKey);
        Assert.assertEquals("我是一段测试aaaa", StrUtil.str(decrypt2, CharsetUtil.CHARSET_UTF_8));
    }

    @Test
    public void rsaBcdTest() {
        String text = "我是一段测试aaaa";

        final RSA rsa = new RSA();

        // 公钥加密,私钥解密
        String encryptStr = rsa.encryptBcd(text, KeyType.PublicKey);
        String decryptStr = StrUtil.utf8Str(rsa.decryptFromBcd(encryptStr, KeyType.PrivateKey));
        Assert.assertEquals(text, decryptStr);
        System.out.println(encryptStr);
        System.out.println(decryptStr);


        // 私钥加密,公钥解密
        String encrypt2 = rsa.encryptBcd(text, KeyType.PrivateKey);
        String decrypt2 = StrUtil.utf8Str(rsa.decryptFromBcd(encrypt2, KeyType.PublicKey));
        Assert.assertEquals(text, decrypt2);
    }

    @Test
    public void rsaBase64Test() {
        String textBase = "我是一段特别长的测试";
        StringBuilder text = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            text.append(textBase);
        }

        final RSA rsa = new RSA();

        // 公钥加密,私钥解密
        String encryptStr = rsa.encryptBase64(text.toString(), KeyType.PublicKey);
        String decryptStr = StrUtil.utf8Str(rsa.decrypt(encryptStr, KeyType.PrivateKey));
        Assert.assertEquals(text.toString(), decryptStr);

        // 私钥加密,公钥解密
        String encrypt2 = rsa.encryptBase64(text.toString(), KeyType.PrivateKey);
        String decrypt2 = StrUtil.utf8Str(rsa.decrypt(encrypt2, KeyType.PublicKey));
        Assert.assertEquals(text.toString(), decrypt2);
    }

    @Test
    public void rsaDecodeTest() {
        String PRIVATE_KEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIL7pbQ+5KKGYRhw7jE31hmA" //
                + "f8Q60ybd+xZuRmuO5kOFBRqXGxKTQ9TfQI+aMW+0lw/kibKzaD/EKV91107xE384qOy6IcuBfaR5lv39OcoqNZ"//
                + "5l+Dah5ABGnVkBP9fKOFhPgghBknTRo0/rZFGI6Q1UHXb+4atP++LNFlDymJcPAgMBAAECgYBammGb1alndta" //
                + "xBmTtLLdveoBmp14p04D8mhkiC33iFKBcLUvvxGg2Vpuc+cbagyu/NZG+R/WDrlgEDUp6861M5BeFN0L9O4hz"//
                + "GAEn8xyTE96f8sh4VlRmBOvVdwZqRO+ilkOM96+KL88A9RKdp8V2tna7TM6oI3LHDyf/JBoXaQJBAMcVN7fKlYP" //
                + "Skzfh/yZzW2fmC0ZNg/qaW8Oa/wfDxlWjgnS0p/EKWZ8BxjR/d199L3i/KMaGdfpaWbYZLvYENqUCQQCobjsuCW"//
                + "nlZhcWajjzpsSuy8/bICVEpUax1fUZ58Mq69CQXfaZemD9Ar4omzuEAAs2/uee3kt3AvCBaeq05NyjAkBme8SwB0iK"//
                + "kLcaeGuJlq7CQIkjSrobIqUEf+CzVZPe+AorG+isS+Cw2w/2bHu+G0p5xSYvdH59P0+ZT0N+f9LFAkA6v3Ae56OrI"//
                + "wfMhrJksfeKbIaMjNLS9b8JynIaXg9iCiyOHmgkMl5gAbPoH/ULXqSKwzBw5mJ2GW1gBlyaSfV3AkA/RJC+adIjsRGg"//
                + "JOkiRjSmPpGv3FOhl9fsBPjupZBEIuoMWOC8GXK/73DHxwmfNmN7C9+sIi4RBcjEeQ5F5FHZ";

        RSA rsa = new RSA(PRIVATE_KEY, null);

        String a = "2707F9FD4288CEF302C972058712F24A5F3EC62C5A14AD2FC59DAB93503AA0FA17113A020EE4EA35EB53F" //
                + "75F36564BA1DABAA20F3B90FD39315C30E68FE8A1803B36C29029B23EB612C06ACF3A34BE815074F5EB5AA3A"//
                + "C0C8832EC42DA725B4E1C38EF4EA1B85904F8B10B2D62EA782B813229F9090E6F7394E42E6F44494BB8";

        byte[] aByte = HexUtil.decodeHex(a);
        byte[] decrypt = rsa.decrypt(aByte, KeyType.PrivateKey);

        Assert.assertEquals("虎头闯杭州,多抬头看天,切勿只管种地", StrUtil.str(decrypt, CharsetUtil.CHARSET_UTF_8));
    }

    @Test
    public void rsaTest2() throws Exception {
        String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgtQn2JZ34ZC28NWYpAUd98iZ37BUrX/aKzmFbt7clFSs6s" +
                "XqHauqKWqdtLkF2KexO40H1YTX8z2lSgBBOAxLsvaklV8k4cBFK9snQXE9/DDaFt6Rr7iVZMldczhC0JNgTz+SHXT6CBHuX3e9S" +
                "dB1Ua44oncaTWz7OBGLbCiK45wIDAQAB";

        byte[] keyBytes = Base64.decode(publicKeyStr);
        PublicKey publicKey = KeyUtil.generateRSAPublicKey(keyBytes);

        byte[] data = RandomUtil.randomString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 16).getBytes();
        //长度不满足128补0
        byte[] finalData = ArrayUtil.resize(data, 128);

        //jdk原生加密
        Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        String result1 = HexUtil.encodeHexStr(cipher.doFinal(finalData));

        //hutool加密
        RSA rsa = new RSA("RSA/ECB/NoPadding", null, publicKeyStr);
        rsa.setEncryptBlockSize(128);
        String result2 = rsa.encryptHex(finalData, KeyType.PublicKey);

        Assert.assertEquals(result1, result2);
    }

    @Test
    public void exponentTest(){
        String modulus = "BD99BAAB9E56B7FD85FB8BCF53CAD2913C1ACEF9063E7C913CD6FC4FEE040DA44D8" +
                "ADAA35A9DCABD6E936C402D47278049638407135BAB22BB091396CB6873195C8AC8B0B7AB123" +
                "C3BF7A6341A4419BDBC0EFB85DBCD9A3AD12C99E2265BDCC1197913749E2AFA568EB7623DA3A" +
                "361335AA1F9FFA6E1801DDC8228AA86306B87";
        String publicExponent = "65537";
        RSA rsa = new RSA(new BigInteger(modulus, 16), null, new BigInteger(publicExponent));

        final String encryptBase64 = rsa.encryptBase64("测试内容", KeyType.PublicKey);
        Assert.assertNotNull(encryptBase64);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值