常见加解密算法代码实现加密与解密

常用的加密算法_不可逆加密算法

对称加密和非对称加密的区别

识别密文方式

常用URL特殊字符的转义 _%2f 转义

Enctypt()这个函数很关键,一般来说加密方法里面都会有这个单词

加密是通过某种算法将原本的数据内容加密为特殊的参数
,网上也有很多自称是可以破解MD5密码的网站,其原理也是一样,就是有一个巨大的资源库,存放了许多字符串及对应的MD5加密后的字符串,通过你输入的MD5加密串来进行比较,如果过你的密码复杂度比较低,还是有很大机率验证出来的

加密方式

Md5加密: 通过md5加密会生成一个16位或者32位的加密参数               特征: 16位或32位  不可逆
对称加密DES/AES两个: 就是加密和解密用的是同一把钥匙                特征: 秘加密解密钥匙唯一  可逆
非对称加密RSA: 有加密公匙和解密私匙                               特征: 加密解密钥匙不唯一  可逆
Base64伪加密: 将数据以另外一种编码方式呈现                        特征: 表示真正的加密算法   可逆

MD5 (不可逆向需要Key)

MD5.js是通过前台js加密的方式对用户信息,密码等私密信息进行加密处理的工具,也可称为插件

MD5共有6种加密方法:

  • hex_md5(value)
  • b64_md5(value)
  • str_md5(value)

HMAC 消息认证码,就是最后加密完成的数据

  • hex_hmac_md5(key, data)
  • b64_hmac_md5(key, data)
  • str_hmac_md5(key, data)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./md5.js"></script>>
</head>
<body>
    <p>你好世界</p>
    <script>
        var code = "123456";
        var username = "123456";
        var password = "123456";
        var str1 = hex_md5("123456");
        var str2 = b64_md5("123456");
        var str3 = str_md5("123456");
        var str4 = hex_hmac_md5(code,code);
        var str5 = b64_hmac_md5(username,username);
        var str6 = str_hmac_md5(password,password);
        console.log(str1);            // e10adc3949ba59abbe56e057f20f883e
        console.log(str2);            // 4QrcOUm6Wau+VuBX8g+IPg
        console.log(str3);            // áÜ9IºY«¾VàWò��
        console.log(str4);            // 30ce71a73bdd908c3955a90e8f7429ef
        console.log(str5);            // MM5xpzvdkIw5VakOj3Qp7w
        console.log(str6);            // 0Îq§;Ý��9U©��t)ï
</script>
</body>
</html>

在这里插入图片描述

判断方式

  • 密文一般为 16 位或者 32 位,其中 16 位是取的 32 位第 9~25 位的值;
  • 组成方式为字母(a-f)和数字(0-9)混合,字母可以全部是大写或者小写。

除了通过密文特征来判断以外,我们还可以搜索源代码,标准 MD5 的源码里是包含了一些特定的值的,没有这些特定值,就无法实现 MD5:

  • 0123456789ABCDEF0123456789abcdef
  • 1732584193-271733879-1732584194271733878

PS:某些特殊情况下,密文的长度也有可能不止 16 位或者 32 位,有可能是在官方算法上有一些魔改,通常也是在 16 位的基础上,左右填充了一些随机字符串。

在这里插入图片描述

Base64编码转换 (可逆)

Base64 使用了 64 个可打印字符(A-Z、a-z、0-9、+、/)Base16 使用了 16 个可打印字符(A-F、0-9)

下列代码可以将普通的字符串通过方法转换为Base64编码的数字

<html>
    <head>
        <title>前端的base64使用方法</title>
    </head>
    <body>
    </body>
<script>
var str = "hello";
var str64 = window.btoa("hello"); // 编码方法
console.log("字符串是:"+str);
console.log("经base64编码后:"+str64);
console.log("base64解码后:"+window.atob(str64)); // 解码方法
</script>
</html>

在这里插入图片描述

判断方式

Base编码系统特征如下

Base16:结尾没有等号,数字要多于字母;

Base32:字母要多于数字,明文数量超过 10 个,结尾可能会有很多等号;

Base58:结尾没有等号,字母要多于数字;

Base64:一般情况下结尾都会有 1 个或者 2 个等号,明文很少的时候可能没有;

Base85:等号一般出现在字符串中间,含有一些奇怪的字符;

Base100:密文由 Emoji 表情组成

在这里插入图片描述

sha1 (不可逆

哈希算法

SHA1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦数据处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。

SHA256是SHA2的一种,可产生256位的哈希值,较SHA1更加的安全

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sha1</title>
    <script src="https://cdn.bootcss.com/js-sha1/0.6.0/sha1.js"></script>
</head>
<body>
<p>sha1加解密</p>
    


<script type="text/javascript">
        var sha1_1 = sha1("mosquito~");
        console.log(sha1_1);
        var sha1_2 = sha1("admin:1001");
        console.log(sha1_2);
</script>
</body>
</html>

在这里插入图片描述

编码/解码字符串原生函数

使用JS函数的escape()unescape() 分别是编码和解码字符串

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>sha1</title>
</head>
<body>

<p>编码解码字符串</p>

<script type="text/javascript">
    var escape1 =escape("我的名字是:mosquito~"); // 将里面的字符串编码
    console.log(escape1);
    var unescape1 = unescape(escape1); //解码 // 解码编码后的字符串
    console.log(unescape1);
</script>  
</script>
</body>
</html>

在这里插入图片描述

对称加密AES/DES 唯一 可逆需要key

对称加密算法只是为了区分非对称加密算法。其中鲜明的特点是对称加密是加密解密使用相同的密钥,而非对称加密加密和解密时使用的密钥不一样 对称就是相同的,不对称就是不唯一的 各有优点

使用场景

对于大部分情况我们都使用对称加密,而对称加密的密钥交换时使用非对称加密,这有效保护密钥的安全。非对称加密加密和解密密钥不同,那么它的安全性是无疑最高的,但是它加密解密的速度很慢,不适合对大数据加密。而对称加密加密速度快,因此混合使用最好

  • AES:高级加密标准,新一代标准,加密速度更快,安全性更高(不用说优先选择)
  • DES:比较老的算法,一共有三个参数入口(原文,密钥,加密模式)。而3DES只是DES的一种模式,是以DES为基础更安全的变形,对数据进行了三次加密,也是被指定为AES的过渡算法

AES的使用

AES密钥长度可以选择128位【16字节】,192位【24字节】和256位【32字节】密钥(其他不行,因此别乱设密码哦

AES支持五种模式:CBC,CFB,ECB,OFB,PCBC,

ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。
ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量

Java语言实现AES算法的加解密
键盘录入需要录入的规则是加密时使用的密钥,也就是加密规则。加密规则需要和解密时使用的密钥相同,否则无法正确解密。因此,加密规则和解密规则之间非常重要。在实际应用中,加密规则需要保密,只有知道加密规则的人才能正确解密

**注意:**如果攻击者能够获取加密使用的密钥,就可以通过逆向分析得出加密的规则,从而破解加密。因此,在实际应用中,加密规则需要保密,只有知道加密规则的人才能正确解密。同时,还需要采取其他安全措施,如加密传输通道、使用安全的存储方式等,以保护加密数据的安全。

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Scanner;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

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

public class RSAUtil {
    /*
     * 加密 1.构造密钥生成器 2.根据ecnodeRules规则初始化密钥生成器 3.产生密钥 4.创建和初始化密码器 5.内容加密 6.返回字符串
     */
    public static String AESEncode(String encodeRules, String content) {
        try {
            // 1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            // 2.根据ecnodeRules规则初始化密钥生成器
            // 生成一个128位的随机源,根据传入的字节数组
            keygen.init(128, new SecureRandom(encodeRules.getBytes()));
            // 3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            // 4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            // 5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            // 6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byte_encode = content.getBytes("utf-8");
            // 9.根据密码器的初始化方式--加密:将数据加密
            byte[] byte_AES = cipher.doFinal(byte_encode);
            // 10.将加密后的数据转换为字符串
            // 这里用Base64Encoder中会找不到包
            // 解决办法:
            // 在项目的Build path中先移除JRE System Library,再添加库JRE System
            // Library,重新编译后就一切正常了。
            String AES_encode = new String(new BASE64Encoder().encode(byte_AES));
            // 11.将字符串返回
            return AES_encode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 如果有错就返加nulll
        return null;
    }

    /*
     * 解密 解密过程: 1.同加密1-4步 2.将加密后的字符串反纺成byte[]数组 3.将加密内容解密
     */
    public static String AESDncode(String encodeRules, String content) {
        try {
            // 1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            // 2.根据ecnodeRules规则初始化密钥生成器
            // 生成一个128位的随机源,根据传入的字节数组
            keygen.init(128, new SecureRandom(encodeRules.getBytes()));
            // 3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            // 4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            // 5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            // 6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            // 8.将加密并编码后的内容解码成字节数组
            byte[] byte_content = new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
            byte[] byte_decode = cipher.doFinal(byte_content);
            String AES_decode = new String(byte_decode, "utf-8");
            return AES_decode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }

        // 如果有错就返加nulll
        return null;
    }

    public static void main(String[] args) {
        RSAUtil jm = new RSAUtil();
        Scanner scanner = new Scanner(System.in);
        /*
         * 加密
         */
        System.out.println("使用AES对称加密,请输入加密的规则");
        String encodeRules = scanner.next();
        System.out. println ("请输入要加密的内容:");
        String content = scanner.next();
        System.out.println("根据输入的规则" + encodeRules + "加密后的密文是:"
                + jm.AESEncode(encodeRules, content));

        /*
         * 解密
         */
        System.out.println("使用AES对称解密,请输入加密的规则:(须与加密相同)");
        encodeRules = scanner.next();
        System.out.println("请输入要解密的内容(密文):");
        content = scanner.next();
        System.out.println("根据输入的规则" + encodeRules + "解密后的明文是:"
                + jm.AESDncode(encodeRules, content));
    }
}

------------------------------------------------------

输出:

使用AES对称加密,请输入加密的规则
zhang
请输入要加密的内容:
123
根据输入的规则zhang加密后的密文是:JXHBwSB8AAspwb5k4YvExQ==
使用AES对称解密,请输入加密的规则:(须与加密相同)
zhang
请输入要解密的内容(密文):
JXHBwSB8AAspwb5k4YvExQ==
根据输入的规则zhang解密后的明文是:123

DES的使用

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

非对称RSA加密 不唯一 可逆

JS中没有私钥是无法解密的,只能通过公钥去加密结果

非对称加密加密解密时使用的不同的密钥,分为公钥(public key)和私钥(private key).公钥可以公开,而私钥自己保存,通过公钥加密结果,必须私钥解密

由于非对称加密的密钥生成麻烦,所以无法做到一次一密,而且其加密速度很慢,无法对大量数据加密。因此最常用的使用场景就是数字签名密码传输,用作数字签名时使用私钥加密,公钥解密;用作加密解密时,使用公钥加密,私钥解密

长度要求:

RSA加密是有长度限制的,1024位密钥可以加密128字节(1024位),不满128字节的使用随机数填充,但是RSA实现中必须要加随机数(11字节以上),所以明文长度最大为117字节,然后剩下的加入随机数。这也产生了每次加密结果每一次都不一样的特点

下方是 Java 实现该RSA算法,最底部字符串我们可以自行选择 ,先是生成密钥对,然后加密,再解密。需要注意的是这个方法是不能跨语言使用的,因为里面对公钥和私钥用到的序列化是java的序列化。 由于加密后的密文都是字节码形式的,我们要以字符串方式保存或传输的话,可以使用Base64编码

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;

public class RSAUtil {


    /** 指定加密算法为RSA */
    private static String ALGORITHM = "RSA";
    /*指定加密模式和填充方式*/
    private static String ALGORITHM_MODEL = "RSA/ECB/PKCS1Padding";
    /** 指定key的大小,一般为1024,越大安全性越高 */
    private static int KEYSIZE = 1024;
    /** 指定公钥存放文件 */
    private static String PUBLIC_KEY_FILE = "PublicKey";
    /** 指定私钥存放文件 */
    private static String PRIVATE_KEY_FILE = "PrivateKey";
    /**
     * 生成密钥对
     */
    private static void generateKeyPair() throws Exception {
        /** RSA算法要求有一个可信任的随机数源 */
        SecureRandom sr = new SecureRandom();
        /** 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM);
        /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
        kpg.initialize(KEYSIZE, sr);
        /** 生成密匙对 */
        KeyPair kp = kpg.generateKeyPair();
        /** 得到公钥 */
        Key publicKey = kp.getPublic();
        /** 得到私钥 */
        Key privateKey = kp.getPrivate();
        /** 用对象流将生成的密钥写入文件 */
        ObjectOutputStream oos1 = new ObjectOutputStream(new FileOutputStream(
                PUBLIC_KEY_FILE));
        ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream(
                PRIVATE_KEY_FILE));
        oos1.writeObject(publicKey);
        oos2.writeObject(privateKey);
        /** 清空缓存,关闭文件输出流 */
        oos1.close();
        oos2.close();
    }
    /**
     * 加密方法 source: 源数据
     */
    public static byte[] encrypt(String source) throws Exception {
        /** 将文件中的公钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                PUBLIC_KEY_FILE));
        Key key = (Key) ois.readObject();
        ois.close();
        /** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODEL);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] b = source.getBytes();
        /** 执行加密操作 */
        byte[] b1 = cipher.doFinal(b);
        return b1;
    }
    /**
     * 解密算法 cryptograph:密文
     */
    public static String decrypt(byte[] cryptograph) throws Exception {
        /** 将文件中的私钥对象读出 */
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
                PRIVATE_KEY_FILE));
        Key key = (Key) ois.readObject();
        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODEL);
        cipher.init(Cipher.DECRYPT_MODE, key);
        /** 执行解密操作 */
        byte[] b = cipher.doFinal(cryptograph);
        return new String(b);
    }
    public static void main(String[] args) throws Exception {
        generateKeyPair();//生成密钥对
        String source = "邓鹏伟";// 要加密的字符串
        System.out.println("加密的字符串为"+source);
        byte[] cryptograph = encrypt(source);// 生成的密文
        //可以将密文进行base64编码进行传输
        System.out.println(new String(Base64.encode(cryptograph)));
        String target = decrypt(cryptograph);// 解密密文
        System.out.println(target);
    }
}

------------------------------------------------------

输出:

加密的字符串为123
axejk/TwfbNQAB9dNlbu3x5bJl7l7bQmEvk1hbi+iV/ZseZOMEZdVpB2kgXYvACI9N8VMjW6+m13q14bRdhkrmwiP6fjVv85af+dc/gk5Jph1MB6nYey/8ZhWZI6VowH4OBncZX33kzomvwxycQfUXLM/yDGxM6neYt8PaIbtaQ=
123

判断方式

在网站中通常使用 JSEncrypt 库来实现,其最大的特征就是有一个设置公钥的过程,我们可以通过以下方法来快速初步判断是否为 RSA 算法

  • 搜索关键词 new JSEncrypt()JSEncrypt 等,一般会使用 JSEncrypt 库,会有 new 一个实例对象的操作
  • 搜索关键词 setPublicKeysetKeysetPrivateKeygetPublicKey 等,一般实现的代码里都含有设置密钥的过程。

RAS的私匙 公匙 明文 密文 也有一一对应的关系

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值