加密算法

为了保护信息安全,在如今数据流动频繁的当今我们往往会对数据进行加密。在学习的过程中做了一些整理归纳。

加密概要

加密技术是对信息进行编码和解码的技术,编码是把原来可读信息(又称明文)译成代码形式(又称密文),其逆过程就是解码(解密),加密技术的要点是加密算法。加密算法主要分为摘要算法(不可逆算法)、对称算法以及非对称算法。

摘要算法

摘要算法是一个不可逆过程,就是无论多大数据,经过算法运算后都是生成固定长度的数据,一般结果使用16进制进行显示。 常用的摘要算法有MD5,SHA1。

MD5和SHA1的区别:MD5结果是128位摘要,SHa1是160位摘要。可以看出MD5的速度更快,而SHA1的强度更高。

下面统一使用MD5算法进行说明,SHA1类似。

主要用途有:验证消息完整性,安全访问认证,数据签名。

消息完整性:由于每一份数据生成的MD5值不一样,因此发送数据时可以将数据和其MD5值一起发送,然后就可以用MD5验证数据是否丢失、修改。

安全访问认证:这是使用了算法的不可逆性质,(就是无法从MD5值中恢复原数据)对账号登陆的密码进行MD5运算然后保存,这样可以保证除了用户之外,即使数据库管理人员都无法得知用户的密码。

数字签名:这是结合非对称加密算法和CA证书的一种使用场景

一般破解方法:字典法,就是将常用密码生成MD5值字典,然后反向查找达到破解目的,因此建议使用强密码。

http://www.cmd5.com/

此站点针对md5、sha1等全球通用公开的加密算法进行反向查询,通过穷举字符组合的方式,创建了明文密文对应查询数据库,创建的记录约90万亿条,占用硬盘约450TB,查询成功率95%以上。

 MD5

MD5 即 Message Digest Algorithm5 (信息摘要算法5),一种数字摘要的实现,摘要长度为128位,由MD4,MD3,MD2改进而来,主要增强了算法复杂度和不可逆性。

基于Java 的MD5算法使用:

public static String md5(String content) throws Exception{

    MessageDigest md = MessageDigest.getInstance("MD5");

    byte[] bytes =md.digest(content.getBytes("utf-8"));

    String md5Str = new BigInteger(1,bytes).toString(16);//16进制编码后

    return md5Str;

}

SHA

SHA 全称是Secure Hash Algorithm(安全散列算法),1995年又发布了一个修订版FIPS PUB 180-1 通常称之为SHA-1,是基于MD4算法。是现在公认的最安全的散列算法之一,被广泛使用。

比较MD5: SHA-1算法生成的摘要信息长度为160位,由于摘要信息更长,运算过程更加复杂,相同的硬件上,SHA-1比 MD5更慢,但是更为安全。

基于Java 的SHA算法使用:

public static String sha(String content) throws Exception{

    MessageDigest md = MessageDigest.getInstance("SHA-1");

    byte[] bytes =md.digest(content.getBytes("utf-8"));

    String shaStr = new BigInteger(1, bytes).toString(16);//16进制编码后

    return shaStr;

}

彩虹表破解Hash算法

彩虹表(Rainbow Table)法是一种破解哈希算法的技术,从原理上来说能够对任何一种Hash算法进行攻击。简单说,彩虹表就是一张采用各种Hash算法生成的明文和密文的对照表。本文不做赘述,详细内容可参考:

http://www.aiezu.com/system/windows/rainbow-table_knowledge.html

运行示例

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

    String content = "hello,world!";

    System.out.println("原文:"+content);

    System.out.println("MD5:"+md5(content));

    System.out.println("SHA:"+sha(content));

}

输出

原文:hello,world!

MD5:c0e84e870874dd37ed0d164c7986f03a

SHA:4518135c05e0706c0a34168996517bb3f28d94b5

对称加密算法

 对称加密算法:对加密和解密使用相同密钥的加密算法。由于其速度,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。

加密过程: 

将明文分成N个组,然后对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。

优点: 

算法公开、计算量小、加密速度快、加密效率高

缺点: 

交易双方都使用同样钥匙,安全性得不到保证

密钥管理困难,尤其是在分布式网络中

常用算法: 

DES、3DES(Triple DES)、AES、RC2、RC4、RC5和Blow fish

DES算法

DES算法属于对称加密算法,一共有三个参数入口(原文,密钥,加密模式)。明文按64位进行分组,密钥长64位,事实上只有56位参与DES运算(第8, 16, 24, 32, 40, 48, 56, 64位是校验位,使得每个密钥都有奇数个1),分组后的明文和56位的密钥按位替代或交换的方法形成密文。

3DES: 是DES向AES过渡的加密算法,使用3条56位的密钥对数据进行3次加密。

基于Java的DES 算法的使用

	/**
	 * 生成DES 密钥
	 */
	public static SecretKey loadKeyDES() throws Exception{
		KeyGenerator keyGen = KeyGenerator.getInstance("DES");
		keyGen.init(56);
		SecretKey key = keyGen.generateKey();
		String base64Key = byte2base64(key.getEncoded());
		byte[] bytes = base642byte(base64Key);
		key = new SecretKeySpec(bytes,"DES");
		return key;
	}
	//DES加密
	public static byte[] encryptDES(byte[] source,SecretKey key) throws Exception{
		Cipher cipher = Cipher.getInstance("DES");
		// 用密匙初始化Cipher对象
		cipher.init(Cipher.ENCRYPT_MODE, key);
		// 现在,获取数据并加密
		byte[] bytes = cipher.doFinal(source);
		return bytes;
	}
	//DES解密
	public static byte[] decryptDES(byte[] source,SecretKey key) throws Exception{
		Cipher cipher = Cipher.getInstance("DES");
		// 用密匙初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, key);
		// 真正开始解密操作
		byte[] bytes = cipher.doFinal(source);
		return bytes;
	}
	
	
	public static void main(String[] args) throws Exception {
		String context = "Hello,World!";
          // 密钥
		SecretKey key = loadKeyDES();
		
		byte[] encryptBytes = encryptDES(context.getBytes(),key);
		System.out.println("加密后:"+new String(encryptBytes));
		
		byte[] decryptBytes = decryptDES(encryptBytes,key);
		System.out.println("解密后:"+new String(decryptBytes));
	}

运行结果如下:

加密后:���9�iP�ﱹp
解密后:Hello,World!

 AES算法

AES算法 全称是Advanced Encryption Standard,即高级加密标准,又称为Rijndael加密算法,是美国联邦政府采用的一种对称加密标准,这个标准用来替代原先的DES算法,目前已成为对称加密算法中最流行的算法之一。

对比DES算法,AES算法作为新一代的数据加密标准,汇聚了强安全性、高性能、高效率、易用和灵活等优点,设计有三个密钥长度(128,192,256位),比DES算法加密强度更高,更加安全。

基于Java的AES算法:

     /**
	 * 生成AES 密钥
	 */
	public static SecretKey loadKeyAES() throws Exception{
		KeyGenerator keyGen = KeyGenerator.getInstance("AES");
		keyGen.init(128);//DES为56
		SecretKey key = keyGen.generateKey();
		String base64Key = byte2base64(key.getEncoded());
		byte[] bytes = base642byte(base64Key);
		key = new SecretKeySpec(bytes,"AES");
		return key;
	}
	//AES加密
	public static byte[] encryptAES(byte[] source,SecretKey key) throws Exception{
		Cipher cipher = Cipher.getInstance("AES");
		// 用密匙初始化Cipher对象
		cipher.init(Cipher.ENCRYPT_MODE, key);
		// 现在,获取数据并加密
		byte[] bytes = cipher.doFinal(source);
		return bytes;
	}
	//AES解密
	public static byte[] decryptAES(byte[] source,SecretKey key) throws Exception{
		Cipher cipher = Cipher.getInstance("AES");
		// 用密匙初始化Cipher对象
		cipher.init(Cipher.DECRYPT_MODE, key);
		// 真正开始解密操作
		byte[] bytes = cipher.doFinal(source);
		return bytes;
	}
	
	
	public static void main(String[] args) throws Exception {
		String context = "Hello,World!";
		SecretKey key = loadKeyAES();
		
		byte[] encryptBytes = encryptAES(context.getBytes(),key);
		System.out.println("加密后:"+new String(encryptBytes));
		
		byte[] decryptBytes = decryptAES(encryptBytes,key);
		System.out.println("解密后:"+new String(decryptBytes));
	}

运行结果如下:

加密后:T�l�X���2�zEO�
解密后:Hello,World!

 

非对称加密算法

非对称加密算法:又称为公开密钥加密算法,需要两个密钥,一个为公开密钥(PublicKey)即公钥,一个为私有密钥(PrivateKey)即私钥。两者需要配对使用。用其中一者加密,则必须用另一者解密。

使用过程: 

乙方生成两把密钥(公钥和私钥)

甲方获取乙方的公钥,然后用它对信息加密。

乙方得到加密后的信息,用私钥解密,乙方也可用私钥加密字符串

甲方获取乙方私钥加密数据,用公钥解密

优点: 

更安全,密钥越长,它就越难破解

缺点: 

加密速度慢

常用算法: 

RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)

RSA 算法

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

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

如果明文长度超过限制怎么办?

1.可以与对称加密混合使用,一次一密产生对称加密的密钥,然后使用此密钥进行数据对称加密,再使用RSA私钥对对称密钥加密,一起保存。解密时使用公钥解密出密钥,然后进行数据解密。

2.可以分段加密。将明文按117字节分成多段,加密后再拼接起来。由于每一段密文长度都是128字节,所以解密时按照128字节分段解密。

java的RSA密钥生成与使用

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

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 = "Hello World!";// 要加密的字符串
        byte[] cryptograph = encrypt(source);// 生成的密文

        //可以将密文进行base64编码进行传输
        System.out.println(new String(Base64.encode(cryptograph)));

        String target = decrypt(cryptograph);// 解密密文
        System.out.println(target);
    }
}

RSA密钥使用Base64编码

要灵活使用肯定不能使用java的序列化保存了,我们对上面的generateKeyPair()方法进行改写。通过密钥生成器生成公钥,私钥后,调用publicKey.getEncoded()和privateKey.getEncoded(),此时它生成的比特编码是有独特格式的(公钥是X.509,私钥是PKCS#8)可以使用publicKey.getFormat(),privateKey.getFormat();进行查看。之后对字节码进行Base64编码就行了。

密钥生成方法:

//以base64编码密钥
    public Map<String ,String> generateKeyPair1() throws Exception{
        SecureRandom sr = new SecureRandom();
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024, sr);
        KeyPair kp = kpg.generateKeyPair();
        Key publicKey = kp.getPublic();
        Key privateKey = kp.getPrivate();
        byte[] pb = publicKey.getEncoded();
        String pbStr =  new String(Base64.encode(pb));
        byte[] pr = privateKey.getEncoded();
        String prStr =  new String(Base64.encode(pr));
        Map<String, String> map = new HashMap<String, String>();
        map.put("publicKey",pbStr);
        map.put("privateKey", prStr);
        return map;
    }

 恢复密钥方法,使用各自不同的编码形式恢复:

    //从base64编码的公钥恢复公钥
    public PublicKey getPulbickey(String key_base64) throws Exception{
        byte[] pb = Base64.decode(key_base64).getBytes();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pb);
        KeyFactory  keyfactory = KeyFactory.getInstance("RSA");
        return keyfactory.generatePublic(keySpec);
    }

    //从base64编码的私钥恢复私钥
    public PrivateKey getPrivatekey(String key_base64) throws Exception{
        byte[] pb = Base64.decode(key_base64).getBytes();
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pb);
        KeyFactory  keyfactory = KeyFactory.getInstance("RSA");
        return keyfactory.generatePrivate(keySpec);
    }

加密解密方法都类似下面,PrivateKey和PublicKey是Key的子接口。

    //执行加密操作
    public static byte[] encrypt(Key key,byte[] source) throws Exception{
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] ciphertext = cipher.doFinal(source);
        return ciphertext;
    }

    //执行加密操作 
    public static byte[] decrypt(Key key,byte[] ciphertext) throws Exception{
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] source = cipher.doFinal(ciphertext);
        return source;
    }

记录RSA的密钥特征值并进行密码恢复

所谓特征值就是RSA中公钥(N,e)私钥(N,d)的三个值:N,e,d。只要有这三个值我们就可以恢复密钥了。这是实际开发中常用的方法。首先是提取特征值,我们需要将PublicKey强制转换为RSAPublicKey.然后获取,看代码。

        //提取特征值保存,以base64编码密钥
        public static Map<String ,String> generateKeyPair2() throws Exception{
            SecureRandom sr = new SecureRandom();
            KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
            kpg.initialize(1024, sr);
            KeyPair kp = kpg.generateKeyPair();
            Key publicKey = kp.getPublic();
            Key privateKey = kp.getPrivate();
            RSAPublicKey rpk = (RSAPublicKey)publicKey;
            RSAPrivateKey rpr= (RSAPrivateKey)privateKey;
            //三个特征值都是BigInteger类型。
            BigInteger N = rpk.getModulus();//N值
            BigInteger e = rpk.getPublicExponent();//e值
            BigInteger d  = rpr.getPrivateExponent();//d值
            Map<String, String> map = new HashMap<String, String>();
            //将BigInteger转为byte[],然后以base64保存
            map.put("N",new String(Base64.decode(N.toByteArray())));
            map.put("e", new String(Base64.decode(e.toByteArray())));
            map.put("d", new String(Base64.decode(d.toByteArray())));
            return map;
        }

 利用三个特征值就可以非常容易恢复密钥了。

    //从base64编码的特征值(N,e)恢复公钥
    public static PublicKey getPulbickey(String N_Str,String e_Str) throws Exception{
        BigInteger N = new BigInteger(1, Base64.decode(N_Str.getBytes()));
        BigInteger e = new BigInteger(1, Base64.decode(e_Str.getBytes()));
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPublicKeySpec ps = new RSAPublicKeySpec(N, e);
        PublicKey pkey = kf.generatePublic(ps);
        return pkey;
    }
    
    //从base64编码的特征值(N,d)恢复私钥
    public static PrivateKey getPrivatekey(String N_Str,String d_Str) throws Exception{
        BigInteger N = new BigInteger(1, Base64.decode(N_Str.getBytes()));
        BigInteger d = new BigInteger(1, Base64.decode(d_Str.getBytes()));
        KeyFactory kf = KeyFactory.getInstance("RSA");
        RSAPrivateKeySpec ps = new RSAPrivateKeySpec(N, d);
        PrivateKey pkey = kf.generatePrivate(ps);
        return pkey;
    }

RSA 算法 与 数字签名

RSA 是目前最有影响力的非对称加密算法,能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA 算法是基于一个十分简单的数论事实:将两个大素数想乘十分容易,但反过来想要对其乘积进行因式分解却极其困难。

常见的数字签名有两种:

1、MD5 + RSA :采用MD5 算法生成需要发送正文的数字摘要,并且使用RSA算法来对摘要进行加密和解密。

2、SHA1 + RSA:采用SHA-1算法生成正文的数字摘要,并且使用RSA算法来对摘要进行加密和解密。

两者算法的流程完全一致,只是签名算法换成了对应的算法。这里只对MD5withRSA做出代码示例。

基于Java的RSA算法使用

        private static final String RSA = "RSA";
	private static final String MD5 = "MD5";
	private static final String SHA1 = "SHA1";
	private static final String MD5withRSA = "MD5withRSA";
	private static final String SHA1withRSA = "SHA1withRSA";
	
	public static String byte2base64(byte[] bytes){
		Base64 base = new Base64();
		return base.encodeAsString(bytes);
	}
	public static byte[] base642byte(String base64){
		Base64 base = new Base64();
		return base.decode(base64);
	}
	//初始化KeyPairGenerator ,生成KeyPair
	public static KeyPair getKeyPair() throws Exception{
		KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA);
		keyPairGenerator.initialize(512);
		KeyPair keypair = keyPairGenerator.generateKeyPair();
		return keypair;
	}
	//获取公钥
	public static String getPublicKey(KeyPair keyPair){
		PublicKey publicKey = keyPair.getPublic();
		byte[] bytes = publicKey.getEncoded();
		return byte2base64(bytes);
	}
	//获取私钥
	public static String getPrivateKey(KeyPair keyPair){
		PrivateKey privateKey = keyPair.getPrivate();
		byte[] bytes = privateKey.getEncoded();
		return byte2base64(bytes);
	}
 
	//MD5withRSA   签名,可将MD5 替换成 SHA1 数字签名
	public static byte[] sign4MD5(byte[] content,PrivateKey privateKey) throws Exception{
		MessageDigest md = MessageDigest.getInstance(MD5);
		byte[] bytes = md.digest(content);
		Cipher cipher = Cipher.getInstance(RSA);
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		byte[] encryptBytes = cipher.doFinal(bytes);
		return encryptBytes;
	}
	//MD5withRSA  验证签名,可将MD5 替换成 SHA1 数字签名
	public static boolean verify4MD5(byte[] content,byte[] sign, PublicKey publicKey) throws Exception{
		MessageDigest md = MessageDigest.getInstance(MD5);
		byte[] bytes = md.digest(content);
		Cipher cipher = Cipher.getInstance(RSA);
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		byte[] decrypeBytes = cipher.doFinal(sign);
		return byte2base64(decrypeBytes).equals(byte2base64(bytes));
	}
	//基于JAVA的Signature API的使用 将MD5withRSA 替换成 SHA1withRSA 数字签名
	public static byte[] sign4Signature(byte[] content,PrivateKey privateKey) throws Exception{
		Signature signature = Signature.getInstance(MD5withRSA);
		signature.initSign(privateKey);;
		signature.update(content);
		return signature.sign();
	}
	public static boolean verify4Signature(byte[] content,byte[] sign, PublicKey publicKey) throws Exception{
		Signature signature = Signature.getInstance(MD5withRSA);
		signature.initVerify(publicKey);
		signature.update(content);
		return signature.verify(sign);
	}
	
	public static void main(String[] args) throws Exception {
		KeyPair keyPair = getKeyPair();
		System.out.println("privateKey:"+getPrivateKey(keyPair));
		System.out.println("publicKey:"+getPublicKey(keyPair));
		
		String content = "hello,World";
		byte[] signMd5 = sign4MD5(content.getBytes(), keyPair.getPrivate());
		System.out.println("signMd5:"+new String(signMd5));
		System.out.println("verifyMd5:"+verify4MD5(content.getBytes(), signMd5, keyPair.getPublic()));
		byte[] signSignature = sign4Signature(content.getBytes(), keyPair.getPrivate());
		System.out.println("sign4Signature:"+new String(signSignature));
		System.out.println("verify4Signature:"+verify4Signature(content.getBytes(), signSignature, keyPair.getPublic()));
	}

运行结果如下: 

privateKey:MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAiD/p5rsULwF3CNQNnh0Y3rUd5v7JSTWwt6RpIP6uoucwa1nI9pMU7IUF+PPgrMY3l6KJmfUdLSLx23/1286QYQIDAQABAkAk91pJvJY0TqxyG756GKDnw7ISOyx3jXadzKCtUAwnrDYXK3kyPpYW4Hnovw0bDF2GhFDs1l3DHk4dAfeFDXJxAiEA0FAesbxDSKaRePdlOTloMN6dm9cw3VJRK765TRVP8IUCIQCncKDGNA1OVSWZZicCaXSBuKlej+krjCavtJ/HWur1LQIhALPtsEV2xmsXLKnejnkaA8vKTTpRaeyQ8HmneGiDUxP9AiBTMzbgZfr6onqlZ8oYe7glwVF/qHjPZ7vNcS43zCiWHQIhAK0u7LLh2lzQNZ7eFGyHpsBQae5gfJMxzVY0/AyLvmtb
publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIg/6ea7FC8BdwjUDZ4dGN61Heb+yUk1sLekaSD+rqLnMGtZyPaTFOyFBfjz4KzGN5eiiZn1HS0i8dt/9dvOkGECAwEAAQ==
signMd5:f��ߜ��L>^�\���o��@���:E�±�X��z���p�d��+����{�?�hg�|Jk
verifyMd5:true
sign4Signature:��oa̠��eH>:4����W]����?@���?zh���j�4�˰�L��i �h,
verify4Signature:true

 

参考文章

https://blog.csdn.net/qwe6112071/article/details/53576584

RSA非对称加密算法详解

https://blog.csdn.net/starryheavens/article/details/8536238

RSA算法详解(详细的说明了算法的数学基础)

https://blog.csdn.net/chengbinbbs/article/details/78640589

java对称加密与非对称加密(内含Java实现代码)

https://blog.csdn.net/hdhai9451/article/details/11481721

MD5、SHA256、SHA512加密算法,以及可逆算法

https://blog.csdn.net/mengfanzhundsc/article/details/62046559

常用的安全算法-数字摘要、对称加密、非对称加密详解

https://blog.csdn.net/u013565368/article/details/53081195

常用加密解密算法【RSA、AES、DES、MD5】介绍和使用

http://www.cnblogs.com/hjgods/p/3998570.html

MD5加密算法原理及实现(C++代码实现)

https://blog.csdn.net/tanyunlong_nice/article/details/52864019

加密方式之MD5

https://blog.csdn.net/w13505963128/article/details/79243484

MD5加密理解以及前台后台例子各一个

https://blog.csdn.net/smilefyx/article/details/49507179

html中使用js进行登录md5加密提交并重定向新页面

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值