【Java 安全】Java加解密--对称/非对称加密,散列函数,数字签名

本文针对对称加密,非对称加密,散列函数和数字签名做一个简单的概述

对称加密

一、介绍

对称加密是指加密和解密用同一个密钥对加密,加密就是通过密码和明文获取到密文,解密就是通过密文和密码,获取到明文

优点:计算速度快,适合数据量大的明文进行加密
缺点:不安全,容易被破解;密钥管理困难

二、常见的加密算法

算法密钥长度工作模式填充模式
DES56/64ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/…
AES128/192/256ECB/CBC/PCBC/CTR/…NoPadding/PKCS5Padding/PKCS7Padding/…
IDEA128ECBPKCS5Padding/PKCS7Padding/…

三、AES加密

	public static void main(String[] args) throws Exception {
        // 原文:
        String message = "Hello, world!";
        System.out.println("明文: " + message);
        // 128位密钥 = 16 bytes Key:
        byte[] key = "HFUOIAYFUGEWGOYO".getBytes("UTF-8");
        // 加密:
        byte[] data = message.getBytes("UTF-8");
        byte[] encrypted = cbcEncrypt(key, data);
        System.out.println("加密: " + Base64.getEncoder().encodeToString(encrypted));
        // 解密:
        byte[] decrypted = cbcDecrypt(key, encrypted);
        System.out.println("解密: " + new String(decrypted, "UTF-8"));
    }

    /**
     * 加密
     *
     * @param key   密钥
     * @param input 明文
     * @return 密文
     * @throws GeneralSecurityException
     */
    public static byte[] ecbEncrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }

    /**
     * 解密
     *
     * @param key   密钥
     * @param input 密文
     * @return 明文
     * @throws GeneralSecurityException
     */
    public static byte[] ecbDecrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        SecretKey keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        return cipher.doFinal(input);
    }

// ============ CBC 模式 ===========

    /**
     * CBC 模式加密
     * @param key 密钥
     * @param input 密文
     * @return 明文
     * @throws GeneralSecurityException
     */
    public static byte[] cbcEncrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        // CBC模式需要生成一个16 bytes的initialization vector:
        SecureRandom sr = SecureRandom.getInstanceStrong();
        byte[] iv = sr.generateSeed(16);
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivps);
        byte[] data = cipher.doFinal(input);
        // IV不需要保密,把IV和密文一起返回:
        return join(iv, data);
    }

    /**
     * CBC 模式解密
     * @param key 密钥
     * @param input 密文
     * @return 明文
     * @throws GeneralSecurityException
     */
    public static byte[] cbcDecrypt(byte[] key, byte[] input) throws GeneralSecurityException {
        // 把input分割成IV和密文:
        byte[] iv = new byte[16];
        byte[] data = new byte[input.length - 16];
        System.arraycopy(input, 0, iv, 0, 16);
        System.arraycopy(input, 16, data, 0, data.length);
        // 解密:
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        IvParameterSpec ivps = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivps);
        return cipher.doFinal(data);
    }

    public static byte[] join(byte[] bs1, byte[] bs2) {
        byte[] r = new byte[bs1.length + bs2.length];
        System.arraycopy(bs1, 0, r, 0, bs1.length);
        System.arraycopy(bs2, 0, r, bs1.length, bs2.length);
        return r;
    }

非对称加密

一、介绍

非对称加密的加密和解密使用的密钥是不一样的,公钥是公开的,私钥是私密的,只有同一对密钥进行加解密。
公钥加密需要私钥解密,反之,私钥加密需要公钥解密

优点:更加安全,密钥也更加便于管理
缺点:运算速度慢

二、常用算法

RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)。其中RSA使用最为广泛。

三、应用场景

  1. 信息加密:用于一些重要数据传输过程中,对信息的加密,发送方将信息用公钥加密,接收方用私钥进行解密,能保证数据不被他人窃取
  2. 数字签名:类似于手写签名一样,保证数据是发送发发送的,具有不可抵赖性
  3. 数字信封:信息发送者首先利用随机产生的【对称密码】加密信息(因为非对称加密技术的速度比较慢),再利用接收方的【公钥】加密对称密码,被公钥加密后的对称密钥被称之为数字信封。在传递信息时,信息接收方要解密信息时,必须先用自己的私钥解密数字信封,得到对称密码,才能利用对称密码解密所得到的信息。
  4. 数字证书:CA 用自己的私钥对信息原文所有者发布的公钥和相关信息进行加密,得出的内容就是数字证书。

四、RSA加密

	/**
     * RSA公钥加密
     *
     * @param data       加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception 加密过程中的异常信息
     */
    private static String encrypt(String data, String publicKey) throws Exception {
        // base64 编码的公钥
        byte[] decoded = Base64.getDecoder().decode(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        // RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        // 公钥加密
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data.getBytes("UTF-8")));
    }
    
 	/**
     * RSA私钥解密
     *
     * @param data        加密字符串
     * @param privateKey 私钥
     * @return 铭文
     * @throws Exception 解密过程中的异常信息
     */
    private static String decrypt(String data, String privateKey) throws Exception {
        byte[] inputByte = Base64.getDecoder().decode(data.getBytes("UTF-8"));
        // base64 编码的私钥
        byte[] decoded = Base64.getDecoder().decode(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        // RSA 解密
        Cipher cipher = Cipher.getInstance("RSA");
        // 私钥解密
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }

散列函数

一、介绍

散列函数又称哈希函数、消息摘要函数、单向函数或者杂凑函数。散列函数主要用来验证数据完整性的重要技术,通过散列函数,可以为数据创造一个散列值。通常是一个随机字母和数字组成的字符串。

二、特征

  1. 固定的长度:散列函数能够接收任意长度的消息,将其转化成固定长度的散列值
  2. 确定性:如果两个散列值不相同,那么两个散列值的原始输入消息也不相同
  3. 单向性:散列函数的运算过程是不可逆的
  4. 抗弱碰转性:对于一个已知的消息和散列值,要找到另外一个消息并获取到相同的散列值是不可能的。这个特征常用于防伪造
  5. 抗强碰撞性:任意两个消息的散列值是一定不相同的
  6. 雪崩效应:即使消息只有一个字节的变化,得到的散列值也是天差地别的

常用的散列函数

MD(消息摘要算法)
SHA(安全散列算法)
Mac(消息认证码算法)

数字签名

一、介绍

数字签名是针对以数字形式存储的消息进行处理,产生一种带有操作者身份信息的编码。
签名者:执行数字签名的实体
签名算法:签名过程中所使用的算法
原理:发送者将消息用私钥签名,将消息和签名发送给接收者。接收者通过公钥对签名和消息进行验证,验证过程中使用的算法叫做验证算法。签名算法受私钥控制,私钥由签名者保存;验证算法受公钥控制,公钥可向外公开

二、特征

  1. 不可否认性:签名者任何时候都无法否认自己签发的签名
  2. 可认证性:信息接收者能够验证收到的数字签名,但是任何人无法伪造信息发送者的数字签名
  3. 当收发双方对数字签名的真伪产生争议时,可以通过第三方机构进行仲裁

三、常用的数字签名

数字签名算法主要有RSA、DSA、ECDSA三种

RSA

RSA签名算法是比较经典的签名算法,使用范围最为广泛。RSA不仅包含了数字签名算法,还兼并加解密算法。RSA数字签名算法主要包括MD和SHA两种算法。MD系列主要包含了MD2withRSA和MD5withRSA,SHA系列主要包括了SHA1withRSA、SHA224withRSA、SHA256withRSA、SHA384withRSA和SHA512withRSA。

DSA

DSA全称Digital Signature Algorithm,他是最为简单的数字签名算法。他不能用于加解密,也不能用于密钥交换,只可以用于签名。所以他的速度更快。DSA仅支持SHA系列的消息摘要算法。SHA1withDSA、SHA224withDSA、SHA256withDSA、SHA384withDSA和SHA512withDSA。
DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚

ECDSA

ECDSA的安全性更高;计算量小,速度快;存储空间小;带宽要求低

四、RSA签名案例

	public static void main(String[] args) throws Exception {
        // 生成RSA公钥/私钥:
        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
        kpGen.initialize(1024);
        KeyPair kp = kpGen.generateKeyPair();
        PrivateKey privateKey = kp.getPrivate();
        PublicKey publicKey = kp.getPublic();

        // 待签名的消息:
        byte[] message = "Hello, World!".getBytes(StandardCharsets.UTF_8);

        // 用私钥签名:
        Signature s = Signature.getInstance("SHA1withRSA");
        s.initSign(privateKey);
        s.update(message);
        byte[] signed = s.sign();
        System.out.println(String.format("signature: %x", new BigInteger(1, signed)));

        // 用公钥验证:
        Signature v = Signature.getInstance("SHA1withRSA");
        v.initVerify(publicKey);
        v.update(message);
        boolean valid = v.verify(signed);
        System.out.println("valid? " + valid);
    }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值