`
bnmnba
  • 浏览: 293557 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

非对称加密、公钥和私钥简要说明,Java实现RSA加密/解密/签章/验章

 
阅读更多

提示:

1、公钥加密只能用私钥解密。

2、私钥加密只能用公钥解密。

3、文章中的密文是指加密后的内容类似:MIGfMA0GC=

4、代码中使用Base64是为了把二进制数组转换为字符串。加密解密内容是二进制,不限于字符串。

 

本文说明一下非对称加密如何实现安全通讯:

A和B两个人进行安全通讯需要:A的公钥和私钥、B的公钥和私钥。

1、A和B保存好自己的私钥不要泄漏。A公开自己的公钥,B保存A的公钥;B公开自己的公钥,A保存B的公钥。

2、A发消息到B。格式如下:

from:A(说明:A名字没有加密,所有人都能看到)
to:B(说明:B名字没有加密,所有人都能看到)
content:X我喜欢你,你知道吗?X(说明:[X我喜欢你,你知道吗?X]是用B的公钥加密后的密文,
B的私钥才能打开)
sign:EG6V/RGbxYFoX1Uz4r6MgUeqh2hAb9Duj8JlB8Y5iSRxMTO1PpAH..
(说明:用B的名字和加密后的内容,用A私钥签章得到的数字印章)

3、很多人都收到了这条消息,其中包括一些想要监控你通信内容的坏人。所有人都看到A向B发消息了,有A公钥的人能验证接收者是不是自己和加密内容没有被修改过,而加密内容却只有拥有B私钥的人才能打开!

4、B向A发消息也是类似。就这样,在不安全的链路上进行安全的通讯就完成了!

 

附上java实现的RSA的小例子:

MainTest:

package rsa;

import java.util.HashMap;
import java.util.Map;

public class MainTest {

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) {
		KeyGenerater kgA = new KeyGenerater();
		kgA.generater();

		KeyGenerater kgB = new KeyGenerater();
		kgB.generater();
		

		System.out.println("pubKeyA = " + new String(kgA.getPubKey()));
		System.out.println("priKeyA = " + new String(kgA.getPriKey()));
		System.out.println("PubKeyB = " + new String(kgB.getPubKey()));
		System.out.println("PriKeyB = " + new String(kgB.getPriKey()));
		
		String text = "我喜欢你,你知道吗?"+((char) 134) + "";   
		byte[] content=text.getBytes();
		print("content :",content);
		byte[] contentByteEntrpted=RASUtil.encryptByPubKey( content,kgB.getPubKey()/*B的公钥*/);//A加密内容,content的内容
		print("contentByteEntrpted    Bytes:",contentByteEntrpted);
		String beSigned=new StringBuilder()//被签章的内容:包括接收者和加密后的内容,保证这些内容,用A的私钥加密后没有人可以修改签章内容。
		.append(new String("B"))//确保接收者不被修改
		.append(new String(contentByteEntrpted))//确保加密内容不被修改
		.toString();
		System.out.println("beSigned ="+beSigned);
		byte[] signByte=RASUtil.sign(kgA.getPriKey()/*A的私钥*/, beSigned);//A签名,sign的内容
		System.out.println("signByte:"+new String(signByte));
		
		//组装成可以进行传输的数据对象,Base64是为了字符串化二进制,方便传输(二进制里的一些特殊控制字符不适合进行传输)
		Map<String,String> map=new HashMap<String, String>();
		map.put("from", "A");
		map.put("to", "B");
		map.put("content", new String(contentByteEntrpted));
		map.put("sign", new String(signByte));
		
		String beSigned_B=new StringBuilder()//B要验章。
		.append(new String("B"))
		.append(map.get("content"))
		.toString();
		//B验章
		System.out.println("B验证签名:"+RASUtil.verify(kgA.getPubKey()/*A的公钥*/, beSigned_B, map.get("sign").getBytes()));//B验证签名,如果为true,说明内容没有被修改,且接收者必定是自己。
		print("contentByteEntrpted.getBytes:",map.get("content").getBytes());
		//B如果发现接收者是自己,用私钥解开内容
		byte[] content2=RASUtil.decryptByPriKey(map.get("content").getBytes(), kgB.getPriKey()/*B的私钥*/);
		content2=Base64.decode(content2);
		
		print("content2:",content2);
		System.out.println("加密解密无误:"+equals(content,content2));//只要保证,byte数组的每一个都是相等的即证明加密解密无误
		//System.out.println(new String(content2).equals(new String(content)));//true
		//System.out.println(new String(content2).equals(text));//false,byte数组和字符串转换时,最后那个特殊char转换后发生变化导致。

	}

	private static boolean equals(byte[] b, byte[] m2) {
		try{
		for (int i = 0; i < m2.length; i++) {
			if(b[i]!=m2[i]){
				return false;
			}
		}
		return true;
		}catch (Exception e) {
			return false;
		}
	}

	private static void print(String s,byte[] m) {
		System.out.print(s);
		for (int i = 0; i < m.length; i++) {
			System.out.print(Byte.valueOf(m[i]).intValue());
			System.out.print(",");
		}
		System.out.println();
		
	}

}

 KeyGenerater:

package rsa;

import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;

public class KeyGenerater {
	private byte[] priKey;
	private byte[] pubKey;

	public byte[] getPriKey() {
		return priKey;
	}

	public void setPriKey(byte[] priKey) {
		this.priKey = priKey;
	}

	public byte[] getPubKey() {
		return pubKey;
	}

	public void setPubKey(byte[] pubKey) {
		this.pubKey = pubKey;
	}

	public void generater() {
		try {
			java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator
					.getInstance("RSA");
			SecureRandom secrand = new SecureRandom();
//			secrand.setSeed(seed.getBytes()); // 初始化随机产生器,不要调用这个,不安全//seed相同的情况下,每次产生的密钥都一样
			keygen.initialize(1024, secrand);
			KeyPair keys = keygen.genKeyPair();

			PublicKey pubkey = keys.getPublic();
			PrivateKey prikey = keys.getPrivate();

			pubKey = Base64.encodeToByte(pubkey.getEncoded());
			priKey = Base64.encodeToByte(prikey.getEncoded());

		} catch (java.lang.Exception e) {
			System.out.println("生成密钥对失败");
			e.printStackTrace();
		}
	}

}

 RASUtil:

package rsa;

public class RASUtil {
	/**
	 * 
	 * Description:数字签名
	 * 
	 * @param priKeyByte
	 * @param plainText
	 * @return
	 */
	public static byte[] sign(byte[] priKeyByte, String plainText) {
		try {
			java.security.spec.PKCS8EncodedKeySpec priPKCS8 = new java.security.spec.PKCS8EncodedKeySpec(
					Base64.decode(priKeyByte));
			java.security.KeyFactory keyf = java.security.KeyFactory.getInstance("RSA");
			java.security.PrivateKey prikey = keyf.generatePrivate(priPKCS8);

			// 用私钥对信息生成数字签名
			java.security.Signature signet = java.security.Signature
					.getInstance("MD5withRSA");
			signet.initSign(prikey);
			signet.update(plainText.getBytes());
			byte[] signed = Base64.encodeToByte(signet.sign());
			return signed;
		} catch (java.lang.Exception e) {
			System.out.println("签名失败");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 
	 * Description:校验数字签名,此方法不会抛出任务异常,成功返回true,失败返回false,要求全部参数不能为空
	 * 
	 * @param pubKeyByte
	 *            公钥,base64编码
	 * @param plainText
	 *            明文
	 * @param signByte
	 *            数字签名的密文,base64编码
	 * @return 校验成功返回true 失败返回false
	 */
	public static boolean verify(byte[] pubKeyByte, String plainText,
			byte[] signByte) {
		try {
			// 解密由base64编码的公钥,并构造X509EncodedKeySpec对象
			java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
					Base64.decode(pubKeyByte));
			// RSA对称加密算法
			java.security.KeyFactory keyFactory = java.security.KeyFactory
					.getInstance("RSA");
			// 取公钥匙对象
			java.security.PublicKey pubKey = keyFactory
					.generatePublic(bobPubKeySpec);
			// 解密由base64编码的数字签名
			byte[] signed = Base64.decode(signByte);
			java.security.Signature signatureChecker = java.security.Signature
					.getInstance("MD5withRSA");
			signatureChecker.initVerify(pubKey);
			signatureChecker.update(plainText.getBytes());
			// 验证签名是否正常
			if (signatureChecker.verify(signed))
				return true;
			else
				return false;
		} catch (Throwable e) {
			System.out.println("校验签名失败");
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 公钥加密
	 * 
	 * @param data
	 * @param publicKey
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPubKey(byte[] data, byte[] pubKeyByte) {
		try {

			// 解密由base64编码的公钥,并构造X509EncodedKeySpec对象
			java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
					Base64.decode(pubKeyByte));
			// RSA对称加密算法
			java.security.KeyFactory keyFactory = java.security.KeyFactory
					.getInstance("RSA");
			// 取公钥匙对象
			java.security.PublicKey pubKey = keyFactory
					.generatePublic(bobPubKeySpec);
			javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("RSA");
			cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, pubKey);
			return Base64.encodeToByte(cipher.doFinal(data));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 私钥加密
	 * 
	 * @param data
	 * @param priKeyByte
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPriKey(byte[] data, byte[] priKeyByte) {
		try {
			java.security.spec.PKCS8EncodedKeySpec priPKCS8 = new java.security.spec.PKCS8EncodedKeySpec(
					Base64.decode(priKeyByte));
			java.security.KeyFactory keyf = java.security.KeyFactory.getInstance("RSA");
			java.security.PrivateKey prikey = keyf.generatePrivate(priPKCS8);
			javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("RSA");
			cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, prikey);
			return Base64.encodeToByte(cipher.doFinal(data));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 公钥解密
	 * 
	 * @param data
	 * @param pubKeyByte
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPubKey(byte[] data, byte[] pubKeyByte) {
		try {
			// 解密由base64编码的公钥,并构造X509EncodedKeySpec对象
			java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(
					Base64.decode(pubKeyByte));
			// RSA对称加密算法
			java.security.KeyFactory keyFactory = java.security.KeyFactory
					.getInstance("RSA");
			// 取公钥匙对象
			java.security.PublicKey pubKey = keyFactory
					.generatePublic(bobPubKeySpec);
			javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("RSA");
			cipher.init(javax.crypto.Cipher.DECRYPT_MODE, pubKey);
			return Base64.encodeToByte(cipher.doFinal(Base64.decode((data))));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 私钥解密
	 * 
	 * @param data
	 * @param priKeyByte
	 * @return
	 * @throws Exception
	 */
	public static byte[] decryptByPriKey(byte[] data, byte[] priKeyByte) {
		try {
			java.security.spec.PKCS8EncodedKeySpec priPKCS8 = new java.security.spec.PKCS8EncodedKeySpec(
					Base64.decode(priKeyByte));
			java.security.KeyFactory keyf = java.security.KeyFactory.getInstance("RSA");
			java.security.PrivateKey prikey = keyf.generatePrivate(priPKCS8);
			javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("RSA");
			cipher.init(javax.crypto.Cipher.DECRYPT_MODE, prikey);
			return Base64.encodeToByte(cipher.doFinal(Base64.decode(data)));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

 Base64:转换一下用了Apache的commons-codec-1.10.jar

package rsa;

public class Base64 {

	public static byte[] encodeToByte(byte[] encoded) {
		return org.apache.commons.codec.binary.Base64.encodeBase64(encoded);
	}

	public static byte[] decode(byte[] plainByte) {
		return org.apache.commons.codec.binary.Base64.decodeBase64(plainByte);
	}

}

代码引用:http://blog.csdn.net/sunyujia/article/details/2008480

附件commons-codec-1.10.jar

分享到:
评论

相关推荐

    C# .net版 RSA 公钥加密私钥解密 私钥加密公钥解密

    本教程主要讲解如何在C# .NET环境中使用RSA进行公钥加密和私钥解密,以及私钥加密和公钥解密的操作。 首先,让我们了解RSA的基本原理。RSA算法基于两个大素数的乘积,这个乘积作为公钥,而这两个大素数作为私钥。...

    RSA算法JAVA公钥加密,C#私钥解密

    在这个示例中,"RSA加密"的压缩包可能包含了Java和C#的完整源代码,用于演示如何在两者之间实现RSA公钥加密和私钥解密的过程。开发者可以通过运行这些示例代码,理解并应用RSA加密解密技术到自己的项目中。

    Java 公钥和私钥加密解密代码

    以下是一个简单的Java代码示例,演示了如何生成公钥和私钥对,并使用它们进行加密和解密: ```java import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; ...

    asp.net RSA 私钥加密公钥解密 能解 php Java 实现RSA加密互通

    在IT行业中,加密技术是确保数据安全的重要手段之一,RSA(Rivest-Shamir-Adleman)算法就是一种广泛使用的非对称加密算法。本文将深入探讨如何在ASP.NET环境中实现RSA加密,并且与PHP和Java进行互通,以及涉及的...

    Java实现RSA生成公钥私钥

    在Java中实现RSA公钥和私钥的生成,通常我们会使用Java Cryptography Extension (JCE) 提供的API,如`java.security.KeyPairGenerator`类。但是,根据你的描述,这里提供的代码是不直接依赖API,而是通过数学计算来...

    C# 非对称加密 私钥加密 公钥解密实现

    C# RSA非对称加密 实现私钥加密 公钥解密;可以用于生成授权码。 RSA生成一下随机值,然后都是用BigInteger类字符串跟字节数组互转

    C#RSA私钥加密公钥解密

    总的来说,这个项目展示了如何在C#中使用`System.Numerics.BigInteger`实现RSA加密算法,同时提供了私钥加密和公钥解密的功能,确保了数据的安全性。为了实际应用,你需要理解并掌握RSA算法的原理,以及如何在.NET...

    RSA生成公钥私钥和使用公钥私钥加密解密demo

    本示例提供了一个RSA加密工具类,用于生成公钥和私钥,并使用它们进行加密和解密操作,这对于保护数据库中的敏感信息,如密码,是非常必要的。 1. **RSA算法原理**: RSA算法基于数论中的大数因子分解难题。其基本...

    Delphi RSA加解密【支持RSA公钥加密私钥解密,RSA私钥加密公钥解密,秘钥格式支持PKCS8和PKCS1】D7~XE10可用

    本例中的Project1.exe可能是一个Delphi编译的示例应用程序,展示了如何在Delphi环境中使用RSA加密和解密。这个程序应该演示了如何生成RSA密钥对,使用公钥加密数据,然后使用私钥解密,反之亦然。在实际应用中,公钥...

    C# 实现与JAVA互通 加签/验签,RSA加密/解密

    * RSA加密解密:私钥解密,公钥加密。 * RSA数字签名-俗称加签验签:私钥加签,公钥验签。  * RSA加密解密:私钥解密,公钥加密。 * RSA数字签名-俗称加签验签:私钥加签,公钥验签。  * RSA加密解密:私钥...

    java中使用公钥加密私钥解密原理实现license控制

    Java 中使用公钥加密私钥解密原理实现 License 控制是指在 Java 应用程序中使用公钥加密、私钥解密机制来实现 License 文件的控制。这种机制可以用来限制系统的使用,例如限制试用期、限制用户数量、限制 IP 地址等...

    Java公钥加密私钥解密.rar

    在这个案例中,开发者可能使用了Java的Java Cryptography Extension (JCE) 来实现RSA算法,这是一种非对称加密算法,它基于两个不同的密钥——公钥和私钥——进行加密和解密。 首先,让我们理解公钥和私钥的概念。...

    C++实现RSA公钥私钥加密算法

    在C++中实现RSA加密和解密,我们需要用到大数运算库,如GMP(GNU Multiple Precision Arithmetic Library),因为它能处理超过标准整型大小的数字。 **加密过程**: - 输入明文m,0 。 - 使用公钥(e, n),计算c = m...

    RSA.zip_C++ rsa私钥加密_rsa加密解密_公钥私钥_私钥加密

    在给定的"RSA.zip"压缩包中,可能包含了C++代码示例,用于演示如何使用RSA算法进行加密和解密操作,以及如何生成和管理公钥私钥对。文件名"RSA"可能是源代码文件或执行程序。通过学习和理解这些代码,开发者可以更好...

    C# RSA加密、支持JAVA格式公钥私钥

    2. **C#实现RSA**:在C#中,`System.Security.Cryptography.RSACryptoServiceProvider`类提供了RSA加密和解密的功能。你可以通过这个类创建、保存和加载密钥对,然后使用`Encrypt`和`Decrypt`方法进行加解密操作。 ...

    公钥加密私钥解密&私钥加密公钥解密

    公钥加密私钥解密是基于非对称加密算法的一种实现方式。这种加密方法使用一对密钥——公钥和私钥。其中,公钥可以公开给任何人使用,而私钥则必须保密,只有密钥的所有者才能掌握。具体工作流程如下: 1. **发送方...

    C# RSA 公钥加密,私钥解密

    在C#中,我们可以使用.NET Framework提供的System.Security.Cryptography命名空间中的RSACryptoServiceProvider类来实现RSA加密和解密。首先,我们需要生成一对公钥和私钥。这可以通过调用RSACryptoServiceProvider...

    Go-gorsa支持rsa公钥加密私钥解密;支持rsa公钥解密私钥加密

    "Go-gorsa"是一个专门为Go语言设计的安全库,它专注于RSA(Rivest-Shamir-Adleman)加密算法的实现,允许用户进行公钥加密和私钥解密,以及公钥解密和私钥加密的操作。这一特性使得gorsa在确保信息安全方面具有很高...

    支持rsa公钥加密私钥解密;支持rsa公钥解密私钥加密

    RSA算法是一种非对称加密算法,它是现代密码学的基石之一,广泛应用于数据加密、数字签名和密钥交换等领域。该算法基于数论中的大数因子分解难题,由Ron Rivest、Adi Shamir和Leonard Adleman在1978年提出,因此得名...

    JavaRSA生成公钥私钥加解密

    JavaRSA生成公钥私钥及加解密是Java编程中涉及密码学的重要实践。RSA是一种非对称加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman在1977年提出,因其发明者的名字首字母命名。在Java中,我们可以使用Java ...

Global site tag (gtag.js) - Google Analytics