Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6923032
  • 博文数量: 700
  • 博客积分: 10821
  • 博客等级: 上将
  • 技术积分: 12011
  • 用 户 组: 普通用户
  • 注册时间: 2005-12-02 10:41
个人简介

大数据、ML、AI、云计算openstack、Linux、SpringCloud。

文章分类

全部博文(700)

分类: Java

2014-01-03 23:25:18

基本原理:
    数字签名使用密钥对(公开密钥和私有密钥),任何持有公开密钥的人都能解密、而只有加密密钥持有者(私有密钥)能够生成消息。
使用举例:
    1. A生成一个非对称加密密钥,她用该密钥对明文进行加密。
    2. A将公开密钥以某种方式传递给B。
    3. A用私有密钥生成消息,发给B。
    4. B用公开密钥解密。B能够确认2点:1)原消息没有被篡改。2)是由A加密的,即发出人是A。
说明:
   Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥,通常应对私钥加密后再保存、如何从文件中得到公钥编码的字节数组、如何从字节数组解码公钥。
   最普通的公共密钥算法是Rivest, Shamir, 和 Adleman发明的RSA算法。直到2000年10月,该算法一直受RSA Security公司授予的专利保护。该专利的转让许可证价格昂贵,通常要支付3%的专利权使用费,每年至少付款50 000美元。现在该加密算法已经公开,Java SE 5.0及以后的版本都支持RSA算法。
注意:如果你使用的是旧版本的JDK,可以使用Legion of Bouncy Castle(网址 bouncycastle.org),它提供了一个支持RSA的密码提供商和其他许多SunJCE提供商没有提供的特性。该提供商已经由Sun公司签名,因此可以将它与JDK结合起来使用。
http://hiyachen.blog.chinaunix.net  chf@tsinghua.org.cn 
如果要使用RSA算法,需要一对公共/私有密钥。你可以按如下方法使用KeyPairGenerator来获得:
KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
SecureRandom random = new SecureRandom();
pairgen.initialize(KEYSIZE, random);
KeyPair keyPair = pairgen.generateKeyPair();
Key publicKey = keyPair.getPublic();
Key privateKey = keyPair.getPrivate();
列表9-18中的程序有三个选项。-genkey选项用于产生一个密钥对,-encrypt选项用于生成AES密钥,并且用公共密钥对其进行包装。
Key key = . . .; // an AES key
Key publicKey = . . .; // a public RSA key
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.WRAP_MODE, publicKey);
byte[] wrappedKey = cipher.wrap(key);
然后它便生成一个包含下列内容的文件:
包装过的密钥的长度
包装过的密钥字节
用AES密钥加密的明文
-decrypt选项用于对这样的文件进行解密。请试运行该程序,首先生成RSA密钥:
java RSATest -genkey public.key private.key
然后对一个文件进行加密:
java RSATest -encrypt plaintextFile encryptedFile public.key
最后,对文件进行解密,并且检验解密后的文件是否与明文相匹配。
java RSATest -decrypt encryptedFile decryptedFile private.key

RSATest.java
1. import java.io.*;
2. import java.security.*;
3. import javax.crypto.*;
4.
5. 
13. public class RSATest
14. {
15.    public static void main(String[] args)
16.    {
17.       try
18.       {
19.          if (args[0].equals("-genkey"))
20.          {
21.              KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
22.              SecureRandom random = new SecureRandom();
23.              pairgen.initialize(KEYSIZE, random);
24.              KeyPair keyPair = pairgen.generateKeyPair();
25.              ObjectOutputStream out = new ObjectOutputStream (new FileOutputStream(args[1]));
26.              out.writeObject(keyPair.getPublic());
27.              out.close();
28.              out = new ObjectOutputStream(new FileOutputStream(args[2]));
29.              out.writeObject(keyPair.getPrivate());
30.              out.close();
31.          }
32.          else if (args[0].equals("-encrypt"))
33.          {
34.             KeyGenerator keygen = KeyGenerator.getInstance("AES");
35.             SecureRandom random = new SecureRandom();
36.             keygen.init(random);
37.             SecretKey key = keygen.generateKey();
38.
39.             // wrap with RSA public key
40.             ObjectInputStream keyIn = new ObjectInputStream
(new FileInputStream(args[3]));
41.             Key publicKey = (Key) keyIn.readObject();
42.             keyIn.close();
43.
44.             Cipher cipher = Cipher.getInstance("RSA");
45.             cipher.init(Cipher.WRAP_MODE, publicKey);
46.             byte[] wrappedKey = cipher.wrap(key);
47.             DataOutputStream out = new DataOutputStream
(new FileOutputStream(args[2]));
48.             out.writeInt(wrappedKey.length);
49.             out.write(wrappedKey);
50.
51.             InputStream in = new FileInputStream(args[1]);
52.             cipher = Cipher.getInstance("AES");
53.             cipher.init(Cipher.ENCRYPT_MODE, key);
54.             crypt(in, out, cipher);
55.             in.close();
56.             out.close();
57.          }
58.          else
59.          {
60.             DataInputStream in = new DataInputStream
(new FileInputStream(args[1]));
61.             int length = in.readInt();
62.             byte[] wrappedKey = new byte[length];
63.             in.read(wrappedKey, 0, length);
64.
65.             // unwrap with RSA private key
66.             ObjectInputStream keyIn = new ObjectInputStream
(new FileInputStream(args[3]));
67.             Key privateKey = (Key) keyIn.readObject();
68.             keyIn.close();
69.
70.             Cipher cipher = Cipher.getInstance("RSA");
71.             cipher.init(Cipher.UNWRAP_MODE, privateKey);
72.             Key key = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
73.
74.             OutputStream out = new FileOutputStream(args[2]);
75.             cipher = Cipher.getInstance("AES");
76.             cipher.init(Cipher.DECRYPT_MODE, key);
77.
78.             crypt(in, out, cipher);
79.             in.close();
80.             out.close();
81.          }
82.       }
83.       catch (IOException e)
84.       {
85.          e.printStackTrace();
86.       }
87.       catch (GeneralSecurityException e)
88.       {
89.          e.printStackTrace();
90.       }
91.       catch (ClassNotFoundException e)
92.       {
93.          e.printStackTrace();
94.       }
95.    }
96.
97.    
104.    public static void crypt(InputStream in, OutputStream out, Cipher cipher)
105.          throws IOException, GeneralSecurityException
106.    {
107.       int blockSize = cipher.getBlockSize();
108.       int outputSize = cipher.getOutputSize(blockSize);
109.       byte[] inBytes = new byte[blockSize];
110.       byte[] outBytes = new byte[outputSize];
111.
112.       int inLength = 0;
113.       ;
114.       boolean more = true;
115.       while (more)
116.       {
117.          inLength = in.read(inBytes);
118.          if (inLength == blockSize)
119.          {
120.             int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
121.             out.write(outBytes, 0, outLength);
122.          }
123.          else more = false;
124.       }
125.       if (inLength > 0) outBytes = cipher.doFinal(inBytes, 0, inLength);
126.       else outBytes = cipher.doFinal();
127.       out.write(outBytes);
128.    }
129.
130.    private static final int KEYSIZE = 512;
131. }
你现在已经看到了Java安全模型是如何允许我们去控制代码的执行的,这是Java平台的一个独一无二且越来越重要的方面。你已经看到了Java类库提供的认证和加密服务。但是我们没有涉及许多高级和专有的话题,比如有:
提供了对Kerberos协议进行支持的"通用安全服务"的GSS-API(原则上同样支持其他安全信息交换协议)。下面这个网址上有一份JDK的指南:
http://docs.oracle.com/javase/7/docs/technotes/guides/security/jgss/tutorials/index.html
对SASL的支持,SASL即简单认证和安全层,可以为LDAP和IMAP协议所使用。如果想在自己的应用程序中实现SASL,请浏览下面这个网址:
http://docs.oracle.com/javase/7/docs/technotes/guides/security/sasl/sasl-refguide.html
对SSL的支持,SSL即安全套接层。在HTTP上使用SSL对应用程序的编程人员是透明的,只需要直接使用以https开头的URL即可。如果想要给你的应用程序添加SSL支持,请参阅下面网址中的:JSSE(Java安全套接扩展)参考指南http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html
全面了解java安全策略:http://docs.oracle.com/javase/7/docs/technotes/guides/security/index.html

阅读(6606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~