常用Java密码技术

著名的密码学者Ron Rivest曾经说过:“密码学是关于如何在敌人存在的环境中通讯”。

的确,从严谨的角度来讲,不管是公网环境还是在企业内网,我们设计系统的时候都需要充分考虑通讯安全。以下总结了一些常用的java密码技术,供参考。

1,单向散列函数

又称单向Hash函数、杂凑函数,就是把任意长的输入消息串变化成固定长的输出串且由输出串难以得到输入串的一种函数。这个输出串称为该消息的散列值。一般用于产生消息摘要,密钥加密等.

1)MD5
是RSA数据安全公司开发的一种单向散列算法,MD5被广泛使用。MD5的强抗碰撞性目前已被破解。
代码示例:

package com.huangzi.demo;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5 { 
    public static byte[] eccrypt(String info) throws NoSuchAlgorithmException{  
        //获取MD5的MessageDigest对象  
        MessageDigest md5 = MessageDigest.getInstance("MD5");  
        byte[] srcBytes = info.getBytes();  
        md5.update(srcBytes);  
        byte[] resultBytes = md5.digest();  
        return resultBytes;  
    }  
      
      
    public static void main(String args[]) throws NoSuchAlgorithmException{  
        String msg = "皇子——常用java密码技术";  
        byte[] resultBytes = MD5.eccrypt(msg);  
        System.out.println("密文:" + new String(resultBytes));  
        System.out.println("明文:" + msg);  
    }  
}

2)SHA

分为SHA-1,SHA-224,SHA-256,SHA-384。目前SHA-1的强抗碰撞性已被破解。

package com.huangzi.demo;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA {
          
        public static byte[] eccrypt(String shaType,String info) throws NoSuchAlgorithmException{  
            MessageDigest md5 = MessageDigest.getInstance(shaType);  
            byte[] srcBytes = info.getBytes();  
            md5.update(srcBytes);  
            byte[] resultBytes = md5.digest();  
            return resultBytes;  
        }  
        
        /** 
         * @param args 
         * @throws NoSuchAlgorithmException  
         */  
        public static void main(String[] args) throws NoSuchAlgorithmException {  
            String msg = "皇子讲java密码技术";  
            String[] shaTypes = new String[] { "SHA1", "SHA-256", "SHA-384", "SHA-512" }; 
            for(String shaType : shaTypes) {
                System.out.println(shaType);
                byte[] resultBytes = SHA.eccrypt(shaType,msg);  
                System.out.println("明文:" + msg);  
                System.out.println("密文:" + new String(resultBytes));
                System.out.println("========================");
            }
        }
              
}

2,对称加密

一种加密与解密用的是相同的密钥的加密方式。



1)DES
DES,全称为“Data Encryption Standard”,中文名为“数据加密标准”,是一种使用密钥加密的块算法。1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。



import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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

public class DES {
      
    
    private KeyGenerator keygen;  
    private SecretKey deskey;  
    private Cipher cipher;  
    private byte[] cipherByte;  
      
    public DES() throws NoSuchAlgorithmException, NoSuchPaddingException{  
        keygen = KeyGenerator.getInstance("DES");  
        deskey = keygen.generateKey();  
        cipher = Cipher.getInstance("DES");  
    }  
      
    public byte[] Encrytor(String str) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        cipher.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] src = str.getBytes();  
        cipherByte = cipher.doFinal(src);  
        return cipherByte;  
    }  
  
    public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        cipher.init(Cipher.DECRYPT_MODE, deskey);  
        cipherByte = cipher.doFinal(buff);  
        return cipherByte;  
    }  
  
    public static void main(String[] args) throws Exception {  
        DES de1 = new DES();  
        String msg ="皇子讲java密码技术";  
        byte[] encontent = de1.Encrytor(msg);  
        byte[] decontent = de1.Decryptor(encontent);  
        System.out.println("明文:" + msg);  
        System.out.println("密文:" + new String(encontent));  
        System.out.println("解密:" + new String(decontent));  
    } 
}

2)3DES

又称Triple DES,是DES加密算法的一种模式,它使用3条56位的密钥对3DES数据进行三次加密。


package com.huangzi.demo;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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

public class DESDESDES {
     
      
    private KeyGenerator keygen;  
    private SecretKey deskey;  
    private Cipher c;  
    private byte[] cipherByte;  
  
    public DESDESDES() throws NoSuchAlgorithmException, NoSuchPaddingException {  
        keygen = KeyGenerator.getInstance("DESede");  
        deskey = keygen.generateKey();  
        c = Cipher.getInstance("DESede");  
    }  
  
    /** 
     * 加密 
     *  
     * @param str 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Encrytor(String str) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        c.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] src = str.getBytes();  
        cipherByte = c.doFinal(src);  
        return cipherByte;  
    }  
  
    /** 
     * 解密 
     *  
     * @param buff 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        c.init(Cipher.DECRYPT_MODE, deskey);  
        cipherByte = c.doFinal(buff);  
        return cipherByte;  
    }  
  
    /** 
     * @param args 
     * @throws NoSuchPaddingException  
     * @throws NoSuchAlgorithmException  
     * @throws BadPaddingException  
     * @throws IllegalBlockSizeException  
     * @throws InvalidKeyException  
     */  
    public static void main(String[] args) throws Exception {  
        DESDESDES des = new DESDESDES();  
        String msg ="皇子讲java密码技术";  
        byte[] encontent = des.Encrytor(msg);  
        byte[] decontent = des.Decryptor(encontent);  
        System.out.println("明文:" + msg);  
        System.out.println("密文:" + new String(encontent));  
        System.out.println("解密:" + new String(decontent));  
    } 
}

3)AES
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。由美国国家标准与技术研究院(NIST)发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。是对称密钥加密中最流行的算法之一。


package com.huangzi.demo;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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

public class AES {
    private KeyGenerator keygen;  
    private SecretKey deskey;  
    private Cipher cipher;  
    private byte[] cipherByte;  
      
    public AES() throws NoSuchAlgorithmException, NoSuchPaddingException{  
        keygen = KeyGenerator.getInstance("AES");  
        deskey = keygen.generateKey();  
        cipher = Cipher.getInstance("AES");  
    }  
      
    /** 
     * 加密 
     * @param str 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Encrytor(String str) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        cipher.init(Cipher.ENCRYPT_MODE, deskey);  
        byte[] src = str.getBytes();  
        cipherByte = cipher.doFinal(src);  
        return cipherByte;  
    }  
  
    /** 
     * 解密 
     * @param buff 
     * @return 
     * @throws InvalidKeyException 
     * @throws IllegalBlockSizeException 
     * @throws BadPaddingException 
     */  
    public byte[] Decryptor(byte[] buff) throws InvalidKeyException,  
            IllegalBlockSizeException, BadPaddingException {  
        cipher.init(Cipher.DECRYPT_MODE, deskey);  
        cipherByte = cipher.doFinal(buff);  
        return cipherByte;  
    }  
  
    /** 
     * @param args 
     * @throws NoSuchPaddingException  
     * @throws NoSuchAlgorithmException  
     * @throws BadPaddingException  
     * @throws IllegalBlockSizeException  
     * @throws InvalidKeyException  
     */  
    public static void main(String[] args) throws Exception {  
        AES aes = new AES();  
        String msg ="皇子讲java密码技术";  
        byte[] encontent = aes.Encrytor(msg);  
        byte[] decontent = aes.Decryptor(encontent);  
        System.out.println("明文:" + msg);  
        System.out.println("密文:" + new String(encontent));  
        System.out.println("解密:" + new String(decontent));  
    }  
}

4)PBE
PBE算法(Password Based Encryption,基于口令加密)是一种基于口令的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。
PBE算法在加密过程中并不是直接使用口令来加密,而是加密的密钥由口令生成,这个功能由PBE算法中的KDF函数完成。KDF函数的实现过程为:将用户输入的口令首先通过“盐”(salt)的扰乱产生准密钥,再将准密钥经过散列函数多次迭代后生成最终加密密钥,密钥生成后,PBE算法再选用对称加密算法对数据进行加密,可以选择DES、3DES、RC5等对称加密算法。

package com.huangzi.demo;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

public class PEB {

    private static Cipher cipher;
    private static SecretKey generateKey;
    private static PBEParameterSpec pbeParameterSpec;

    public static byte[] encode(String src) throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException{
        SecureRandom secureRandom = new SecureRandom();
        byte[] salt = secureRandom.generateSeed(8);

        String password = "abc123";
        PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
        SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
        generateKey = secretKeyFactory.generateSecret(pbeKeySpec);

        pbeParameterSpec = new PBEParameterSpec(salt, 100);
        cipher = Cipher.getInstance("PBEWITHMD5andDES");
        cipher.init(Cipher.ENCRYPT_MODE, generateKey, pbeParameterSpec);
        return cipher.doFinal(src.getBytes());
    }

    public static byte[] decode(byte[] src) throws InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException{
            cipher.init(Cipher.DECRYPT_MODE, generateKey, pbeParameterSpec);
            return cipher.doFinal(src);
    }
    public static void main(String[] args) throws Exception{
        String msg ="皇子讲java密码技术";  
        byte[] encontent = PEB.encode(msg);
        byte[] decontent = PEB.decode(encontent);
        System.out.println("明文:" + msg);  
        System.out.println("密文:" + new String(encontent));  
        System.out.println("解密:" + new String(decontent));   
    }
}

3,公钥密码
公钥密码又称为非对称密码,拥有公钥密码的用户分别拥有加密密钥和解密密钥。通过加密密钥不能得到解密密钥。并且加密密钥是公开的。
解密密钥一开始就由接收者自己保管,可以解决密钥配送的问题

1)RSA
1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。1987年7月首次在美国公布,当时他们三人都在麻省理工学院工作实习。RSA就是他们三人姓氏开头字母拼在一起组成的。
RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。



今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。
但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战和质疑。

package com.huangzi.demo;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import javax.crypto.Cipher;

public class RSA {

    public static byte[] encrypt(RSAPublicKey publicKey,byte[] srcBytes) throws Exception{  
        if(publicKey!=null){  
            Cipher cipher = Cipher.getInstance("RSA");  
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
            byte[] resultBytes = cipher.doFinal(srcBytes);  
            return resultBytes;  
        }  
        return null;  
    }  

    public static byte[] decrypt(RSAPrivateKey privateKey,byte[] srcBytes) throws Exception{  
        if(privateKey!=null){  
            Cipher cipher = Cipher.getInstance("RSA");  
            cipher.init(Cipher.DECRYPT_MODE, privateKey);  
            byte[] resultBytes = cipher.doFinal(srcBytes);  
            return resultBytes;  
        }  
        return null;  
    }  

    public static void main(String[] args) throws Exception {  
        String msg = "皇子讲java密码技术";  
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");  
        keyPairGen.initialize(1024);  
        KeyPair keyPair = keyPairGen.generateKeyPair();  
        RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();               
        RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();  

        byte[] srcBytes = msg.getBytes();  
        byte[] resultBytes = RSA.encrypt(publicKey, srcBytes);  
        byte[] decBytes = RSA.decrypt(privateKey, resultBytes);  

        System.out.println("明文:" + msg);  
        System.out.println("密文:" + new String(resultBytes));  
        System.out.println("解密:" + new String(decBytes));  
    }  
}

4,数字签名
数字签名(又称公钥数字签名、电子签章)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。
数字签名会使用公钥和私钥组成的密钥对
私钥加密相当于生成签名;用公钥解密相当于验证签名


package com.huangzi.demo;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;

public class RSASign {
    
    public static byte[] sign(PrivateKey rsaPrivateKey,String msg) throws Exception{

        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        Signature signature = Signature.getInstance("MD5withRSA");
        signature.initSign(privateKey);
        signature.update(msg.getBytes());
        return signature.sign();
    }
    public static boolean verify(PublicKey rsaPublicKey,String msg,byte[] signatureByte) throws Exception {
        Signature signature = Signature.getInstance("MD5withRSA");
        signature = Signature.getInstance("MD5withRSA");
        signature.initVerify(rsaPublicKey);
        signature.update(msg.getBytes());
        return signature.verify(signatureByte);
    }
    
    public static void main(String[] args) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        PublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
        PrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
        String msg = "皇子讲java密码技术";
        byte[] signature = RSASign.sign(rsaPrivateKey, msg);
        System.out.println("消息明文:" + msg);
        System.out.println("签名:" + new String(signature));
        boolean flag = RSASign.verify(rsaPublicKey, msg, signature);
        System.out.println("验签结果:" + flag);
    }
}
                        作者:VIP.FCS 皇子
                        日期:2018.1.14

来赞赏一瓶可乐?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342