`
talin2010
  • 浏览: 521011 次
  • 性别: Icon_minigender_1
  • 来自: 河北
社区版块
存档分类
最新评论

Java加密与解密(by quqi99)

阅读更多

Java加密与解密(by quqi99)

作者:张华 发表于:2009-12-31

版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

1)base64算法

加密:new BASE64Encoder().encode(byte[] b)

解密: new BASE64Decoder().decode(byte[] b)

2) MD5或SHA摘要

MessageDigest digest = MessageDigest.getInstance("SHA"); //若是md5就 "MD5"

digest.update(byte[] b);

sha.degest();

3) 字节与16进制互换。

String strDigits = "0123456789ABCDEF";

String strDigitArr = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F");

public String byte2Hex(byte[] bytes){

String hs = "";

String stmp = "";

for(int =0;n<bytes.length;n++){

stmp = (Integer.toHexString(bytes[n] & 0XFF));

if(stmp.length() == 1)

hs = hs + "0" + stmp;

else

hs = hs + stmp;

}

return hs.toUpperCase();

}

public byte[] hex2Str(String hexStr){

char[] hexs = hexStr.toCharArray();

byte[] bytes = new byte[hexStr.length()/2];

int n;

for(int i=0;i<bytes.length;i++){

n = strDigits.indexOf(hexs[2*i]) * 16;

n += strDigits.indexOf(hexs[2*i + 1]);

bytes[i] = (byte)(n & 0xff);

}

}

4) RSA有公钥与密钥

生成密钥对:

private KeyPair generateKeyPair(){

KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");

gen.initialize(1024,new SecureRandom());

KeyPari key = gen.genKeyPair();

return key;

}

//从公钥字节恢复公钥

//从密钥字节恢复密钥与这差不多,只不过将public字眼换成private

private RSAPublicKey recoverRSAPublicKey(byte[] modulus, byte[] publicExponent){

RSAPublicKeySpec spec = new RSAPublicKeySpec(new BigInteger(modulus),new BigInteger(publicExponent));

KeyFactory fac = KeyFacotry.getInstance("RSA");

RSAPublicKey key = (RSAPublicKey)fac.generatePublic(spec);

return key;

}

//RSA加解密

private byte[] rsaTrans(int mode,Key key,byte[] data){

if(mode != Cipher.ENCRYPT_MODE && mode!=Cipher.DECRYPT_MODE)

throw new Exception("");

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(mode,key,new SecureRandom());

return cipher.doFinal(data);

}

使用上述的方法:

KeyPair keyPair = generateKeyPair();

RSAPublicKey pubKey = (RSAPublicKey)keyPair.getPublic();

RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();

byte[] pubModulusBytes = pubKey.getModulus().toByteArray();

byte[] publicExponentBytes = pubKey.getPublicExponent().toByteArray();

byte[] privateModulusBytes = privateKey.getModulus().toByteArray();

byte[]privateExponentBytes = privateKey.getPrivateExponent().toByteArray();

pubKey = recoverRSAPublicKey(pubModulusBytes,publicExponentBytes); //恢复公钥,恢复密钥类似

//用私钥加密

byte[] encryptData = rsaTran(Cipher.ENCRYPT_MODE,privateKey,bytes));

//用公钥解密

encryptData = rsaTran(Cipher.DECRYPT_MODE,privateKey,bytes));

5) DES为单钥加密机制,加密过程与RSA差不多。

步骤1:生成一个安全密匙。在加密或解密任何数据之前需要有一个密匙。密匙是随同被加密的应用一起发布的一小段数据

import java.security.SecureRandom;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
public class GenerateKey
{
static public void main( String args[] ) throws Exception {
String keyFilename = "key.data";
String algorithm = "DES";
// 生成密匙
SecureRandom sr = new SecureRandom();
KeyGenerator kg = KeyGenerator.getInstance( algorithm );
kg.init( sr );
SecretKey key = kg.generateKey();//[-68, -68, -57, -71, 42, -125, 32, 13]
// 把密匙数据保存到文件
Util.writeFile( keyFilename, key.getEncoded() );
}
}

步骤2:加密数据。得到密匙之后,接下来就可以用它加密数据。

 // DES算法要求有一个可信任的随机数源

SecureRandom sr = new SecureRandom();

byte rawKeyData[] = /* 用某种方法获得密匙数据 */;

// 从原始密匙数据创建DESKeySpec对象

DESKeySpec dks = new DESKeySpec( rawKeyData );

// 创建一个密匙工厂,然后用它把DESKeySpec转换

// 一个SecretKey对象

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance( "DES" );

SecretKey key = keyFactory.generateSecret( dks );

// Cipher对象实际完成加密操作

Cipher cipher = Cipher.getInstance( "DES" );

// 用密匙初始化Cipher对象

cipher.init( Cipher.ENCRYPT_MODE, key, sr )

// 现在,获取数据并加密

byte data[] = /* 用某种方法获取数据 */

// 正式执行加密操作

byte encryptedData[] = cipher.doFinal( data );

// 进一步处理加密后的数据



步骤3:解密数据。

在上述加密数据将

cipher.init( Cipher.ENCRYPT_MODE, key, sr );

一句换成

cipher.init( Cipher.DECRYPT_MODE, key, sr );

doSomething( encryptedData );









下面附一个练习的例子,写的一个License,代码如下:

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.security.SecureRandom;

import java.text.SimpleDateFormat;

import java.util.Date;

import javax.crypto.Cipher;

import javax.crypto.KeyGenerator;

import javax.crypto.SecretKey;

import javax.crypto.SecretKeyFactory;

import javax.crypto.spec.DESKeySpec;

/**



* @version 0.10 2010-2-28

* @author Zhang Hua

* 利用license机制来保护Java软件产品的安全

*/

public class License {

private static final String licensePath = "license.dat";

private static final String keyFilename = "key.data";

private static SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd"); //yyyy-MM-dd HH:mm:ss

//Product.title , AppServer

private String title = "AppServer";

//Product.sku, J2EE/CORBA

private String sku = "J2EE/CORBA";

//Serial.number, MAC Address

private byte[] serialNumber;

//Platform, all

private String platform = "";

//Trial.license

private boolean isTrial;

//License.expiry, 2010-05-12

private String expiry = "";

//Test

public static void main(String[] args){

//为用户生成license,并email给他

License om = new License();

om.setTitle("AppServer");

om.setSku("J2EE/CORBA");

String mac = getMACAddress();

om.setPlatform("Windows");

om.setTrial(false);

om.setExpiry("2010-05-12");

License.generateLicense(om,mac);

//在程序中校验license

License.validate();

}



//为用户生成license, 也就是将serialNumber字段的MAC加密

public static License generateLicense(License om,String mac){

try{

//密匙不存在,则生成密匙

if(! new File(keyFilename).exists()){

generateKey();

}

//用密匙加密数据

byte rawKeyData[] = readFile(keyFilename); //用某种方法获得密匙数据

DESKeySpec dks = new DESKeySpec( rawKeyData ); //从原始密匙数据创建DESKeySpec对象

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); //创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象

SecretKey key = keyFactory.generateSecret( dks );

Cipher cipher = Cipher.getInstance( "DES" ); //Cipher对象实际完成加密操作

SecureRandom sr = new SecureRandom(); //DES算法要求有一个可信任的随机数源

cipher.init(Cipher.ENCRYPT_MODE, key, sr ); //用密匙初始化Cipher对象

byte data[] = mac.getBytes(); //用某种方法获取数据

byte encryptedData[] = cipher.doFinal( data ); //正式执行加密操作

System.out.println("加密后的数据:" + encryptedData);

om.setSerialNumber(encryptedData);

//输出license

write(om);

}catch(Exception e){

e.printStackTrace();

}

return om;

}



//生成密匙

private static boolean generateKey(){

boolean result = false'

String algorithm = "DES";

try{

SecureRandom sr = new SecureRandom(); //DES算法要求有一个可信任的随机数源

KeyGenerator kg = KeyGenerator.getInstance(algorithm);

kg.init( sr );

SecretKey key = kg.generateKey(); //[-68, -68, -57, -71, 42, -125, 32, 13]

result = writeFile(keyFilename, key.getEncoded()); //把密匙数据保存到文件

}catch(Exception e){

e.printStackTrace();

}

return result;

}





public static boolean validate(){

boolean result = false;

try{

License om = read()'

String os = System.getProperty("os.name");

if (os.toLowerCase().startsWith(om.getPlatform().toLowerCase()) || "all".equals(om.getPlatform())) {

Date expireDate = sdf.parse(om.getExpiry());

if(expireDate.getTime() - new Date().getTime() < 0){

System.err.println("License过期了");

result = false'

}else{

if(om.isTrial()){

System.out.println("试用License有效");

result = true;

}else{

String mac = getMACAddress();

//用密匙解密数据

byte rawKeyData[] = readFile(keyFilename); //用某种方法获得密匙数据

DESKeySpec dks = new DESKeySpec( rawKeyData ); //从原始密匙数据创建DESKeySpec对象

SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); //创建一个密匙工厂,然后用它把DESKeySpec转换成一个SecretKey对象

SecretKey key = keyFactory.generateSecret( dks );

Cipher cipher = Cipher.getInstance( "DES" ); //Cipher对象实际完成加密操作

SecureRandom sr = new SecureRandom(); //DES算法要求有一个可信任的随机数源

cipher.init(Cipher.DECRYPT_MODE, key, sr ); //用密匙初始化Cipher对象

byte data[] = om.getSerialNumber(); //用某种方法获取数据

byte encryptedData[] = cipher.doFinal(data); //正式执行加密操作

String tmp = new String(encryptedData);

System.out.println("解密后的数据:" + tmp);

if(mac.equals(tmp)){

System.out.println("License有效");

result = true;

}else{

System.err.println("License无效");

result = false;

}

}

}

}else{

System.err.println("License的平台无效");

result = false;

}

}catch(Exception e){

e.printStackTrace();

}

return result;

}



public static License read(){

License om = null;

try{

om = new License();

ObjectInputStream in = new ObjectInputStream(new FileInputStream(licensePath));

om.setTitle((String)in.readObject());

om.setSku((String)in.readObject());

om.setPlatform((String)in.readObject());

om.setTrial(in.readBoolean());

om.setExpiry((String)in.readObject());

om.setSerialNumber((byte[])in.readObject());

in.close();

}catch(Exception e){

e.printStackTrace();

}

return om;

}





public static boolean write(License om){

boolean result;

try{

File f = new File(licensePath);

if(f.exists())

f.delete();

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));

out.writeObject(om.getTitle());

out.writeObject(om.getSku());

out.writeObject(om.getPlatform());

out.writeBoolean(om.isTrial());

out.writeObject(om.getExpiry());

out.writeObject(om.getSerialNumber());

out.close();

result = true;

}catch(Exception e){

e.printStackTrace();

result = false;

}

return result;

}















public static boolean writeFile(String path, byte[] bytes){







boolean result = false;







try {







FileOutputStream fos = new FileOutputStream(path);







fos.write(bytes);







fos.close();







result = true;







} catch (Exception e) {







e.printStackTrace();







}







return result;







}















public static byte[] readFile(String path){







byte[] bytes = null;







try {







FileInputStream fin = new FileInputStream(path);







bytes = new byte[fin.available()];







fin.read(bytes);







fin.close();







} catch (Exception e) {







e.printStackTrace();







}







return bytes;







}































public static String getMACAddress() {







String address = "";







String os = System.getProperty("os.name");







if (os.startsWith("Windows")) {







try {







String command = "cmd.exe /c ipconfig /all";







Process p = Runtime.getRuntime().exec(command);







BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));







String line;







while ((line = br.readLine()) != null) {







if (line.indexOf("Physical Address") > 0) {







int index = line.indexOf(":");







index += 2;







address = line.substring(index);







break;







}







}







br.close();







return address.trim();







} catch (IOException e) {







e.printStackTrace();







}







} else if (os.startsWith("Linux")) {







String command = "/bin/sh -c ifconfig -a";







Process p;







try {







p = Runtime.getRuntime().exec(command);







BufferedReader br = new BufferedReader(new InputStreamReader(p







.getInputStream()));







String line;







while ((line = br.readLine()) != null) {







if (line.indexOf("HWaddr") > 0) {







int index = line.indexOf("HWaddr") + "HWaddr".length();







address = line.substring(index);







break;







}







}







br.close();







} catch (IOException e) {







e.printStackTrace();



}



}



address = address.trim();

return address;

}





public String getTitle() {

return title;

}

public void setTitle(String title) {



this.title = title;

}

public String getSku() {

return sku;

}

public void setSku(String sku) {

this.sku = sku;

}

public byte[] getSerialNumber() {

return serialNumber;

}

public void setSerialNumber(byte[] serialNumber) {

this.serialNumber = serialNumber;

}



public String getPlatform() {

return platform;

}

public void setPlatform(String platform) {

this.platform = platform;

}



public boolean isTrial() {

return isTrial;

}

public void setTrial(boolean isTrial) {

this.isTrial = isTrial;

}

public String getExpiry() {

return expiry;

}

public void setExpiry(String expiry) {

this.expiry = expiry;

}

}







关于license的生成,还想说几点:

1)无论是生成二进制license,还是文件的,最好带上指纹校验。

2)无论是用什么加密算法无所谓,问题的关键不在里,在于JAVA容易被反编译,反编译之后很容易看到你的加密算法,人家可以

把这块替掉或者删除掉。另外,人家也可以在主程序调用license处的地方反编译之后直接返回true。

有网友说,对JAR包加密,然后自定义classloader解密,我看也是不行的,因为你自定义的classloader也是很容易被

反编译的,那样你的解密过程也就都清楚了。

所以,我认为,JAVA的东西就应用是开源的。当然,我们可以用混淆工具进行一定程度的混淆,算是给反编译增中一点困难的。

3)我试用了混淆工具proguard,觉得混淆工具有点不满足我的需求。

它默认是都混淆,但可以通过-keep参数指定某些类某些方法不混淆。

而我的需求是大多数类我不想混淆,我只想对少数几个类混淆,而且我的程序非常大,如果按照它的通过-keep参数指定

我不想混淆的类是不是有点太麻烦了。

下面是一个我测试过程中算是比较通用的配置my.conf,它对public,protected都不进行混淆,

用java -cp .;test.jar -jar proguard.jar @E:/workspace/test/my.conf 可执行混淆操作,my.conf文件如下:

-injars E:/workspace/test/test.jar

-outjars E:/workspace/test/test_out.jar

-libraryjars <java.home>/lib/rt.jar

-libraryjars E:/workspace/test/lib/mail.jar

-printmapping proguard.map



-renamesourcefileattribute SourceFile

-keepattributes Exceptions,InnerClasses,Signature,Deprecated,

SourceFile,LineNumberTable,*Annotation*,EnclosingMethod



-keep public class org.**





-keep public class * {

public protected *;

}



-keepclassmembernames class * {

java.lang.Class class$(java.lang.String);

java.lang.Class class$(java.lang.String, boolean);

}



-keepclasseswithmembernames class * {

native <methods>;

}



-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}



-keepclassmembers class * implements java.io.Serializable {

static final long serialVersionUID;

private void writeObject(java.io.ObjectOutputStream);

private void readObject(java.io.ObjectInputStream);

java.lang.Object writeReplace();

java.lang.Object readResolve();

}





 一、密码学上常用的概念 
  1)消息摘要:
  这是一种与消息认证码结合使用以确保消息完整性的技术。主要使用单向散列函数算法,可用于检验消息的完整性,和通过散列密码直接以文本形式 保存等,目前广泛使用的算法有MD4、MD5、SHA-1,jdk1.5对上面都提供了支持,在java中进行消息摘要很简单, java.security.MessageDigest提供了一个简易的操作方法:
  /**
   *MessageDigestExample.java
  *Copyright 2005-2-16
  */
   import java.security.MessageDigest;
  /**
  *单一的消息摘要算法,不使用密码.可以用 来对明文消息(如:密码)隐藏保存
  */
  public class MessageDigestExample{
   public static void main(String[] args) throws Exception{
   if(args.length!=1){
   System.err.println("Usage:java MessageDigestExample text");
   System.exit(1);
  }
  byte[] plainText=args[0].getBytes("UTF8");
  //使用getInstance("算法")来获得消息摘要, 这里使用SHA-1的160位算法
  MessageDigest messageDigest=MessageDigest.getInstance("SHA-1");
   System.out.println(" "+messageDigest.getProvider().getInfo());
  //开 始使用算法
  messageDigest.update(plainText);
  System.out.println(" Digest:");
  //输出算法运算结果
  System.out.println(new String(messageDigest.digest(),"UTF8"));
  }
  }
  还可以通过消息认证码 来进行加密实现,javax.crypto.Mac提供了一个解决方案,有兴趣者可以参考相关API文档,本文只是简单介绍什么是摘要算法。
   2)私钥加密:
  消息摘要只能检查消息的完整性,但是单向的,对明文消息并不能加密,要加密明文的消息的话,就要使用其他的算法,要确保机密性,我们需要使 用私钥密码术来交换私有消息。
  这种最好理解,使用对称算法。比如:A用一个密钥对一个文件加密,而B读取这个文件的话,则需要和A一样的密 钥,双方共享一个私钥(而在web环境下,私钥在传递时容易被侦听):
  使用私钥加密的话,首先需要一个密钥,可用 javax.crypto.KeyGenerator产生一个密钥(java.security.Key),然后传递给一个加密工具 (javax.crypto.Cipher),该工具再使用相应的算法来进行加密,主要对称算法有:DES(实际密钥只用到56位),AES(支持三种密 钥长度:128、192、256位),通常首先128位,其他的还有DESede等,jdk1.5种也提供了对对称算法的支持,以下例子使用AES算法来 加密:
  /**
  *PrivateExmaple.java
  *Copyright 2005-2-16
   */
  import javax.crypto.Cipher;
  import javax.crypto.KeyGenerator;
  import java.security.Key;
  /**
   *私鈅加密,保证消息机密性
  */
  public class PrivateExample{
  public static void main(String[] args) throws Exception{
   if(args.length!=1){
   System.err.println("Usage:java PrivateExample ");
   System.exit(1);
  }
  byte[] plainText=args[0].getBytes("UTF8");
  //通过KeyGenerator形成一个key
   System.out.println(" Start generate AES key");
  KeyGenerator keyGen=KeyGenerator.getInstance("AES");
  keyGen.init(128);
   Key key=keyGen.generateKey();
  System.out.println("Finish generating DES key");
  //获得一个私鈅加密类Cipher,ECB是加密方式,PKCS5Padding是填充方法
  Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");
   System.out.println(" "+cipher.getProvider().getInfo());
  //使用私鈅加密
   System.out.println(" Start encryption:");
   cipher.init(Cipher.ENCRYPT_MODE,key);
  byte[] cipherText=cipher.doFinal(plainText);
  System.out.println("Finish encryption:");
  System.out.println(new String(cipherText,"UTF8"));
   System.out.println(" Start decryption:");
   cipher.init(Cipher.DECRYPT_MODE,key);
  byte[] newPlainText=cipher.doFinal(cipherText);
   System.out.println("Finish decryption:");
  System.out.println(new String(newPlainText,"UTF8"));
  }
  }
  3)公钥加密:
  上面提到,私钥加密需要一个共享的密钥,那么如何传递密钥呢?web环境下,直接传递的话很容易被侦听到,幸好有了公钥加密的出现。公钥加 密也叫不对称加密,不对称算法使用一对密钥对,一个公钥,一个私钥,使用公钥加密的数据,只有私钥能解开(可用于加密);同时,使用私钥加密的数据,只有 公钥能解开(签名)。但是速度很慢(比私钥加密慢100到1000倍),公钥的主要算法有RSA,还包括Blowfish,Diffie-Helman 等,jdk1.5种提供了对RSA的支持,是一个改进的地方:
  /**
  *PublicExample.java
   *Copyright 2005-2-16
  */
  import java.security.Key;
   import javax.crypto.Cipher;
  import java.security.KeyPairGenerator ;
  import java.security.KeyPair;
  /**
  *一个简单的公鈅加密例子,Cipher类使用KeyPairGenerator 生成的公鈅和私鈅
  */
  public class PublicExample{
  public static void main(String[] args) throws Exception{
  if(args.length!=1){
    System.err.println("Usage:java PublicExample ");
   System.exit(1);
   }
  byte[] plainText=args[0].getBytes("UTF8");
  //构成一个RSA密钥
   System.out.println(" Start generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator .getInstance("RSA");
  keyGen.initialize(1024);
  KeyPair key=keyGen.generateKeyPair();
  System.out.println("Finish generating RSA key");
  //获得一个RSA的Cipher类,使用公鈅加密
  Cipher cipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");
   System.out.println(" "+cipher.getProvider().getInfo());
   System.out.println(" Start encryption");
   cipher.init(Cipher.ENCRYPT_MODE,key.getPublic());
  byte[] cipherText=cipher.doFinal(plainText);
  System.out.println("Finish encryption:");
  System.out.println(new String(cipherText,"UTF8"));
   //使用私鈅解密
  System.out.println(" Start decryption");
   cipher.init(Cipher.DECRYPT_MODE,key.getPrivate());
  byte[] newPlainText=cipher.doFinal(cipherText);
   System.out.println("Finish decryption:");
  System.out.println(new String(newPlainText,"UTF8"));
  }
  }
  4)数字签名:
  数字签名,它是确定交换消息的通信方身份的第一个级别。上面A通过使用公钥加密数据后发给B,B利用私钥解密就得到了需要的数据,问题来 了,由于都是使用公钥加密,那么如何检验是A发过来的消息呢?上面也提到了一点,私钥是唯一的,那么A就可以利用A自己的私钥进行加密,然后B再利用A的 公钥来解密,就可以了;数字签名的原理就基于此,而通常为了证明发送数据的真实性,通过利用消息摘要获得简短的消息内容,然后再利用私钥进行加密散列数据 和消息一起发送。java中为数字签名提供了良好的支持,java.security.Signature类提供了消息签名:
  /**
   *DigitalSignature2Example.java
  *Copyright 2005-2-16
  */
   import java.security.Signature;
  import java.security.KeyPairGenerator ;
  import java.security.KeyPair;
  import java.security.SignatureException;
   /**
  *数字签名,使用RSA私钥对对消息摘要签名,然后使用公鈅验证 测试
  */
  public class DigitalSignature2Example{
  public static void main(String[] args) throws Exception{
  if(args.length!=1){
    System.err.println("Usage:java DigitalSignature2Example ");
    System.exit(1);
  }
  byte[] plainText=args[0].getBytes("UTF8");
  //形成RSA公钥对
  System.out.println(" Start generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator .getInstance("RSA");
   keyGen.initialize(1024);
  KeyPair key=keyGen.generateKeyPair();
   System.out.println("Finish generating RSA key");
  //使用私鈅签名
   Signature sig=Signature.getInstance("SHA1WithRSA");
   sig.initSign(key.getPrivate());
  sig.update(plainText);
   byte[] signature=sig.sign();
   System.out.println(sig.getProvider().getInfo());
   System.out.println(" Signature:");
  System.out.println(new String(signature,"UTF8"));
  //使用公鈅验证
  System.out.println(" Start signature verification");
  sig.initVerify(key.getPublic());
   sig.update(plainText);
  try{
   if(sig.verify(signature)){
     System.out.println("Signature verified");
   }else System.out.println("Signature failed");
   }catch(SignatureException e){
    System.out.println("Signature failed");
   }
  }
   }
  5)数字证书。
  还有个问题,就是公钥问题,A用私钥加密了,那么B接受到消息后,用A提供的公钥解密;那么现在有个讨厌的C,他把消息拦截了,然后用自己 的私钥加密,同时把自己的公钥发给B,并告诉B,那是A的公钥,结果....,这时候就需要一个中间机构出来说话了(相信权威,我是正确的),就出现了 Certificate Authority(也即CA),有名的CA机构有Verisign等,目前数字认证的工业标准是:CCITT的X.509:
   数字证书:它将一个身份标识连同公钥一起进行封装,并由称为认证中心或 CA 的第三方进行数字签名。
  密钥库:java平台为你提供了密 钥库,用作密钥和证书的资源库。从物理上讲,密钥库是缺省名称为 .keystore 的文件(有一个选项使它成为加密文件)。密钥和证书可以拥有名称(称为别名),每个别名都由唯一的密码保护。密钥库本身也受密码保护;您可以选择让每个别 名密码与主密钥库密码匹配。
  使用工具keytool ,我们来做一件自我认证的 事情吧(相信我的认证):
  1、创建密钥库keytool -genkey -v -alias feiUserKey -keyalg RSA 默认在自己的home目录下(windows系统是c:documents and settings<你的用户名> 目录下的.keystore文件),创建我们用 RSA 算法生成别名为 feiUserKey 的自签名的证书,如果使用了-keystore mm 就在当前目录下创建一个密钥库mm文件来保存密钥和证书。
  2、查看证书:keytool -list 列举了密钥库的所有的证书
  也可以在dos下输入keytool -help查看帮助。
   4)数字签名:
  数字签名,它是确定交换消息的通信方身份的第一个级别。上面A通过使用公钥加密数据后发给B,B利用私钥解密就得到了需要的数据,问题来 了,由于都是使用公钥加密,那么如何检验是A发过来的消息呢?上面也提到了一点,私钥是唯一的,那么A就可以利用A自己的私钥进行加密,然后B再利用A的 公钥来解密,就可以了;数字签名的原理就基于此,而通常为了证明发送数据的真实性,通过利用消息摘要获得简短的消息内容,然后再利用私钥进行加密散列数据 和消息一起发送。java中为数字签名提供了良好的支持,java.security.Signature类提供了消息签名:
  /**
   *DigitalSignature2Example.java
  *Copyright 2005-2-16
  */
   import java.security.Signature;
  import java.security.KeyPairGenerator ;
  import java.security.KeyPair;
  import java.security.SignatureException;
   /**
  *数字签名,使用RSA私钥对对消息摘要签名,然后使用公鈅验证 测试
  */
  public class DigitalSignature2Example{
  public static void main(String[] args) throws Exception{
  if(args.length!=1){
    System.err.println("Usage:java DigitalSignature2Example ");
    System.exit(1);
  }
  byte[] plainText=args[0].getBytes("UTF8");
  //形成RSA公钥对
  System.out.println(" Start generating RSA key");
  KeyPairGenerator keyGen=KeyPairGenerator .getInstance("RSA");
   keyGen.initialize(1024);
  KeyPair key=keyGen.generateKeyPair();
   System.out.println("Finish generating RSA key");
  //使用私鈅签名
   Signature sig=Signature.getInstance("SHA1WithRSA");
   sig.initSign(key.getPrivate());
  sig.update(plainText);
   byte[] signature=sig.sign();
   System.out.println(sig.getProvider().getInfo());
   System.out.println(" Signature:");
  System.out.println(new String(signature,"UTF8"));
  //使用公鈅验证
  System.out.println(" Start signature verification");
  sig.initVerify(key.getPublic());
   sig.update(plainText);
  try{
   if(sig.verify(signature)){
     System.out.println("Signature verified");
   }else System.out.println("Signature failed");
   }catch(SignatureException e){
    System.out.println("Signature failed");
   }
  }
   }
  5)数字证书。
  还有个问题,就是公钥问题,A用私钥加密了,那么B接受到消息后,用A提供的公钥解密;那么现在有个讨厌的C,他把消息拦截了,然后用自己 的私钥加密,同时把自己的公钥发给B,并告诉B,那是A的公钥,结果....,这时候就需要一个中间机构出来说话了(相信权威,我是正确的),就出现了 Certificate Authority(也即CA),有名的CA机构有Verisign等,目前数字认证的工业标准是:CCITT的X.509:
   数字证书:它将一个身份标识连同公钥一起进行封装,并由称为认证中心或 CA 的第三方进行数字签名。
  密钥库:java平台为你提供了密 钥库,用作密钥和证书的资源库。从物理上讲,密钥库是缺省名称为 .keystore 的文件(有一个选项使它成为加密文件)。密钥和证书可以拥有名称(称为别名),每个别名都由唯一的密码保护。密钥库本身也受密码保护;您可以选择让每个别 名密码与主密钥库密码匹配。
  使用工具keytool ,我们来做一件自我认证的 事情吧(相信我的认证):
  1、创建密钥库keytool







分享到:
评论

相关推荐

    quqi.rar_mtk_mtk software_mtk平台

    在标签"mtk"、"mtk_software"和"mtk平台"方面,这些标签直接体现了软件与MediaTek芯片及其软件生态系统的紧密联系。"mtk_software"很可能指代那些针对MTK硬件进行优化的软件产品,它们在性能调优和兼容性方面进行了...

    视频播放源代码directshow开发

    - 构建过滤图,将源过滤器与解码过滤器、渲染过滤器连接起来。 - 实现事件处理,例如播放、暂停、停止等。 - 控制播放,调用IMediaControl接口的方法启动、停止或暂停播放。 6. **错误处理**:由于DirectShow...

    dm8_setup_win64_ent_8.1.1.45_20191121.iso

    国内最好的数据库达梦DM8,曲奇网盘下载链接:https://quqi.com/s/1243222/wcOZdaWgUlHrwhOk

    基于微信小程序的校园论坛;微信小程序;云开发;云数据库;云储存;云函数;纯JS无后台;全部资料+详细文档+高分项目.zip

    【资源说明】 基于微信小程序的校园论坛;微信小程序;云开发;云数据库;云储存;云函数;纯JS无后台;全部资料+详细文档+高分项目.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

    单电阻采样 基于单电阻采样的相电流重构算法 keil完整工程 单电阻采样 f103的单电阻,完整工程,带文档,带硬件资料 f3平台的单电阻完整工程,代码详细注释 还有微芯的单电阻smo代码加文档

    单电阻采样 基于单电阻采样的相电流重构算法 keil完整工程。 单电阻采样 f103的单电阻,完整工程,带文档,带硬件资料。 f3平台的单电阻完整工程,代码详细注释。 还有微芯的单电阻smo代码加文档 具体如截图请看下

    jQuery左侧导航右侧tab页面切换.zip

    jQuery左侧导航右侧tab页面切换

    数据结构之哈希查找方法

    哈希查找

    五相电机邻近四矢量SVPWM模型-MATLAB-Simulink仿真模型包括: (1)原理说明文档(重要):包括扇区判断、矢量作用时间计算、矢量作用顺序及切时间计算、PWM波的生成; (2)输出部分仿

    五相电机邻近四矢量SVPWM模型_MATLAB_Simulink仿真模型包括: (1)原理说明文档(重要):包括扇区判断、矢量作用时间计算、矢量作用顺序及切时间计算、PWM波的生成; (2)输出部分仿真波形及仿真说明文档; (3)完整版仿真模型:Simulink仿真模型; 注意,只包含五相电机邻近四矢量SVPWM算法,并非五相电机双闭环矢量控制,如果想要五相电机双闭环矢量控制资料,另一个链接。 资料介绍过程十分详细

    法码滋.exe法码滋2.exe法码滋3.exe

    法码滋.exe法码滋2.exe法码滋3.exe

    java毕设项目之教务信息平台的设计与实现+jsp(完整前后端+说明文档+mysql+lw).zip

    项目包含完整前后端源码和数据库文件,均测试可正常运行 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea Maven包:Maven3.3 部署容器:tomcat7

    基于Python+OpenCv的人手分割算法

    算法允许用户在图像上自行划定标签,并对这些区域内的图像进行肤色检测和处理;最后在一个PyQt窗口中显示处理后的三张图片,分别为带标签图片,二值化图片,膨胀后图片。

    浪漫节日代码 - 爱心代码、圣诞树代码

    内容概要: 本资料包含了一系列用于庆祝浪漫节日的创意代码,主要包括爱心代码和圣诞树代码。这些代码可以生成视觉上吸引人的图案和动画,用于在屏幕上展示爱心和圣诞树,增加节日气氛。爱心代码可以用于表达爱意,而圣诞树代码则适合在圣诞节期间使用,为用户带来节日的欢乐和视觉享受。 适用人群: 本资料适用于以下人群: 程序员和开发者,他们希望在项目中添加节日元素或为特别场合创造个性化的视觉效果。 网页设计师,他们需要为网站或应用程序添加节日主题的装饰。 技术爱好者和DIY爱好者,他们喜欢通过编程来庆祝节日或为朋友和家人制作特别的礼物。 实现:可直接运行python程序。

    疫情隔离管理-JAVA-基于springboot + vue的疫情隔离管理系统设计与实现(毕业论文)

    1. 患者信息与隔离状态管理 患者基本信息录入:对于疑似、确诊或密切接触者患者,系统记录其基本信息,包括姓名、年龄、性别、联系方式、住址等。 疫情风险评估:通过问卷或医务人员评估,系统对患者进行风险评估,判断是否需要隔离、隔离的级别(如轻症、中症、重症等)。 隔离状态管理:记录患者的隔离状态(如隔离中、已解除隔离、转入ICU等),并能够实时更新隔离状态变化。 隔离病房分配:根据患者的病情、感染风险和病房资源,系统自动分配适当的隔离病房或床位,避免交叉感染。 2. 隔离病房与环境管理 病房信息管理:系统对每个隔离病房进行实时监控,包括病房的床位使用情况、设备设施、清洁消毒状况等,确保每个病房的隔离效果。 空气流通与环境消毒管理:记录隔离病房的空气流通情况、消毒记录、物品消耗等,确保符合疫情防控要求。 设备与物资分配:针对隔离病房的特殊需求,系统可以自动化管理医疗设备(如氧气、呼吸机等)与防护物资(如口罩、手套、防护服等)的分配与库存管理。 3. 医护人员防护与工作管理 医护人员排班与防护管理:为隔离病房的医护人员进行特殊排班,避免交叉感染,并根据需要分配适当的防护装备,如全身防护服、N9

    富芮坤FR8003作为主机连接FR8003抓包文件20241223-135206.pcapng

    适配文章:https://editor.csdn.net/md?not_checkout=1&spm=1011.2415.3001.6217&articleId=144663667 富芮坤FR8003作为主机连接FR8003二:官方代码主从的UUID和att_idx

    德普微一级代理 DP3145D SOT23-6 USB PD 协议单口控制器

    内容概要:文章介绍了USB PD协议单口控制器DP3145D的技术特点、主要功能和应用场景。DP3145D支持USB Type-C和USB Power Delivery(PD)3.1协议,具备多种配置选项,最高输出功率45W。它集成了CV环路光耦驱动电路、反馈网络电阻以及多项保护措施,适用于ACDC适配器等USB充电设备。 适合人群:电子工程师、电源产品设计师和技术研究人员。 使用场景及目标:主要用于设计和开发支持USB PD协议的ACDC适配器和充电设备,实现高效、安全的充电解决方案。 阅读建议:重点关注DP3145D的具体技术参数、功能特点和典型应用实例,结合自身需求进行产品选型和设计。

    VBA视频教程 0005

    VBA视频教程 05

    基于Spring Boot框架的网上蛋糕销售系统_30z8r428_231-wx.zip

    基于Spring Boot框架的网上蛋糕销售系统_30z8r428_231-wx.zip

    simulink线性马达H-infinity控制

    matlab

    蜡笔小新-去掉动效.zip

    蜡笔小新-去掉动效.zip

Global site tag (gtag.js) - Google Analytics