java代碼實現(xiàn)電子簽名,函數(shù)簽名java

基于java語言的數(shù)字簽名

Java加密和數(shù)字簽名編程快速入門

成都創(chuàng)新互聯(lián)公司擁有十余年成都網(wǎng)站建設(shè)工作經(jīng)驗,為各大企業(yè)提供成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計服務(wù),對于網(wǎng)頁設(shè)計、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、app開發(fā)定制、wap網(wǎng)站建設(shè)(手機版網(wǎng)站建設(shè))、程序開發(fā)、網(wǎng)站優(yōu)化(SEO優(yōu)化)、微網(wǎng)站、域名與空間等,憑借多年來在互聯(lián)網(wǎng)的打拼,我們在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了很多網(wǎng)站制作、網(wǎng)站設(shè)計、網(wǎng)絡(luò)營銷經(jīng)驗,集策劃、開發(fā)、設(shè)計、營銷、管理等網(wǎng)站化運作于一體,具備承接各種規(guī)模類型的網(wǎng)站建設(shè)項目的能力。

本文主要談一下密碼學(xué)中的加密和數(shù)字簽名,以及其在java中如何進行使用。對密碼學(xué)有興趣的伙伴,推薦看Bruce Schneier的著作:Applied Crypotography。在jdk1.5的發(fā)行版本中安全性方面有了很大的改進,也提供了對RSA算法的直接支持,現(xiàn)在我們從實例入手解決問題(本文僅是作為簡單介紹):

一、密碼學(xué)上常用的概念

1)消息摘要:

這是一種與消息認證碼結(jié)合使用以確保消息完整性的技術(shù)。主要使用單向散列函數(shù)算法,可用于檢驗消息的完整性,和通過散列密碼直接以文本形式保存等,目前廣泛使用的算法有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("\n"+messageDigest.getProvider().getInfo());

//開始使用算法

messageDigest.update(plainText);

System.out.println("\nDigest:");

//輸出算法運算結(jié)果

System.out.println(new String(messageDigest.digest(),"UTF8"));

}

}

還可以通過消息認證碼來進行加密實現(xiàn),javax.crypto.Mac提供了一個解決方案,有興趣者可以參考相關(guān)API文檔,本文只是簡單介紹什么是摘要算法。

2)私鑰加密:

消息摘要只能檢查消息的完整性,但是單向的,對明文消息并不能加密,要加密明文的消息的話,就要使用其他的算法,要確保機密性,我們需要使用私鑰密碼術(shù)來交換私有消息。

這種最好理解,使用對稱算法。比如:A用一個密鑰對一個文件加密,而B讀取這個文件的話,則需要和A一樣的密鑰,雙方共享一個私鑰(而在web環(huán)境下,私鑰在傳遞時容易被偵聽):

使用私鑰加密的話,首先需要一個密鑰,可用javax.crypto.KeyGenerator產(chǎn)生一個密鑰(java.security.Key),然后傳遞給一個加密工具(javax.crypto.Cipher),該工具再使用相應(yīng)的算法來進行加密,主要對稱算法有: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 text");

System.exit(1);

}

byte[] plainText=args[0].getBytes("UTF8");

//通過KeyGenerator形成一個key

System.out.println("\nStart 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("\n"+cipher.getProvider().getInfo());

//使用私鈅加密

System.out.println("\nStart 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("\nStart 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環(huán)境下,直接傳遞的話很容易被偵聽到,幸好有了公鑰加密的出現(xiàn)。公鑰加密也叫不對稱加密,不對稱算法使用一對密鑰對,一個公鑰,一個私鑰,使用公鑰加密的數(shù)據(jù),只有私鑰能解開(可用于加密);同時,使用私鑰加密的數(shù)據(jù),只有公鑰能解開(簽名)。但是速度很慢(比私鑰加密慢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 text");

System.exit(1);

}

byte[] plainText=args[0].getBytes("UTF8");

//構(gòu)成一個RSA密鑰

System.out.println("\nStart 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("\n"+cipher.getProvider().getInfo());

System.out.println("\nStart 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("\nStart 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)數(shù)字簽名:

數(shù)字簽名,它是確定交換消息的通信方身份的第一個級別。上面A通過使用公鑰加密數(shù)據(jù)后發(fā)給B,B利用私鑰解密就得到了需要的數(shù)據(jù),問題來了,由于都是使用公鑰加密,那么如何檢驗是A發(fā)過來的消息呢?上面也提到了一點,私鑰是唯一的,那么A就可以利用A自己的私鑰進行加密,然后B再利用A的公鑰來解密,就可以了;數(shù)字簽名的原理就基于此,而通常為了證明發(fā)送數(shù)據(jù)的真實性,通過利用消息摘要獲得簡短的消息內(nèi)容,然后再利用私鑰進行加密散列數(shù)據(jù)和消息一起發(fā)送。java中為數(shù)字簽名提供了良好的支持,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;

/**

*數(shù)字簽名,使用RSA私鑰對對消息摘要簽名,然后使用公鈅驗證 測試

*/

public class DigitalSignature2Example{

public static void main(String[] args) throws Exception{

if(args.length!=1){

System.err.println("Usage:java DigitalSignature2Example text");

System.exit(1);

}

byte[] plainText=args[0].getBytes("UTF8");

//形成RSA公鑰對

System.out.println("\nStart 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("\nSignature:");

System.out.println(new String(signature,"UTF8"));

//使用公鈅驗證

System.out.println("\nStart 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)數(shù)字證書。

還有個問題,就是公鑰問題,A用私鑰加密了,那么B接受到消息后,用A提供的公鑰解密;那么現(xiàn)在有個討厭的C,他把消息攔截了,然后用自己的私鑰加密,同時把自己的公鑰發(fā)給B,并告訴B,那是A的公鑰,結(jié)果....,這時候就需要一個中間機構(gòu)出來說話了(相信權(quán)威,我是正確的),就出現(xiàn)了Certificate Authority(也即CA),有名的CA機構(gòu)有Verisign等,目前數(shù)字認證的工業(yè)標(biāo)準(zhǔn)是:CCITT的X.509:

數(shù)字證書:它將一個身份標(biāo)識連同公鑰一起進行封裝,并由稱為認證中心或 CA 的第三方進行數(shù)字簽名。

密鑰庫:java平臺為你提供了密鑰庫,用作密鑰和證書的資源庫。從物理上講,密鑰庫是缺省名稱為 .keystore 的文件(有一個選項使它成為加密文件)。密鑰和證書可以擁有名稱(稱為別名),每個別名都由唯一的密碼保護。密鑰庫本身也受密碼保護;您可以選擇讓每個別名密碼與主密鑰庫密碼匹配。

使用工具keytool,我們來做一件自我認證的事情吧(相信我的認證):

1、創(chuàng)建密鑰庫keytool -genkey -v -alias feiUserKey -keyalg RSA 默認在自己的home目錄下(windows系統(tǒng)是c:\documents and settings\你的用戶名 目錄下的.keystore文件),創(chuàng)建我們用 RSA 算法生成別名為 feiUserKey 的自簽名的證書,如果使用了-keystore mm 就在當(dāng)前目錄下創(chuàng)建一個密鑰庫mm文件來保存密鑰和證書。

2、查看證書:keytool -list 列舉了密鑰庫的所有的證書

也可以在dos下輸入keytool -help查看幫助。

java如何對pdf文件實現(xiàn)數(shù)字簽名

用Spire.Doc? for Java 可以添加及驗證數(shù)字簽名,參考代碼:

import?com.spire.pdf.*;

import?com.spire.pdf.graphics.PdfImage;

import?com.spire.pdf.graphics.PdfTrueTypeFont;

import?com.spire.pdf.security.GraphicMode;

import?com.spire.pdf.security.PdfCertificate;

import?com.spire.pdf.security.PdfCertificationFlags;

import?com.spire.pdf.security.PdfSignature;

import?java.awt.*;

import?java.awt.geom.Point2D;

import?java.awt.geom.Rectangle2D;

public?class?AddCertificate?{

public?static?void?main(String[]args){

//加載PDF文檔

PdfDocument?doc?=?new?PdfDocument();

doc.loadFromFile("test.pdf");

//加載pfx證書,及證書秘鑰

PdfCertificate?cert?=?new?PdfCertificate("Cermia.pfx","123654yes!");

//添加數(shù)字簽名到指定頁面,并設(shè)置其位置和大小

PdfSignature?signature?=?new?PdfSignature(doc,?doc.getPages().get(2),?cert,?"MySignature");

Rectangle2D?rect?=?new?Rectangle2D.Float();

rect.setFrame(new?Point2D.Float((float)?doc.getPages().get(0).getActualSize().getWidth()?-?340,?(float)?doc.getPages().get(0).getActualSize().getHeight()?-?230),?new?Dimension(280,?150));

signature.setBounds(rect);

//設(shè)置簽名為圖片加文本模式

signature.setGraphicMode(GraphicMode.Sign_Image_And_Sign_Detail);

//設(shè)置簽名的內(nèi)容

signature.setNameLabel("簽字者:");

signature.setName("Mia");

signature.setContactInfoLabel("聯(lián)系電話:");

signature.setContactInfo("02881705109");

signature.setDateLabel("日期:");

signature.setDate(new?java.util.Date());

signature.setLocationInfoLabel("地點:");

signature.setLocationInfo("成都");

signature.setReasonLabel("原因:");

signature.setReason("文檔所有者");

signature.setDistinguishedNameLabel("DN:?");

signature.setDistinguishedName(signature.getCertificate().get_IssuerName().getName());

signature.setSignImageSource(PdfImage.fromFile("sign.png"));

//設(shè)置簽名的字體

signature.setSignDetailsFont(new?PdfTrueTypeFont(new?Font("Arial?Unicode?MS",?Font.PLAIN,?9)));

//設(shè)置文檔權(quán)限為禁止更改

signature.setDocumentPermissions(PdfCertificationFlags.Forbid_Changes);

signature.setCertificated(true);

//保存文檔

doc.saveToFile("AddSignature.pdf");

doc.close();

}

}

數(shù)字簽名添加效果:

數(shù)字簽名效果

參考原文

編寫一個Java程序,對指定文本進行數(shù)字簽名(文本隨意舉例)

一:需要包含的包

import java.security.*;

import java.io.*;

import java.util.*;

import java.security.*;

import java.security.cert.*;

import sun.security.x509.*

import java.security.cert.Certificate;

import java.security.cert.CertificateFactory;

二:從文件中讀取證書

用keytool將.keystore中的證書寫入文件中,然后從該文件中讀取證書信息

CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in=new FileInputStream("out.csr");

Certificate c=cf.generateCertificate(in);

String s=c.toString();

三:從密鑰庫中直接讀取證書

String pass="123456";

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,pass.toCharArray());

java.security.cert.Certificate c=ks.getCertificate(alias);//alias為條目的別名

四:JAVA程序中顯示證書指定信息

System.out.println("輸出證書信息:\n"+c.toString());

System.out.println("版本號:"+t.getVersion());

System.out.println("序列號:"+t.getSerialNumber().toString(16));

System.out.println("主體名:"+t.getSubjectDN());

System.out.println("簽發(fā)者:"+t.getIssuerDN());

System.out.println("有效期:"+t.getNotBefore());

System.out.println("簽名算法:"+t.getSigAlgName());

byte [] sig=t.getSignature();//簽名值

PublicKey pk=t.getPublicKey();

byte [] pkenc=pk.getEncoded();

System.out.println("公鑰");

for(int i=0;ipkenc.length;i++)System.out.print(pkenc[i]+",");

五:JAVA程序列出密鑰庫所有條目

String pass="123456";

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,pass.toCharArray());

Enumeration e=ks.aliases();

while(e.hasMoreElements())

java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());

六:JAVA程序修改密鑰庫口令

String oldpass="123456";

String newpass="654321";

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,oldpass.toCharArray());

in.close();

FileOutputStream output=new FileOutputStream(".keystore");

ks.store(output,newpass.toCharArray());

output.close();

七:JAVA程序修改密鑰庫條目的口令及添加條目

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,storepass.toCharArray());

Certificate [] cchain=ks.getCertificate(alias);獲取別名對應(yīng)條目的證書鏈

PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());獲取別名對應(yīng)條目的私鑰

ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密鑰庫中添加條目

第一個參數(shù)指定所添加條目的別名,假如使用已存在別名將覆蓋已存在條目,使用新別名將增加一個新條目,第二個參數(shù)為條目的私鑰,第三個為設(shè)置的新口令,第四個為該私鑰的公鑰的證書鏈

FileOutputStream output=new FileOutputStream("another");

ks.store(output,storepass.toCharArray())將keystore對象內(nèi)容寫入新文件

八:JAVA程序檢驗別名和刪除條目

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,storepass.toCharArray());

ks.containsAlias("sage");檢驗條目是否在密鑰庫中,存在返回true

ks.deleteEntry("sage");刪除別名對應(yīng)的條目

FileOutputStream output=new FileOutputStream(".keystore");

ks.store(output,storepass.toCharArray())將keystore對象內(nèi)容寫入文件,條目刪除成功

九:JAVA程序簽發(fā)數(shù)字證書

(1)從密鑰庫中讀取CA的證書

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,storepass.toCharArray());

java.security.cert.Certificate c1=ks.getCertificate("caroot");

(2)從密鑰庫中讀取CA的私鑰

PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());

(3)從CA的證書中提取簽發(fā)者的信息

byte[] encod1=c1.getEncoded(); 提取CA證書的編碼

X509CertImpl cimp1=new X509CertImpl(encod1); 用該編碼創(chuàng)建X509CertImpl類型對象

X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 獲取X509CertInfo對象

X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 獲取X509Name類型的簽發(fā)者信息

(4)獲取待簽發(fā)的證書

CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in2=new FileInputStream("user.csr");

java.security.cert.Certificate c2=cf.generateCertificate(in);

(5)從待簽發(fā)的證書中提取證書信息

byte [] encod2=c2.getEncoded();

X509CertImpl cimp2=new X509CertImpl(encod2); 用該編碼創(chuàng)建X509CertImpl類型對象

X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 獲取X509CertInfo對象

(6)設(shè)置新證書有效期

Date begindate=new Date(); 獲取當(dāng)前時間

Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期為3000天

CertificateValidity cv=new CertificateValidity(begindate,enddate); 創(chuàng)建對象

cinfo2.set(X509CertInfo.VALIDITY,cv); 設(shè)置有效期

(7)設(shè)置新證書序列號

int sn=(int)(begindate.getTime()/1000); 以當(dāng)前時間為序列號

CertificateSerialNumber csn=new CertificateSerialNumber(sn);

cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);

(8)設(shè)置新證書簽發(fā)者

cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);應(yīng)用第三步的結(jié)果

(9)設(shè)置新證書簽名算法信息

AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);

cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);

(10)創(chuàng)建證書并使用CA的私鑰對其簽名

X509CertImpl newcert=new X509CertImpl(cinfo2);

newcert.sign(caprk,"MD5WithRSA"); 使用CA私鑰對其簽名

(11)將新證書寫入密鑰庫

ks.setCertificateEntry("lf_signed",newcert);

FileOutputStream out=new FileOutputStream("newstore");

ks.store(out,"newpass".toCharArray()); 這里是寫入了新的密鑰庫,也可以使用第七條來增加條目

十:數(shù)字證書的檢驗

(1)驗證證書的有效期

(a)獲取X509Certificate類型對象

CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in1=new FileInputStream("aa.crt");

java.security.cert.Certificate c1=cf.generateCertificate(in1);

X509Certificate t=(X509Certificate)c1;

in2.close();

(b)獲取日期

Date TimeNow=new Date();

(c)檢驗有效性

try{

t.checkValidity(TimeNow);

System.out.println("OK");

}catch(CertificateExpiredException e){ //過期

System.out.println("Expired");

System.out.println(e.getMessage());

}catch((CertificateNotYetValidException e){ //尚未生效

System.out.println("Too early");

System.out.println(e.getMessage());}

(2)驗證證書簽名的有效性

(a)獲取CA證書

CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in2=new FileInputStream("caroot.crt");

java.security.cert.Certificate cac=cf.generateCertificate(in2);

in2.close();

(c)獲取CA的公鑰

PublicKey pbk=cac.getPublicKey();

(b)獲取待檢驗的證書(上步已經(jīng)獲取了,就是C1)

(c)檢驗證書

boolean pass=false;

try{

c1.verify(pbk);

pass=true;

}catch(Exception e){

pass=false;

System.out.println(e);

}

電子簽名用Java怎么實現(xiàn)

import?java.security.InvalidKeyException;

import?java.security.Key;

import?java.security.KeyPair;

import?java.security.KeyPairGenerator;

import?java.security.NoSuchAlgorithmException;

import?java.security.PrivateKey;

import?java.security.PublicKey;

import?java.security.SecureRandom;

import?java.security.Signature;

import?java.security.SignatureException;

import?java.util.logging.Level;

import?java.util.logging.Logger;

/**

*?ECDSA?160bit?簽名及簽名驗證例子

*/

public?class?ECDSASignature?{

public?static?void?main(String?argv[])?{

signatureTest();

}

public?static?void?signatureTest()?{

/**

*?密鑰對生成

*/

KeyPairGenerator?keyPairGenerator?=?null;

try?{

keyPairGenerator?=?KeyPairGenerator.getInstance("EC");

}?catch?(NoSuchAlgorithmException?ex)?{

return;

}

SecureRandom?secureRandom?=?new?SecureRandom();

keyPairGenerator.initialize(160,?secureRandom);

KeyPair?pair?=?keyPairGenerator.generateKeyPair();

Key?publicKey?=?pair.getPublic();

Key?privateKey?=?pair.getPrivate();

//?字符串

String?hako?=?"test";

/**

*?私鑰簽名(ECDSA?160bit)

*/

byte[]?sign?=?null;

try?{

Signature?signatureSign?=?null;

signatureSign?=?Signature.getInstance("NONEwithECDSA");

signatureSign.initSign((PrivateKey)?privateKey,?secureRandom);

signatureSign.update(hako.getBytes());

sign?=?signatureSign.sign();

System.out.println("sign:?"?+?new?String(sign));

}?catch?(InvalidKeyException?|?NoSuchAlgorithmException?|?SignatureException?ex)?{

Logger.getLogger(ECDSASignature.class.getName()).log(Level.SEVERE,?null,?ex);

}

/**

*?用公鑰進行簽名驗證

*/

Signature?signatureVerify?=?null;

try?{

signatureVerify?=?Signature.getInstance("NONEwithECDSA");

signatureVerify.initVerify((PublicKey)?publicKey);

signatureVerify.update(hako.getBytes());

boolean?verifyResult?=?signatureVerify.verify(sign);

System.out.println(verifyResult???"簽名OK"?:?"簽名NG");

}?catch?(NoSuchAlgorithmException?|?InvalidKeyException?|?SignatureException?e)?{

Logger.getLogger(ECDSASignature.class.getName()).log(Level.SEVERE,?null,?e);

}

}

}

如何從java生成簽名在AWS問題,怎么解決

Java2下Applet數(shù)字簽名實現(xiàn)過程如下:

在代碼的分發(fā)端:

(1)開發(fā)Java源程序并對其進行編譯。

(2)用JAR工具對類文件和資源文件進行封裝。

(3)用keytool創(chuàng)建公鑰和密鑰,生成X。509V1簽名證書,輸出證書。

(4)通過jarsigner工具用生成的密鑰對JAR文件進行數(shù)字簽名。

在代碼的接收端:

(1)用keytool輸入證書視其為可信任。

(2)用policytool創(chuàng)建和修改安全性策略配置文件,授權(quán)請求的訪問權(quán)限。

(3)從網(wǎng)絡(luò)取得字節(jié)碼,用公鑰驗證數(shù)字簽名證書和文檔代碼的完整性。

(4)驗證字節(jié)碼的合法性,根據(jù)策略文件分配相應(yīng)權(quán)限。

(5)執(zhí)行代碼,完成后被垃圾回收器回收內(nèi)存。

在用公鑰驗證數(shù)字簽名證書之前,接收方需要確認公鑰自身的可靠性,因此通常情況是提供一個包含公鑰的證書而不是公鑰自身。1個證書包括:

(1)1個公鑰。

(2)1個唯一的名字實體(個人或公司),它是證書的所有者,包含用戶名字、公司、組織、城市、地址、國家代碼、省份等信息。

(3)數(shù)字簽名:1個證書被1個分發(fā)者的實體簽名,保證證書確實包含另1個實體(所有者)的公鑰。

Java2下Applet數(shù)字簽名實現(xiàn)方法

Java2下Applet數(shù)字簽名具體實現(xiàn)方法我的項目是使用APPLET制作一個實時消息隊列監(jiān)控程序,由于涉及到了本地資源,對APPLET一定要進行數(shù)字簽名和認證。我使用的環(huán)境是WINDOWS2000,應(yīng)用服務(wù)器是WEBLOGIC6.0,開發(fā)環(huán)境是JBUILDER4.0。之前我提醒大家一定要注意服務(wù)器端和客戶端的概念。那些文件應(yīng)該在服務(wù)器端,那些文件應(yīng)該在客戶端。

首先在客戶端使用JRE1.3.0_01(JAVA運行環(huán)境1.3.0.1版本)以取代IE的JVM(JAVA虛擬機),可以到網(wǎng)站上去下載,下載好了先在客戶端安裝好,安裝過程非常簡單。

在服務(wù)器端的調(diào)用APPLET的HTML文件中也需要將它包含進來,以便沒有事先安裝JRE的客戶端下載,具體的寫法,請接著往下看;

具體步驟如下:

服務(wù)器端:

1.將程序需要用到的各種包文件全部解壓(我這兒要用到WEBLOGIC的JMS包使用命令jar xf weblogicc.jar),然后使用JDK的打包命令將編譯好的監(jiān)控程序.class和剛才解壓的包一起打包到一個包中。(前提我已經(jīng)將監(jiān)控程序和解開的包都放在同一個目錄下了),都是dos狀態(tài)下的命令,具體命令見jdk1.3(1.2)的bin目錄下,

命令如下:

jar cvf monitor.jar *.class

此命令生成一個名為monitor.jar的包

2.為剛才創(chuàng)建的包文件(monitor.jar)創(chuàng)建keystore和keys。其中,keystore將用來存放密匙(private keys)和公共鑰匙的認證,alias別名這兒取為monitor。

命令如下:

keytool -genkey -keystore monitor.keystore –alias monitor

此命令生成了一個名為monitor.keystore的keystore文件,接著這條命令,系統(tǒng)會問你好多問題,比如你的公司名稱,你的地址,你要設(shè)定的密碼等等,都由自己的隨便寫。

3.使用剛才生成的鑰匙來對jar文件進行簽名

命令如下:

jarsigner -keystore monitor.keystore monitor.jar monitor

這個命令將對monitor.jar文件進行簽名,不會生成新文件。

4.將公共鑰匙導(dǎo)入到一個cer文件中,這個cer文件就是要拷貝到客戶端的唯一文件 。

命令如下:

keytool -export -keystore monitor.keystore -alias monitor -file monitor.cer

此條命令將生成monitor.cer認證文件,當(dāng)然這幾步都有可能問你剛才設(shè)置的密碼。這樣就完成了服務(wù)器端的設(shè)置。這時你就可以將jar文件和keystore文件以及cer文件(我這兒是monitor.jar,monitor.keystore,monitor.cer)拷貝到服務(wù)器的目錄下了,我用的是weblogic6.0,所以就拷貝到C:\bea\wlserver6.0\config\mydomain\applications\DefaultWebApp_myserver下的自己建的一個目錄下了。

客戶端:

1. 首先應(yīng)該安裝jre1.3.0_01,然后將服務(wù)器端生成的monitor.cer 文件拷貝到j(luò)re的特定目錄下,我這兒是:

c:\program files\javasoft\jre\1.3.0_01\lib\security目錄下。

2. 將公共鑰匙倒入到j(luò)re的cacerts(這是jre的默認keystore)

命令如下:

keytool -import -alias monitor -file monitor.cer

-keystore cacerts

注意這兒要你輸入的是cacerts的密碼,應(yīng)該是changeit,而不是你自己設(shè)定的keystore的密碼。

3. 修改policy策略文件,在dos狀態(tài)下使用命令 policytool

系統(tǒng)會自動彈出一個policytool的對話框,如圖4所示,在這里面首先選擇file菜單的open項,打開c:\program files\javasoft\jre\1.3.0_01\lib\security目錄下的java.poliy文件,然后在edit菜單中選擇Change keystore ,在對話框中new keystore url:中輸入

file:/c:/program files /javasoft/jre/1.3.0_01/lib/security/cacerts, 這兒要注意反斜杠,在new keystore type 中輸入JKS,這是cacerts的固定格式,然后單擊Add Policy Entry,在出現(xiàn)的對話框中CodeBase中輸入:

*

其中的URL是服務(wù)器的IP地址,7001是我的weblogic的端口,如果你是在別的應(yīng)用服務(wù)器上比如說是apache,那端口號就可以省略掉。

在SignedBy中輸入(別名alias):這兒是Monitor然后單擊add peimission按鈕,在出現(xiàn)的對話框中permission中選擇你想給這個applet的權(quán)限,這兒具體有許多權(quán)限,讀者可以自己找資料看看。我這兒就選用allpeimission,右邊的signedBy中輸入別名:monitor

最后保存,在file菜單的save項。

當(dāng)然你可以看見我已經(jīng)對多個包實現(xiàn)了簽名認證。

這樣客戶端的設(shè)置就完成了。在客戶端用ie運行該applet程序時,會詢問你是不是對該簽名授權(quán),選擇授權(quán)后,包會自動從服務(wù)器下載到本地計算機,而且ie會自動啟動jre,在右下欄中可以看見,相當(dāng)于ie的java控制臺。

4.調(diào)用applet的html文件

大家都知道由于java2的安全性,對applet的正常調(diào)用的html文件已經(jīng)不能再使用了,而改為ActiveX類型的調(diào)用。具體的又分ie和nescape的不同寫法,這一些在sun網(wǎng)上都能找到現(xiàn)成的教程。我就不多說了,只是將我的這個小程序為ie寫的的html給大家看看。

<html>

<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=gb2312">

<center>

<h3>消息中心實時監(jiān)控平臺</h3>

<hr>

<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"

width="900" height="520" align="baseline" codebase="">

<PARAM NAME="java_code" VALUE="wise.monitor.applet.monitorApplet">

<PARAM NAME="java_codebase" VALUE="monitor/classes">

<PARAM NAME="java_type" VALUE="application/x-java-applet;version=1.3">

<PARAM NAME="ARCHIVE" VALUE="monitor.jar" >

<PARAM NAME="scriptable" VALUE="true">

</OBJECT>

</center>

</html>

其中我要強調(diào)一點,因為applet每一次的改動都需要重新打包簽名,手續(xù)非常繁瑣,所以在具體的實現(xiàn)中要將一些會變化參數(shù)放到html文件中來,傳到applet中去,這一點網(wǎng)上文章好多,自己去看吧。

另外一個就是有朋友問我,那這樣不是太麻煩了,每一個客戶端都要進行復(fù)雜的dos命令操作,我只能說一目前我的水平只能將一個已經(jīng)做好的客戶端文件cer文件和java.policy以及cacerts文件直接拷貝到客戶端,當(dāng)然這也有缺陷,如果別人的計算機已經(jīng)有了認證,就會丟失。就這些問題我們可以一起探討。

另外還有一點優(yōu)化,就是在打包的時候,我這兒只講了把所有要用的涉及到安全性的包和源程序到要打到一個包中。這樣如果包非常大的話,會非常影響下載的速度,如果可以使用本地計算機的包就好了,這一點jre也做到了,具體的要到控制面板的jre控制臺上去設(shè)置。這個就留著讀者自己去摸索吧。

結(jié)束語

我發(fā)現(xiàn)網(wǎng)上java相關(guān)的資料非常少,中文的更少,所以希望自己能將一些小知識和大家共享,省掉許多重復(fù)的無用功。如果大家對這個問題還有不清楚的地方,或者就這問題相進一步展開討論的,請和我聯(lián)系,我的信箱是afeilb@163.net。希望我們能共同進步!

名稱欄目:java代碼實現(xiàn)電子簽名,函數(shù)簽名java
本文網(wǎng)址:http://muchs.cn/article10/hcpigo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)站排名、外貿(mào)網(wǎng)站建設(shè)、建站公司、響應(yīng)式網(wǎng)站、ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站