本文主要是介绍2 数字签名,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
转载自: http://blog.chinaunix.net/uid-7374279-id-4064434.html
基本原理:
数字签名使用密钥对(公开密钥和私有密钥),任何持有公开密钥的人都能解密、而只有加密密钥持有者(私有密钥)能够生成消息。
使用举例:
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(网址http://www. bouncycastle.org),它提供了一个支持RSA的密码提供商和其他许多SunJCE提供商没有提供的特性。该提供商已经由Sun公司签名,因此可以将它与JDK结合起来使用。
http://hiyachen.blog.chinaunix.net chf@tsinghua.org.cn http://weibo.com/u/1741045910
如果要使用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
这篇关于2 数字签名的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!