java 常用加解密算法總結

細心的開發會發現,我們在下載文件時,會帶有密文,這是幹嘛的呢,是用來校驗下載的文件完整性和正確性,防止文件被篡改。

如下圖:

加解密測試代碼:

package com;

import java.io.File;
import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils;

public class Test {
    //DES也可以用,要保證明文字節數爲8字節
    private final static String CIPHER_ALGORITHM_AES = "AES";
    private final static String CIPHER_ALGORITHM_RSA = "RSA";
    private final static String KEY_CHARSET_NAME = "ASCII";
    private final static String PLAIN_TEXT_CHARSET_NAME = "UTF-8";

    public static void main(String[] args) throws Exception {

        //測試的明文
        String str = "hello world";
        //明文密鑰
        String aesKey = "1";

        //MD5,常用於校驗網絡上下載的文件的完整性和正確性
        String md5 = DigestUtils.md5Hex(new FileInputStream(new File("D://apache-activemq-5.15.10-bin.tar.gz")));
        System.out.println("MD5:" + md5 + ",位數:" + md5.length());

        //SHA512,常用於校驗網絡上下載的文件的完整性和正確性
        String sha512 = DigestUtils.sha512Hex(new FileInputStream(new File("D://apache-activemq-5.15.10-bin.tar.gz")));
        System.out.println("SHA512:" + sha512 + ",位數:" + sha512.length());
        System.out.println();

        System.out.println("明文:" + str);
        //base64
        //編碼
        String base64Encode = new String(Base64.encodeBase64(str.getBytes()));
        System.out.println("------------------base64編碼,解碼-----------------------------");
        System.out.println("base64編碼:" + base64Encode);

        //解碼
        String base64Decode = new String(Base64.decodeBase64(base64Encode.getBytes()));
        System.out.println("base64解碼:" + base64Decode);
        System.out.println();

        //AES/DES,加解密
        String enctrypt = aesEncrypt(str, aesKey);
        System.out.println("------------------AES加解密-----------------------------");
        System.out.println("密文:" + enctrypt);
        System.out.println("明文:" + aesDecrypt(enctrypt, aesKey));
        System.out.println();

        //RSA,非對稱加解密
        String publicKey = getPublicKey(aesKey);
        String privateKey = getPrivateKey(aesKey);
        System.out.println("------------------RSA公鑰,私鑰,對明文生成公鑰和私鑰,公鑰加密,私鑰解密,或者私鑰加密,公鑰解密-----------------------------");
        System.out.println("RSA公鑰:" + publicKey);
        System.out.println("RSA私鑰:" + privateKey);

        //公鑰加密
        String encStr = RSAencrypt(str, publicKey);
        //私鑰解密
        String decStr = RSAdecrypt(encStr, privateKey);
        System.out.println("-------------------------------------------------------");
        System.out.println("RSA密文:" + encStr);
        System.out.println("RSA明文:" + decStr);
    }

    /**
     * RSA公鑰加密
     *
     * @param str
     * @param publicKey
     * @return
     * @throws Exception
     */
    public static String RSAencrypt(String str, String publicKey) throws Exception {
        //base64編碼的公鑰
        byte[] decoded = Base64.decodeBase64(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey)KeyFactory.getInstance(CIPHER_ALGORITHM_RSA).generatePublic(
            new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_RSA);
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes(PLAIN_TEXT_CHARSET_NAME)));
        return outStr;
    }

    /**
     * rsa私鑰解密
     *
     * @param str
     * @param privateKey
     * @return
     * @throws Exception
     */
    public static String RSAdecrypt(String str, String privateKey) throws Exception {
        //64位解碼加密後的字符串
        byte[] inputByte = Base64.decodeBase64(str.getBytes(PLAIN_TEXT_CHARSET_NAME));
        //base64編碼的私鑰
        byte[] decoded = Base64.decodeBase64(privateKey);
        RSAPrivateKey priKey = (RSAPrivateKey)KeyFactory.getInstance(CIPHER_ALGORITHM_RSA).generatePrivate(
            new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_RSA);
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        String outStr = new String(cipher.doFinal(inputByte));
        return outStr;
    }

    private static String getPublicKey(String slatKey) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CIPHER_ALGORITHM_RSA);
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(slatKey.getBytes());
        keyPairGenerator.initialize(1024, random);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
    }

    /**
     * 根據slatKey獲取私匙,傳入的slatKey作爲SecureRandom的隨機種子
     */
    private static String getPrivateKey(String slatKey) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(CIPHER_ALGORITHM_RSA);
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
        random.setSeed(slatKey.getBytes());
        keyPairGenerator.initialize(1024, random);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
    }

    /**
     * 加密
     *
     * @param plainText
     * @param aesKey
     * @return
     */
    private static String aesEncrypt(String plainText, String aesKey) {
        try {
            SecretKey key = generateAesKey(aesKey, KEY_CHARSET_NAME);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_AES);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] plainBytes = plainText.getBytes(PLAIN_TEXT_CHARSET_NAME);
            byte[] cipherBytes = cipher.doFinal(plainBytes);

            return new String(Hex.encodeHex(cipherBytes));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密
     *
     * @param content
     * @param aesKey
     * @return
     */
    private static String aesDecrypt(String content, String aesKey) {
        try {
            SecretKey key = generateAesKey(aesKey, KEY_CHARSET_NAME);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_AES);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] encryptBytes = Hex.decodeHex(content.toCharArray());
            byte[] plainBytes = cipher.doFinal(encryptBytes);

            return new String(plainBytes, PLAIN_TEXT_CHARSET_NAME);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static SecretKeySpec generateAesKey(final String key, final String encoding) {
        try {
            final byte[] finalKey = new byte[16];
            int i = 0;
            for (byte b : key.getBytes(encoding)) {
                finalKey[i++ % 16] ^= b;
            }
            return new SecretKeySpec(finalKey, CIPHER_ALGORITHM_AES);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章