加密算法

文章1:https://www.cnblogs.com/xibushijie/p/12851771.html

文章2:https://blog.csdn.net/weixin_37069598/article/details/106630717

汇总了网上一些加密算法。(部分未进行实操,在之后工作中使用到会更新正确性)


1.BASE64加密/解密

Base64 编码是我们程序开发中经常使用到的编码方法,它用 64 个可打印字符来表示二进制数据。这 64 个字符是:小写字母 a-z、大写字母 A-Z、数字 0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是 65 个字符),其他所有符号都转换成这个字符集中的字符。Base64 编码通常用作存储、传输一些二进制数据编码方法,所以说它本质上是一种将二进制数据转成文本数据的方案。


通常用作对二进制数据进行加密,示例:


import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;

 public class Base64Util {

 

    /***

     * BASE64解密

     * @param key

     * @return

     * @throws Exception

     */

    public static byte[] decryBASE64(String key) throws Exception{

        return (new BASE64Decoder()).decodeBuffer(key);

    }

    

    /***

     * BASE64加密

     * @param key

     * @return

     * @throws Exception

     */

    public static String encryptBASE64(byte[] key) throws Exception{

        return (new BASE64Encoder()).encode(key);

    }

    }1234567891011121314151617181920212223242526

2.MD5(Message Digest Algorithm)加密/解密

MD5 是将任意长度的数据字符串转化成短小的固定长度的值的单向操作,任意两个字符串不应有相同的散列值。因此 MD5 经常用于校验字符串或者文件,因为如果文件的 MD5 不一样,说明文件内容也是不一样的,如果发现下载的文件和给定的 MD5 值不一样,就要慎重使用。


MD5 主要用做数据一致性验证、数字签名和安全访问认证,而不是用作加密。比如说用户在某个网站注册账户时,输入的密码一般经过 MD5 编码,更安全的做法还会加一层盐(salt),这样密码就具有不可逆性。然后把编码后的密码存入数据库,下次登录的时候把密码 MD5 编码,然后和数据库中的作对比,这样就提升了用户账户的安全性。


是一种单向加密算法,只能加密不能解密,示例:


import java.security.MessageDigest;

 public class MD5Util {

 

    public static final String KEY_MD5 = "MD5";  

    

    /***

     * MD5加密(生成唯一的MD5值)

     * @param data

     * @return

     * @throws Exception

     */

    public static byte[] encryMD5(byte[] data) throws Exception {

        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);

        md5.update(data);

        return md5.digest();

    }

    }12345678910111213141516171819

3.DES(Data Encryption Standard)对称加密/解密

DES 是一种对称加密算法,所谓对称加密算法就是:加密和解密使用相同密钥的算法。DES 加密算法出自 IBM 的研究,后来被美国政府正式采用,之后开始广泛流传。但近些年使用越来越少,因为 DES 使用 56 位密钥,以现代的计算能力,24 小时内即可被破解。


顺便说一下 3DES(Triple DES),它是 DES 向 AES 过渡的加密算法,使用 3 条 56 位的密钥对数据进行三次加密。是 DES 的一个更安全的变形。它以 DES 为基本模块,通过组合分组方法设计出分组加密算法。比起最初的 DES,3DES 更为安全。


使用 Java 实现 DES 加密解密,注意密码长度要是 8 的倍数。加密和解密的 Cipher 构造参数一定要相同,不然会报错。


数据加密标准算法,和BASE64最明显的区别就是有一个工作密钥,该密钥既用于加密、也用于解密,并且要求密钥是一个长度至少大于8位的字符串,示例:


import java.security.Key;import java.security.SecureRandom;

 import javax.crypto.Cipher;import javax.crypto.KeyGenerator;

 import sun.misc.BASE64Decoder;import sun.misc.BASE64Encoder;

 public class DesUtil {

 

    private static Key key;

    

    private static String KEY_STR="myKey";

    private static String CHARSETNAME="UTF-8";

    private static String ALGORITHM="DES";

    

    

    static {

        try {

            //生成DES算法对象

            KeyGenerator generator=KeyGenerator.getInstance(ALGORITHM);

            //运用SHA1安全策略

            SecureRandom secureRandom=SecureRandom.getInstance("SHA1PRNG");

            //设置上密钥种子

            secureRandom.setSeed(KEY_STR.getBytes());

            //初始化基于SHA1的算法对象

            generator.init(secureRandom);

            //生成密钥对象

            key=generator.generateKey();

            generator=null;

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

    

    

    /***

     * 获取加密的信息

     * @param str

     * @return

     */

    public static String getEncryptString(String str) {

        //基于BASE64编码,接收byte[]并转换成String

        BASE64Encoder encoder = new BASE64Encoder();

        try {

            //按utf8编码

            byte[] bytes = str.getBytes(CHARSETNAME);

            //获取加密对象

            Cipher cipher = Cipher.getInstance(ALGORITHM);

            //初始化密码信息

            cipher.init(Cipher.ENCRYPT_MODE, key);

            //加密

            byte[] doFinal = cipher.doFinal(bytes);

            //byte[]to encode好的String 并返回

            return encoder.encode(doFinal);

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

    

    

    /***

     * 获取解密之后的信息

     * @param str

     * @return

     */

    public static String getDecryptString(String str) {

        BASE64Decoder decoder = new BASE64Decoder();

        try {

            //将字符串decode成byte[]

            byte[] bytes = decoder.decodeBuffer(str);

            //获取解密对象

            Cipher cipher = Cipher.getInstance(ALGORITHM);

            //初始化解密信息

            cipher.init(Cipher.DECRYPT_MODE, key);

            //解密

            byte[] doFial = cipher.doFinal(bytes);

            

            return new String(doFial, CHARSETNAME);

            

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

    }

    }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687

4.AES(Advanced Encryption Standard) 加密/解密

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的 DES,已经被多方分析且广为全世界所使用。简单说就是 DES 的增强版,比 DES 的加密强度更高。


AES 与 DES 一样,一共有四种加密模式:电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)。

示例代码:


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

 public class AESUtil {

 

    public static final String algorithm = "AES";

    // AES/CBC/NOPaddin

    // AES 默认模式

    // 使用CBC模式, 在初始化Cipher对象时, 需要增加参数, 初始化向量IV : IvParameterSpec iv = new

    // IvParameterSpec(key.getBytes());

    // NOPadding: 使用NOPadding模式时, 原文长度必须是8byte的整数倍

    public static final String transformation = "AES/CBC/NOPadding";

    public static final String key = "1234567812345678";

 

    /***

     * 加密

     * @param original 需要加密的参数(注意必须是16位)

     * @return

     * @throws Exception

     */

    public static String encryptByAES(String original) throws Exception {

        // 获取Cipher

        Cipher cipher = Cipher.getInstance(transformation);

        // 生成密钥

        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);

        // 指定模式(加密)和密钥

        // 创建初始化向量

        IvParameterSpec iv = new IvParameterSpec(key.getBytes());

        cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);

        // cipher.init(Cipher.ENCRYPT_MODE, keySpec);

        // 加密

        byte[] bytes = cipher.doFinal(original.getBytes());

 

        return Base64Util.encryptBASE64(bytes);

    }

 

    /**

     * 解密

     * @param encrypted 需要解密的参数

     * @return

     * @throws Exception

     */

    public static String decryptByAES(String encrypted) throws Exception {

        // 获取Cipher

        Cipher cipher = Cipher.getInstance(transformation);

        // 生成密钥

        SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), algorithm);

        // 指定模式(解密)和密钥

        // 创建初始化向量

        IvParameterSpec iv = new IvParameterSpec(key.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);

        // cipher.init(Cipher.DECRYPT_MODE, keySpec);

        // 解密

        byte[] bytes = cipher.doFinal(Base64Util.decryBASE64(encrypted));

 

        return new String(bytes);

    }

 }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960

5.HMAC(Hash Message Authentication Code,散列消息鉴别码)

使用一个密钥生成一个固定大小的小数据块,即MAC,并将其加入到消息中,然后传输。接收方利用与发送方共享的密钥进行鉴别认证,示例:


import javax.crypto.KeyGenerator;

import javax.crypto.Mac;

import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;

 

public class HMACUtil {

 

    public static final String KEY_MAC = "HmacMD5";  

    

    /***

     * 初始化HMAC密钥

     * @return

     * @throws Exception

     */

    public static String initMacKey() throws Exception{

        

        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);

        SecretKey secreKey = keyGenerator.generateKey();

        return Base64Util.encryptBASE64(secreKey.getEncoded());

    }

    

    /**

     * HMAC加密

     * @param data

     * @param key

     * @return

     * @throws Exception

     */

    public static byte[] encryHMAC(byte[] data, String key) throws Exception{

        SecretKey secreKey = new SecretKeySpec(Base64Util.decryBASE64(key), KEY_MAC);

        Mac mac = Mac.getInstance(secreKey.getAlgorithm());

        mac.init(secreKey);

        return mac.doFinal();

    }

    


}12345678910111213141516171819202122232425262728293031323334353637

6.恺撒加密

在密码学中,恺撒密码是一种最简单并且最广为人知的加密技术。


它是一种替换加密的技术,明文中的所欲字母都在字母表上向后(或向前)按照一个固定的数目进行偏移后被替换成密文。


例如:当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。


这个加密方法是以恺撒的名字命名的,当年恺撒曾用此方法与其将军们进行联系。


恺撒密码通常被座位其他更复杂的加密方法中的一个步骤。


public class KaisaUtil {

 

    /***

     * 使用凯撒加密方式加密数据

     * @param orignal 原文

     * @param key 密钥

     * @return 加密后的字符

     */

    private static String encryptKaisa(String orignal, int key) {

        //将字符串转换为数组

        char[] chars = orignal.toCharArray();

        StringBuffer buffer = new StringBuffer();

        //遍历数组

        for(char aChar : chars) {

            //获取字符的ASCII编码

            int asciiCode = aChar;

            //偏移数据

            asciiCode += key;

            //将偏移后的数据转为字符

            char result = (char)asciiCode;

            //拼接数据

            buffer.append(result);

        }

        return buffer.toString();

    }

    

    /**

     * 使用凯撒加密方式解密数据

     *

     * @param encryptedData :密文

     * @param key           :密钥

     * @return : 源数据

     */

    private static String decryptKaiser(String encryptedData, int key) {

        // 将字符串转为字符数组

        char[] chars = encryptedData.toCharArray();

        StringBuilder sb = new StringBuilder();

        // 遍历数组

        for (char aChar : chars) {

            // 获取字符的ASCII编码

            int asciiCode = aChar;

            // 偏移数据

            asciiCode -= key;

            // 将偏移后的数据转为字符

            char result = (char) asciiCode;

            // 拼接数据

            sb.append(result);

        }

 

        return sb.toString();

    }

    

    

    public static void main(String[] args) {

        String str = "open fire";

        String encode = encryptKaisa(str, 3);

        System.out.println("加密后:"+encode);

        

        String decode = decryptKaiser(encode, 3);

        System.out.println("解密后:"+decode);

        

    }

    

}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364

7.SHA(Secure Hash Algorithm,安全散列算法)

SHA全名叫做安全散列算法,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。


数字签名等密码学应用中重要的工具,被广泛地应用于电子商务等信息安全领域,示例:


import java.security.MessageDigest;

 public class SHAUtil {

 

    public static final String KEY_SHA = "SHA";  

    

    /***

     * SHA加密(比MD5更安全)

     * @param data

     * @return

     * @throws Exception

     */

    public static byte[] encryptSHA(byte[] data) throws Exception{

        MessageDigest sha = MessageDigest.getInstance(KEY_SHA);

        sha.update(data);

        return sha.digest();

    }

    

    

    public static String SHAEncrypt(final String content) {

        try {

            MessageDigest sha = MessageDigest.getInstance(KEY_SHA);

            byte[] sha_byte = sha.digest(content.getBytes());

            StringBuffer hexValue = new StringBuffer();

            for (byte b : sha_byte) {

                //将其中的每个字节转成十六进制字符串:byte类型的数据最高位是符号位,通过和0xff进行与操作,转换为int类型的正整数。

                String toHexString = Integer.toHexString(b & 0xff);

                hexValue.append(toHexString.length() == 1 ? "0" + toHexString : toHexString);

            }

            return hexValue.toString();

        } catch (Exception e) {

            e.printStackTrace();

        }

       return "";

    }

    }12345678910111213141516171819202122232425262728293031323334353637

8.RSA 加密/解密

RSA算法是一种非对称加密算法,所谓非对称就是该算法需要一对密钥,若使用其中一个加密,则需要用另一个才能解密。目前它是最有影响力和最常用的公钥加密算法,能够抵抗已知的绝大多数密码攻击。从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。


该算法基于一个的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。由于进行的都是大数计算,RSA 最快的情况也比 DES 慢上好几倍,比对应同样安全级别的对称密码算法要慢 1000 倍左右。所以 RSA 一般只用于少量数据加密,比如说交换对称加密的密钥。


使用 RSA 加密主要有这么几步:生成密钥对、公开公钥、公钥加密私钥解密、私钥加密公钥解密。


示例代码:


import com.sun.org.apache.xml.internal.security.utils.Base64;import javax.crypto.Cipher;

 import org.apache.commons.io.FileUtils;

 import java.io.ByteArrayOutputStream;import java.io.File;import java.nio.charset.Charset;import java.security.*;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;

 public class RsaUtil {

 

    /**

     * 生成密钥对并保存在本地文件中

     *

     * @param algorithm : 算法

     * @param pubPath   : 公钥保存路径

     * @param priPath   : 私钥保存路径

     * @throws Exception

     */

    private static void generateKeyToFile(String algorithm, String pubPath, String priPath) throws Exception {

        // 获取密钥对生成器

        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);

        // 获取密钥对

        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取公钥

        PublicKey publicKey = keyPair.getPublic();

        // 获取私钥

        PrivateKey privateKey = keyPair.getPrivate();

        // 获取byte数组

        byte[] publicKeyEncoded = publicKey.getEncoded();

        byte[] privateKeyEncoded = privateKey.getEncoded();

        // 进行Base64编码

        String publicKeyString = Base64.encode(publicKeyEncoded);

        String privateKeyString = Base64.encode(privateKeyEncoded);

        // 保存文件

        FileUtils.writeStringToFile(new File(pubPath), publicKeyString, Charset.forName("UTF-8"));

        FileUtils.writeStringToFile(new File(priPath), privateKeyString, Charset.forName("UTF-8"));

 

    }

 

    /**

     * 从文件中加载公钥

     *

     * @param algorithm : 算法

     * @param filePath  : 文件路径

     * @return : 公钥

     * @throws Exception

     */

    private static PublicKey loadPublicKeyFromFile(String algorithm, String filePath) throws Exception {

        // 将文件内容转为字符串

        String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));

 

        return loadPublicKeyFromString(algorithm, keyString);

 

    }

 

    /**

     * 从字符串中加载公钥

     *

     * @param algorithm : 算法

     * @param keyString : 公钥字符串

     * @return : 公钥

     * @throws Exception

     */

    private static PublicKey loadPublicKeyFromString(String algorithm, String keyString) throws Exception {

        // 进行Base64解码

        byte[] decode = Base64.decode(keyString);

        // 获取密钥工厂

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

        // 构建密钥规范

        X509EncodedKeySpec keyspec = new X509EncodedKeySpec(decode);

        // 获取公钥

        return keyFactory.generatePublic(keyspec);

 

    }

 

    /**

     * 从文件中加载私钥

     *

     * @param algorithm : 算法

     * @param filePath  : 文件路径

     * @return : 私钥

     * @throws Exception

     */

    private static PrivateKey loadPrivateKeyFromFile(String algorithm, String filePath) throws Exception {

        // 将文件内容转为字符串

        String keyString = FileUtils.readFileToString(new File(filePath), Charset.forName("UTF-8"));

        return loadPrivateKeyFromString(algorithm, keyString);

 

    }

 

    /**

     * 从字符串中加载私钥

     *

     * @param algorithm : 算法

     * @param keyString : 私钥字符串

     * @return : 私钥

     * @throws Exception

     */

    private static PrivateKey loadPrivateKeyFromString(String algorithm, String keyString) throws Exception {

        // 进行Base64解码

        byte[] decode = Base64.decode(keyString);

        // 获取密钥工厂

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

        // 构建密钥规范

        PKCS8EncodedKeySpec keyspec = new PKCS8EncodedKeySpec(decode);

        // 生成私钥

        return keyFactory.generatePrivate(keyspec);

 

    }

 

    /**

     * 使用密钥加密数据

     *

     * @param algorithm      : 算法

     * @param input          : 原文

     * @param key            : 密钥

     * @param maxEncryptSize : 最大加密长度(需要根据实际情况进行调整)

     * @return : 密文

     * @throws Exception

     */

    private static String encrypt(String algorithm, String input, Key key, int maxEncryptSize) throws Exception {

        // 获取Cipher对象

        Cipher cipher = Cipher.getInstance(algorithm);

        // 初始化模式(加密)和密钥

        cipher.init(Cipher.ENCRYPT_MODE, key);

        // 将原文转为byte数组

        byte[] data = input.getBytes();

        // 总数据长度

        int total = data.length;

        // 输出流

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        decodeByte(maxEncryptSize, cipher, data, total, baos);

        // 对密文进行Base64编码

        return Base64.encode(baos.toByteArray());

 

    }

 

    /**

     * 解密数据

     *

     * @param algorithm      : 算法

     * @param encrypted      : 密文

     * @param key            : 密钥

     * @param maxDecryptSize : 最大解密长度(需要根据实际情况进行调整)

     * @return : 原文

     * @throws Exception

     */

    private static String decrypt(String algorithm, String encrypted, Key key, int maxDecryptSize) throws Exception {

        // 获取Cipher对象

        Cipher cipher = Cipher.getInstance(algorithm);

        // 初始化模式(解密)和密钥

        cipher.init(Cipher.DECRYPT_MODE, key);

        // 由于密文进行了Base64编码, 在这里需要进行解码

        byte[] data = Base64.decode(encrypted);

        // 总数据长度

        int total = data.length;

        // 输出流

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

 

        decodeByte(maxDecryptSize, cipher, data, total, baos);

        // 输出原文

        return baos.toString();

 

    }

 

    /**

     * 分段处理数据

     *

     * @param maxSize : 最大处理能力

     * @param cipher  : Cipher对象

     * @param data    : 要处理的byte数组

     * @param total   : 总数据长度

     * @param baos    : 输出流

     * @throws Exception

     */

    private static void decodeByte(int maxSize, Cipher cipher, byte[] data, int total, ByteArrayOutputStream baos) throws Exception {

        // 偏移量

        int offset = 0;

        // 缓冲区

        byte[] buffer;

        // 如果数据没有处理完, 就一直继续

        while (total - offset > 0) {

            // 如果剩余的数据 >= 最大处理能力, 就按照最大处理能力来加密数据

            if (total - offset >= maxSize) {

                // 加密数据

                buffer = cipher.doFinal(data, offset, maxSize);

                // 偏移量向右侧偏移最大数据能力个

                offset += maxSize;

            } else {

                // 如果剩余的数据 < 最大处理能力, 就按照剩余的个数来加密数据

                buffer = cipher.doFinal(data, offset, total - offset);

                // 偏移量设置为总数据长度, 这样可以跳出循环

                offset = total;

            }

            // 向输出流写入数据

            baos.write(buffer);

        }

    }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202

加密算法的安全级别(Security Level of Cryptographic Algorithms):


安全级别 (Security Level)   工作因素(Work Factor)   算法 (Algorithms)


薄弱(Weak)           O(240)           DES, MD5

传统(Legacy)          O(264)           RC4, SHA-1

基准(Baseline)         O(280)           3DES

标准(Standard)        O(2128)           AES-128, SHA-256

较高(High)          O(2192)           AES-192, SHA-384

超高(Ultra)          O(2256)           AES-256, SHA-512


9.PBE 加密/解密

PBE是一种基于口令的加密算法,使用口令代替其他对称加密算法中的密钥,其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。


PBE算法是对称加密算法的综合算法,常见算法PBEWithMD5AndDES,使用MD5和DES算法构建了PBE算法。将盐附加在口令上,通过消息摘要算法经过迭代获得构建密钥的基本材料,构建密钥后使用对称加密算法进行加密解密。


算法/密钥长度/默认密钥长度:


1.PBEWithMD5AndDES/56/56

2.PBEWithMD5AndTripleDES/112,168/168

3.PBEWithSHA1AndDESede/112,168/168

4.PBEWithSHA1AndRC2_40/40 to 1024/128


工作模式:CBC

填充方式:PKCS5Padding


import java.security.Key;import java.security.SecureRandom;

  import javax.crypto.Cipher;import javax.crypto.SecretKeyFactory;import javax.crypto.spec.PBEKeySpec;import javax.crypto.spec.PBEParameterSpec;

  public class PBEUtil {

  

    public static final String ALGORITHM = "PBEWITHMD5andDES";

     

    public static final int ITERATION_COUNT = 100;

     

     

    public static byte[] initSalt() throws Exception{

        //实例化安全随机数

        SecureRandom random = new SecureRandom();

        return random.generateSeed(8);

    }

     

    /***

     * 转换密钥

     * @param password 密码

     * @return 密钥

     * @throws Exception

     */

    private static Key toKey(String password) throws Exception{

        //密钥材料

        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());

        //实例化

        SecretKeyFactory factory = SecretKeyFactory.getInstance(ALGORITHM);

        //生成密钥

        return factory.generateSecret(keySpec);

    }

     

    /***

     * 加密

     * @param data 待加密数据

     * @param password 密钥

     * @param salt

     * @return

     * @throws Exception

     */

    public static byte[] encrypt(byte[] data, String password, byte[] salt) throws Exception{

        //转换密钥

        Key key = toKey(password);

        //实例化PBE参数材料

        PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT);

        //实例化

        Cipher cipher = Cipher.getInstance(ALGORITHM);

        //初始化

        cipher.init(Cipher.ENCRYPT_MODE, key, spec);

        return cipher.doFinal(data);

    }

     

     

    /***

     * 解密

     * @param data 待解密数据

     * @param password 密钥

     * @param salt

     * @return

     * @throws Exception

     */

    public static byte[] decrypt(byte[] data, String password, byte[] salt) throws Exception{

        //转换密钥

        Key key = toKey(password);

        //实例化PBE参数材料

        PBEParameterSpec spec = new PBEParameterSpec(salt, ITERATION_COUNT);

        //实例化

        Cipher cipher = Cipher.getInstance(ALGORITHM);

        //初始化 

        cipher.init(Cipher.DECRYPT_MODE, key, spec);

        //执行操作 

        return cipher.doFinal(data); 

    }

     

     

    private static String showByteArray(byte[] data) {

        if(null == data) {

            return null;

        }

        StringBuilder sb = new StringBuilder();

        for(byte b : data) {

            sb.append(b).append(",");

        }

        sb.deleteCharAt(sb.length()-1);

        sb.append("");

        return sb.toString();

    }

     

     

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

        byte[] salt = initSalt();

        System.out.println("salt:"+showByteArray(salt));

        String password = "1111";

        System.out.println("口令:"+password);

        String data = "PBE数据";

        System.out.println("加密前数据:String:"+data);

        System.out.println("加密前数据:byte[]:"+showByteArray(data.getBytes()));

         

        byte[] encryptData = encrypt(data.getBytes(), password, salt);

        System.out.println("加密后数据:byte[]:"+showByteArray(encryptData));

         

        byte[] decryptData = decrypt(encryptData, password, salt);

        System.out.println("解密后数据: byte[]:"+showByteArray(decryptData));

        System.out.println("解密后数据: string:"+new String(decryptData));

    }123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109

10.RC4 加密/解密

RC4算法原理

利用Key生成S盒——The key-scheduling algorithm (KSA)


密钥调度算法用于初始化数组S盒中的置换。“keylength”被定义为密钥中的字节数,并且可以在1≤keylength≤256的范围内,通常在5和16之间,对应于40到128位的密钥长度。首先,数组“S”被初始化为i。 然后以类似于PRGA的方式对S进行256次迭代处理,同时也以密钥的字节为单位进行混合。


利用S盒生成密钥流——The pseudo-random generation algorithm(PRGA)


对于需要的迭代次数,PRGA修改状态并输出一个字节的密钥流。在每次迭代中,PRGA递增i,将i指向的S的值与j相加,交换S [i]和S [j]的值,然后在S [i] + S [j](模256)。每256个迭代,S的每个元素至少与另一个元素交换一次。


代码示例:


package RC4;import java.util.Random;public class Rc4Demo {

    public static void main(String[] args) {

        String inputStr = "做个好男人,然后你才能娶到一个好老婆,come on,boy! 顽张ります! ";//        String key = "abcdefghijklmnop";   // 固定秘钥


        String key = getKey();              // 随机秘钥//        System.out.println("秘钥是:" + key);


        String str = HloveyRC4(inputStr,key);


        //打印加密后的字符串

        System.out.println(str);


        //打印解密后的字符串

        System.out.println(HloveyRC4(str,key));

    }


    // 随机秘钥方法

    public static String getKey(){

        char[] k = new char[16];

        Random r = new Random();

        for (int i = 0; i < 16; i++) {

            k[i] = (char) ('a' + r.nextInt()%26);

        }

        String  s=new String(k);

        return s;


    }


    public static String HloveyRC4(String aInput,String aKey)

    {

        int[] iS = new int[256];

        byte[] iK = new byte[256];


        // 1.1 KSA--密钥调度算法--利用key来对S盒做一个置换,也就是对S盒重新排列

        for (int i=0;i<256;i++)

            iS[i]=i;


        int j;


        for (short i= 0;i<256;i++)

        {

            iK[i]=(byte)aKey.charAt((i % aKey.length()));

        }


        j=0;


        for (int i=0;i<256;i++)

        {

            j=(j+iS[i]+iK[i]) % 256;

            int temp = iS[i];

            iS[i]=iS[j];

            iS[j]=temp;

        }


        // 1.2 RPGA--伪随机生成算法--利用上面重新排列的S盒来产生任意长度的密钥流

        int i=0;

        j=0;

        char[] iInputChar = aInput.toCharArray();

        char[] iOutputChar = new char[iInputChar.length];

        for(short x = 0;x<iInputChar.length;x++)

        {

            i = (i+1) % 256;

            j = (j+iS[i]) % 256;

            int temp = iS[i];

            iS[i]=iS[j];

            iS[j]=temp;

            int t = (iS[i]+(iS[j] % 256)) % 256;

            int iY = iS[t];

            char iCY = (char)iY;

            iOutputChar[x] =(char)( iInputChar[x] ^ iCY) ;

        }

        return new String(iOutputChar);

    }}