Java语言的非对称加密的实现
来源:互联网 发布:iphone怎么授权软件 编辑:程序博客网 时间:2024/06/05 07:46
众所周知,互联网上的安全是非常重要的一个课题,如何让我们的软件,通信协议更加安全,是每个程序员都需要思考的问题。
本文主要讨论三种非对称加密的情况。
1.私钥加密-公钥解密
2.公钥加密-私钥解密
3.私钥签名-公钥验证
产生密钥对
无论上述哪种情况,我们都需要产生一个密钥对。
使用Keytool生成
需要借助JDK中自带的keytool来生成。在命令行模式下输入keytool.
如果配置正常,应该显示以上内容,如果提示commend not found.那需要把JDK的路径加入到Path中。有不会的同学请自行百度。
我们使用-genkeypair命令。
在命令行中输入:
keytool -genkey -help
可以看到这里详细参数的用法。
我们创建一个密钥库(含密钥对),命令如下:
keytool -genkey -alias blogkey -keyalg RSA -validity 36500 -keystore h:\key\blogkey.keystore
-alias 密钥库的别名,用于识别这个密钥库
-keyalg 这里我们使用常见的RSA算法
-validity 有效期,这里我们填了100年
-keystore 生成的文件名
根据系统引导填完内容,我们就创建了一个密钥库。
接下来我们需要导出证书,里面包含公钥。
我们使用-export命令。
keytool -export -rfc -alias blogkey -file pubkey.cer -keystore h:\key\blogkey.keystore
我们把导出的证书存为pubkey.cer
到目前为止,我们获取一个blogkey.keystore的密钥库及pubkey.cer的证书,其中blogkey.keystore自用,pubkey.cer转给别人使用。
从keystore中提取privatekey
private static PrivateKey getPrivateKey(String keyStorePath, String alias, String password) throws Exception { FileInputStream is = new FileInputStream(keyStorePath); KeyStore ks = KeyStore.getInstance("JKS"); ks.load(is, password.toCharArray()); is.close(); PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray()); return key; }
在pubkey.cer中获取publickey
private static PublicKey getPublicKey(String certificatePath) throws Exception { CertificateFactory certificateFactory = CertificateFactory .getInstance("X.509"); FileInputStream in = new FileInputStream(certificatePath); Certificate certificate = certificateFactory.generateCertificate(in); in.close(); PublicKey key = certificate.getPublicKey(); return key; }
使用KeyPairGenerator直接生成
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); //可支持DiffieHellman (1024), DSA (1024),RSA (1024, 2048) keyPairGenerator.initialize(1024); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic();
私钥加密-公钥解密
前面的章节我们获得了privateKey及publicKey, 接下来的事情就简单了。
私钥加密
private static byte[] encryptByPrivateKey(data[] plainData, PrivateKey privateKey ) throws Exception { Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(plainData); }
公钥解密
public static byte[] decryptByPublicKey(byte[] data, PublicKey publicKey ) throws Exception { Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(data);}
公钥加密-私钥解密
公钥加密
public static byte[] encryptByPublicKey(byte[] plainData, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(plainData); }
私钥解密
public static byte[] decryptByPrivateKey(byte[] data, PrivateKey privateKey ) throws Exception { Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privateKey); return cipher.doFinal(data); }
私钥签名-公钥验证
私钥签名
利用私钥签名除了私钥之外,我们还需要一个证书,因此如果没有在第一步生成pubkey.cer,这部分是无法实验的。
public static byte[] sign(byte[] sign, String keyStorePath, String alias, String password) throws Exception { // 获得证书 X509Certificate x509Certificate = (X509Certificate) getCertificate( keyStorePath, alias, password); // 获取私钥 KeyStore ks = getKeyStore(keyStorePath, password); // 取得私钥 PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password .toCharArray()); // 构建签名 Signature signature = Signature.getInstance(x509Certificate .getSigAlgName()); signature.initSign(privateKey); signature.update(sign); return (signature.sign()); } private static Certificate getCertificate(String keyStorePath, String alias, String password) throws Exception { KeyStore ks = getKeyStore(keyStorePath, password); Certificate certificate = ks.getCertificate(alias); return certificate; }
公钥验证
public static boolean verify(byte[] data, byte[] sign, String certificatePath) throws Exception { // 获得证书 X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath); // 获得公钥 PublicKey publicKey = x509Certificate.getPublicKey(); // 构建签名 Signature signature = Signature.getInstance(x509Certificate .getSigAlgName()); signature.initVerify(publicKey); signature.update(data); return signature.verify((sign)); } private static Certificate getCertificate(String certificatePath) throws Exception { CertificateFactory certificateFactory = CertificateFactory .getInstance(X509); FileInputStream in = new FileInputStream(certificatePath); Certificate certificate = certificateFactory.generateCertificate(in); in.close(); return certificate; }
小结
本文讲述了利用公钥和私钥对通信过程的数据进行非对称加密。而在实际应用过程中,由于非对称加密比对称加密更加费CPU,因此,通常都是非对称加密与对称加密相结合。即对称加密使用的密钥通过非对称加密来传递。对于交换密钥,另一个算法叫DH和他的优化算法Oakley,专门用来处理这类任务,有兴趣的同学可以下去了解下。
加密的目的是为了提高破解门槛,要记住一句话,世界没有绝对安全,只有更加安全。
扩展,关于Key的序列化问题
通常,我们的Key是以byte[]的形式进行交换,因此,我们需要把PublicKey/PrivateKey的对象转换为byte[].
在Key的方法有一个getEncoded()能够将其转为byte[].
byte[] dataprivate = privateKey.getEncoded(); byte[] datapublic = publicKey.getEncoded();
在恢复时,则需要分别处理。
对于私钥,我们有
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dataprivate); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey1 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
对于公钥,我们有
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(datapublic); keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey1 = keyFactory.generatePublic(x509EncodedKeySpec);
参考文章:
- http://snowolf.iteye.com/blog/391931
- http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html
参考书目:Java加密与解密的艺术
- Java语言的非对称加密的实现
- android Java语言非对称加密的实现
- Java实现的RSA非对称加密工具
- 对称加密与非对称加密理解和非对称加密的java例子
- Sql2005 非对称加密的实现
- Java 实现非对称加密
- Java实现非对称加密
- JAVA实现非对称加密
- Java非对称加密的源代码(RSA)
- java非对称加密的源代码(RSA)
- java非对称加密的源代码(RSA)
- java非对称加密的源代码(RSA)
- java非对称加密的源代码(RSA)
- Java加密与解密的艺术-非对称加密
- java实现DH非对称加密工具包
- Java实现Rsa非对称加密
- Java实现RSA非对称加密
- JAVA实现RSA加密,非对称加密算法
- 优酷 Java笔试题(摘要)
- 1015 Knight Moves
- Oracle数据库触发器如何调用Java程序实现Openfire消息推送
- jQuery源码学习之对象创建与初始化
- 数值的整数次方
- Java语言的非对称加密的实现
- 文章标题
- C++静态多态性之函数重载
- 使用循环语句输出空心金字塔
- 关于编程语句i++与++i的区别用法
- eclipse出现 Some character…
- php实现二维数组转置
- php中标准使用类的方法
- php复选框中获取文本框、密码域、…