DES和RSA加密解密实例

加密的应用

        加密是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。数据加密技术已经广泛应用于因特网电子商务、手机网络和银行自动取款机等领域。加密系统中有如下重要概念:
1:明文。被隐蔽的消息称作明文(plaintext)。
2:密文。隐蔽后的消息称作密文(ciphertext)。
3.加密。将明文变换成密文的过程称作加密(encryption)。
4:解密。由密文恢复出原明文的过程称作解密(decryption)。
5:敌方。主要指非授权者,通过各种办法,窃取机密信息。
6:被动攻击。获密文进行分析,这类攻击称作被动攻击(passive attack) 。
7:主动攻击。非法入侵者(tamper)采用篡改、伪造等手段向系统注入假消息,称为主动攻击(active attack)。
8:加密算法。对明文进行加密时采用的算法。
9:解密算法。对密文进行解密时采用算法。
10:加密密钥和解密密钥。加密算法和解密算法的操作通常是在一组密钥( key)的控制下进行的,分别称为加密密钥(encryption key)和解密密钥(decryption key)。
在加密系统中,加密算法和密钥是最重要的两个概念。在这里需要对加密算法和密钥进行一个解释。以最简单的“恺撒加密法”为例。
       《高卢战记》有描述恺撒曾经使用密码来传递信息,即所谓的“恺撒密码”。它是一种替代密码,通过将字母按顺序推后3位起到加密作用,如将字母A换作字母D,将字母B换作字母E。如“China”可以变为“Fklqd”;解密过程相反。
在这个简单的加密方法中,“向右移位”,可以理解为加密算法;“3”可以理解为加密密钥。对于解密过程,“向左移位”,可以理解为解密算法;“3”可以理解为解密密钥。显然,密钥是一种参数,它是在明文转换为密文或将密文转换为明文的算法中输入的数据。
        恺撒加密法的安全性来源于两个方面:第一,对加密算法的隐藏;第二,对密钥的隐蔽。单单隐蔽加密算法以保护信息,在学界和业界已有相当讨论,一般认为是不够安全的。公开的加密算法是给黑客长年累月攻击测试,对比隐蔽的加密算法要安全多。一般说来,加密之所以安全,是因为其加密的密钥的隐藏,并非加密解密算法的保密。而流行的一些加密解密算法一般是完全公开的。敌方如果取得已加密的数据,即使得知加密算法,若没有密钥,也不能进行解密。


常见的加密算法

      加密技术从本质上说是对信息进行编码和解码的技术。加密是将可读信息(明文)变为代码形式(密文);解密是加密的逆过程,相当于将密文变为明文。加密算法有很多种,一般可分为对称加密、非对称加密和单向加密三类算法。
对称加密算法应用较早,技术较为成熟。其过程如下:
安全编程技术
1:发送方将明文和加密密钥一起经过加密算法处理,变成密文,发送出去。
2:接收方收到密文后,使用加密密钥及相同算法的逆算法对密文解密,恢复为明文。
在对称加密算法中,双方使用的密钥相同,要求解密方事先必须知道加密密钥。其特点是算法公开、计算量小、加密速度快、加密效率高。不足之处是,通信双方都使用同样的密钥,安全性得不到保证。此外,用户每次使用该算法,需要保证密钥的唯一性,使得双方所拥有的密钥数量很大,密钥管理较为困难。对称加密算法中,目前流行的算法有:DES、3DES和IDEA等,美国国家标准局倡导的AES即将作为新标准取代DES。
       与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。每个人拥有这两个密钥,公开密钥对外公开,私有密钥不公开。如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。
非对称加密算法的基本过程是:
1:通信前,接收方随机生成的公钥,发送给发送方,自己保留私钥。
2:发送方利用接收方的公钥加密明文,使其变为密文。
3:接收方收到密文后,使用自己的私钥解密密文。
        广泛应用的非对称加密算法有RSA算法和美国国家标准局提出的DSA。非对称加密算法的保密性比较好,它消除了最终用户交换密钥的需要,但加密和解密花费时间长、速度慢,它不适合于对文件加密而只适用于对少量数据进行加密。
另一类是单向加密算法。该算法在加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,密文无法解密。只有重新输入明文,并经过同样的加密算法处理,得到相同的密文并被系统重新识别后,才能真正解密。该方法计算复杂,通常只在数据量有限的情形下使用,如广泛应用在计算机系统中的口令加密。近年来,单向加密的应用领域正在逐渐增大。应用较多单向加密算法的有RSA公司发明的MD5算法和美国国家安全局(NSA) 设计,美国国家标准与技术研究院(NIST) 发布SHA (Secure Hash Algorithm,安全散列算法)。
        大多数语言体系(如.net、Java)都具有相关的API支持各种加密算法。本章以Java语言为例来阐述加密解密过程,这些算法在其他语言中的实现,读者可以参考相关资料。


DES对称加密实例:

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
public class DES
{
//KeyGenerator提供对称密钥生成器的功能,支持各种算法
private KeyGenerator keygen;
//SecretKey负责保存对称密钥
private SecretKey deskey;
//Cipher负责完成加密或解密工作
private Cipher c;
//该字节数组负责保存加密的结果
private byte[] cipherByte;
public DESEncrypt()
{
Security.addProvider(new com.sun.crypto.provider.SunJCE());
try
{
//实例化支持DES算法的密钥生成器(算法名称命名需按规定,否则抛出异常)
keygen = KeyGenerator.getInstance("DES");
 
//生成密钥
deskey = keygen.generateKey();
//生成Cipher对象,指定其支持DES算法
c = Cipher.getInstance("DES");
}
catch(NoSuchAlgorithmException ex)
{
ex.printStackTrace();
}
catch(NoSuchPaddingException ex)
{
ex.printStackTrace();
}
}
/*对字符串str加密*/
public byte[] createEncryptor(String str)
{
try
{
//根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示加密模式
c.init(Cipher.ENCRYPT_MODE, deskey);
byte[] src = str.getBytes();
//加密,结果保存进cipherByte
cipherByte = c.doFinal(src);
}
catch(java.security.InvalidKeyException ex)
{
ex.printStackTrace();
}
catch(javax.crypto.BadPaddingException ex)
{
ex.printStackTrace();
}
catch(javax.crypto.IllegalBlockSizeException ex)
{
ex.printStackTrace();
}
return cipherByte;
}

/*对字节数组buff解密*/
public byte[] createDecryptor(byte[] buff)
{
try
{
//根据密钥,对Cipher对象进行初始化,ENCRYPT_MODE表示解密模式
c.init(Cipher.DECRYPT_MODE, deskey);
//得到明文,存入cipherByte字符数组
cipherByte = c.doFinal(buff);
}
catch(java.security.InvalidKeyException ex)
{
ex.printStackTrace();
}
catch(javax.crypto.BadPaddingException ex)
{
ex.printStackTrace();
}
catch(javax.crypto.IllegalBlockSizeException ex)
{
ex.printStackTrace();
}
return cipherByte;
}
public static void main(String[] args) throws Exception
{
DESEncrypt enc = new DESEncrypt();
String msg = "叶落枫亭的DES测试";
System.out.println("明文是:" + msg);
byte[] enc = p12_01.createEncryptor(msg);
System.out.println("密文是:" + new String(enc));
byte[] dec = p12_01.createDecryptor(enc);
System.out.println("解密后的结果是:" + new String(dec));
}
}

其中,可以用文件来保存对称密钥


RSA 非对称加密实例:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import javax.crypto.Cipher;

import sun.security.rsa.RSAPrivateKeyImpl;
import sun.security.rsa.RSAPublicKeyImpl;
import sun.security.util.DerValue;

public class RSAEncrypt
{

    private static String keyPath1 = "D:\\PRIVATE_KEY.txt"; // 私钥文件地址
    private static String keyPath2 = "D:\\PUBLIC_KEY.txt"; // 公钥文件地址

    private KeyPairGenerator keyPairGen;

    private KeyPair keyPair;

    private RSAPrivateKey privateKey;

    private RSAPublicKey publicKey;

    public void createKey()
    {
        try
        {
            keyPairGen = KeyPairGenerator.getInstance("RSA");
            keyPairGen.initialize(512);
            keyPair = keyPairGen.generateKeyPair();
            // Generate keys
            privateKey = (RSAPrivateKey)keyPair.getPrivate();
            publicKey = (RSAPublicKey)keyPair.getPublic();

            byte[] privateEncode = privateKey.getEncoded();
            try
            {
                // 生成私钥文件
                createFile(privateEncode, keyPath1, true);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }

            byte[] publicEncode = publicKey.getEncoded();
            try
            {
                // 生成公钥文件
                createFile(publicEncode, keyPath2, true);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }
    }

    public static String createFile(byte[] desEncode, String keyPath, boolean overWrite) throws IOException
    {
        // 指定文件是否存在
        boolean fileExisted = false;

        // 判断指定路径合法与否
        if ((keyPath.indexOf(":\\") > 0) || (keyPath.indexOf(":/") > 0))
        {
            //
        }
        else
        {
            System.out.println("密钥文件存放位置不合法," + keyPath);
            return "";
        }

        // 判断密钥文件是否存在及可写
        java.io.File keyFile = new File(keyPath);
        fileExisted = keyFile.exists();
        if (fileExisted && ((overWrite == false) || (keyFile.canWrite() == false)))
        {
            System.out.println("指定密钥文件" + keyFile + "已存在且不可写,请重新指定其他文件或修改覆盖选项为真。");
            return "";
        }

        // 若密钥文件不存在,创建新文件
        if (fileExisted == false)
        {
            if (keyFile.createNewFile() == false)
            {
                System.out.println("创建新文件" + keyFile + "失败。");
                return "";
            }
        }

        // 初始化IO对象,写入密钥
        java.io.ObjectOutputStream out = new java.io.ObjectOutputStream(new java.io.FileOutputStream(keyPath));
        try
        {
            out.writeObject(desEncode);
        }
        catch (IOException ex)
        {
            // 若使用用户指定位置存放失败,则使用服务器路径存放。
            return "";
        }
        finally
        {
            out.close();
        }
        return "";
    }

    /**
     * 得到私钥
     * 
     * @param keyPath
     *            私钥地址
     * @return
     */
    public RSAPrivateKey getPrivateKey(String keyPath)
    {
        try
        {
            java.io.ObjectInputStream in = new java.io.ObjectInputStream(new java.io.FileInputStream(keyPath));
            try
            {
                byte[] desEncodeRead = (byte[])in.readObject();
                in.close();
                DerValue d = new DerValue(desEncodeRead);

                PrivateKey p = RSAPrivateKeyImpl.parseKey(d);
                return (RSAPrivateKey)p;
            }
            catch (ClassNotFoundException ex1)
            {
                ex1.printStackTrace();
            }
            catch (IOException ex2)
            {
                ex2.printStackTrace();
            }

            return null;

        }
        catch (IOException ex)
        {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 得到公钥
     * 
     * @param keyPath
     *            公钥文件地址
     * @return
     */
    public RSAPublicKey getPublicKey(String keyPath)
    {
        try
        {
            java.io.ObjectInputStream in = new java.io.ObjectInputStream(new java.io.FileInputStream(keyPath));
            try
            {
                byte[] desEncodeRead = (byte[])in.readObject();
                in.close();
                DerValue d = new DerValue(desEncodeRead);

                PublicKey p = RSAPublicKeyImpl.parse(d);
                return (RSAPublicKey)p;
            }
            catch (ClassNotFoundException ex1)
            {
                ex1.printStackTrace();
            }
            catch (IOException ex2)
            {
                ex2.printStackTrace();
            }

            return null;

        }
        catch (IOException ex)
        {
            ex.printStackTrace();
            return null;
        }
    }

    public void encryptFile(RSAPublicKey publicKey, File file, File newFile)
    {
        try
        {
            InputStream is = new FileInputStream(file);
            OutputStream os = new FileOutputStream(newFile);

            byte[] bytes = new byte[53];
            while (is.read(bytes) > 0)
            {
                byte[] e = this.encrypt(publicKey, bytes);
                bytes = new byte[53];
                os.write(e, 0, e.length);
            }
            os.close();
            is.close();
            System.out.println("write success");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void decryptFile(RSAPrivateKey privateKey, File file, File newFile)
    {
        try
        {
            InputStream is = new FileInputStream(file);
            OutputStream os = new FileOutputStream(newFile);
            byte[] bytes1 = new byte[64];
            while (is.read(bytes1) > 0)
            {
                byte[] de = this.decrypt(privateKey, bytes1);
                bytes1 = new byte[64];
                os.write(de, 0, de.length);
            }
            os.close();
            is.close();
            System.out.println("write success");

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /** */
    /**
     * * Encrypt String. *
     * 
     * @return byte[]
     */
    protected byte[] encrypt(RSAPublicKey publicKey, byte[] obj)
    {
        if (publicKey != null)
        {
            try
            {
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.ENCRYPT_MODE, publicKey);
                return cipher.doFinal(obj);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return null;
    }

    /** */
    /**
     * * Basic decrypt method *
     * 
     * @return byte[]
     */
    protected byte[] decrypt(RSAPrivateKey privateKey, byte[] obj)
    {
        if (privateKey != null)
        {
            try
            {
                Cipher cipher = Cipher.getInstance("RSA");
                cipher.init(Cipher.DECRYPT_MODE, privateKey);
                return cipher.doFinal(obj);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return null;
    }

    public static void main(String[] args)
    {
        RSAEncrypt encrypt = new RSAEncrypt();
    
        // 需要加密的文件
        File file = new File("D:\\a.rar");
        // 加密到哪个文件
        File newFile = new File("D:\\b.rar");
    
        encrypt.createKey();
    
        RSAPublicKey publicKey = encrypt.getPublicKey(keyPath2);
    
        // 公钥加密操作
        encrypt.encryptFile(publicKey, file, newFile);
    
        RSAPrivateKey privateKey = encrypt.getPrivateKey(keyPath1);
    
        // 需要解密的文件
        File file1 = new File("D:\\b.rar");
        // 解密到哪个文件
        File newFile1 = new File("D:\\c.rar");
        // 私钥解密操作
        encrypt.decryptFile(privateKey, file1, newFile1);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值