日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java实现签名和解签

發(fā)布時(shí)間:2023/12/9 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java实现签名和解签 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
  • 文章出至 ?http://blog.csdn.net/lll350203041/article/details/41482017
  • ?
  • 學(xué)習(xí)網(wǎng)址:
  • ?

    http://www.ibm.com/developerworks/cn/java/l-security/

  • 1.簽名:
  • ?

    ? ??用他私人密鑰 (prikey) 對(duì)他所確認(rèn)的信息 (info) 進(jìn)行數(shù)字簽名產(chǎn)生一個(gè)簽名數(shù)組
    從文件中讀入私人密鑰 (prikey)
    java.io.ObjectInputStream in=new java.io.ObjectInputStream(
    ? ? new java.io.FileInputStream("myprikey.dat"));?
    PrivateKey myprikey=(PrivateKey)in.readObject();?
    in.close();?
    初始一個(gè) Signature 對(duì)象 , 并用私鑰對(duì)信息簽名
    java.security.Signature signet=java.security.Signature.getInstance("DSA");?
    signet.initSign(myprikey);?
    signet.update(myinfo.getBytes());?
    byte[] signed=signet.sign();?


    把信息和簽名保存在一個(gè)文件中 (myinfo.dat)?
    java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(
    ? ? new java.io.FileOutputStream("myinfo.dat"));?
    out.writeObject(myinfo);?
    out.writeObject(signed);?
    out.close();?
    把他的公鑰的信息及簽名發(fā)給其它用戶
    ?

    2. 使用公鑰驗(yàn)證簽名是否正確:

    其他用戶用他的公共密鑰 (pubkey) 和簽名 (signed) 和信息 (info) 進(jìn)行驗(yàn)證是否由他簽名的信息

    讀入公鑰?
    java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));?
    PublicKey pubkey=(PublicKey)in.readObject();?
    in.close();

    讀入簽名和信息?
    in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));?
    String info=(String)in.readObject();?
    byte[] signed=(byte[])in.readObject();?
    in.close();

    初始一個(gè) Signature 對(duì)象 , 并用公鑰和簽名進(jìn)行驗(yàn)證?
    java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");?
    signetcheck.initVerify(pubkey);?
    signetcheck.update(info.getBytes());?
    if (signetcheck.verify(signed)) { System.out.println("簽名正常");}

    // 使用公鑰將signed進(jìn)行解簽,然后與info比較是否相等,相等則簽名正確。即保證是指定人發(fā)送,也保證信息傳輸中沒有被修改。如果被修改,那么修改后的info肯定與解簽后的值不相等,驗(yàn)證簽名失敗。

    對(duì)于密鑰的保存本文是用對(duì)象流的方式保存和傳送的 , 也可可以用編碼的方式保存 . 注意要?
    import java.security.spec.*?
    import java.security.*

    =以下為學(xué)習(xí)網(wǎng)址中的內(nèi)容==========================================================================

    ?

    第 1 章基礎(chǔ)知識(shí)

    1.1. 單鑰密碼體制

    ?

    單鑰密碼體制是一種傳統(tǒng)的加密算法,是指信息的發(fā)送方和接收方共同使用同一把密鑰進(jìn)行加解密。

    通常 , 使用的加密算法 比較簡(jiǎn)便高效 , 密鑰簡(jiǎn)短,加解密速度快,破譯極其困難。但是加密的安全性依靠密鑰保管的安全性 , 在公開的計(jì)算機(jī)網(wǎng)絡(luò)上安全地傳送和保管密鑰是一個(gè)嚴(yán)峻的問題,并且如果在多用戶的情況下密鑰的保管安全性也是一個(gè)問題。

    單鑰密碼體制的代表是美國(guó)的 DES

    1.2. 消息摘要

    一個(gè)消息摘要就是一個(gè)數(shù)據(jù)塊的數(shù)字指紋。即對(duì)一個(gè)任意長(zhǎng)度的一個(gè)數(shù)據(jù)塊進(jìn)行計(jì)算,產(chǎn)生一個(gè)唯一指印(對(duì)于 SHA1 是產(chǎn)生一個(gè) 20 字節(jié)的二進(jìn)制數(shù)組)。

    消息摘要有兩個(gè)基本屬性:

    • 兩個(gè)不同的報(bào)文難以生成相同的摘要
    • 難以對(duì)指定的摘要生成一個(gè)報(bào)文,而由該報(bào)文反推算出該指定的摘要

    代表:美國(guó)國(guó)家標(biāo)準(zhǔn)技術(shù)研究所的 SHA1 和麻省理工學(xué)院 Ronald Rivest 提出的 MD5

    1.3. Diffie-Hellman 密鑰一致協(xié)議

    密鑰一致協(xié)議是由公開密鑰密碼體制的奠基人 Diffie 和 Hellman 所提出的一種思想。

    先決條件 , 允許兩名用戶在公開媒體上交換信息以生成"一致"的 , 可以共享的密鑰

    代表:指數(shù)密鑰一致協(xié)議 (Exponential Key Agreement Protocol)

    1.4. 非對(duì)稱算法與公鑰體系

    1976 年,Dittie 和 Hellman 為解決密鑰管理問題,在他們的奠基性的工作"密碼學(xué)的新方向"一文中,提出一種密鑰交換協(xié)議,允許在不安全的媒體上通過通訊雙方交換信息,安全地傳送秘密密鑰。在此新思想的基礎(chǔ)上,很快出現(xiàn)了非對(duì)稱密鑰密碼體制,即公鑰密碼體制。在公鑰體制中,加密密鑰不同于解密密鑰,加密密鑰公之于眾,誰都可以使用;解密密鑰只有解密人自己知道。它們分別稱為公開密鑰(Public key)和秘密密鑰(Private key)。

    迄今為止的所有公鑰密碼體系中,RSA 系統(tǒng)是最著名、最多使用的一種。RSA 公開密鑰密碼系統(tǒng)是由 R.Rivest、A.Shamir 和 L.Adleman 俊教授于 1977 年提出的。RSA 的取名就是來自于這三位發(fā)明者的姓的第一個(gè)字母

    1.5. 數(shù)字簽名

    所謂數(shù)字簽名就是信息發(fā)送者用其私鑰對(duì)從所傳報(bào)文中提取出的特征數(shù)據(jù)(或稱數(shù)字指紋)進(jìn)行 RSA 算法操作,以保證發(fā)信人無法抵賴曾發(fā)過該信息(即不可抵賴性),同時(shí)也確保信息報(bào)文在經(jīng)簽名后末被篡改(即完整性)。當(dāng)信息接收者收到報(bào)文后,就可以用發(fā)送者的公鑰對(duì)數(shù)字簽名進(jìn)行驗(yàn)證。 

    在數(shù)字簽名中有重要作用的數(shù)字指紋是通過一類特殊的散列函數(shù)(HASH 函數(shù))生成的,對(duì)這些 HASH 函數(shù)的特殊要求是:

  • 接受的輸入報(bào)文數(shù)據(jù)沒有長(zhǎng)度限制;
  • 對(duì)任何輸入報(bào)文數(shù)據(jù)生成固定長(zhǎng)度的摘要(數(shù)字指紋)輸出
  • 從報(bào)文能方便地算出摘要;
  • 難以對(duì)指定的摘要生成一個(gè)報(bào)文,而由該報(bào)文反推算出該指定的摘要;
  • 兩個(gè)不同的報(bào)文難以生成相同的摘要
  • 代表:DSA

    回頁首

    第 2 章在 JAVA 中的實(shí)現(xiàn)

    2.1. 相關(guān)

    Diffie-Hellman 密鑰一致協(xié)議和 DES 程序需要 JCE 工具庫的支持 , 可以到?http://java.sun.com/security/index.html?下載 JCE, 并進(jìn)行安裝。簡(jiǎn)易安裝把 jce1.2.1\lib 下的所有內(nèi)容復(fù)制到 %java_home%\lib\ext 下 , 如果沒有 ext 目錄自行建立 , 再把 jce1_2_1.jar 和 sunjce_provider.jar 添加到 CLASSPATH 內(nèi) , 更詳細(xì)說明請(qǐng)看相應(yīng)用戶手冊(cè)

    2.2. 消息摘要 MD5 和 SHA 的使用

    使用方法 :

    首先用生成一個(gè) MessageDigest 類 , 確定計(jì)算方法

    java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");

    添加要進(jìn)行計(jì)算摘要的信息

    alga.update(myinfo.getBytes());

    計(jì)算出摘要

    byte[] digesta=alga.digest();

    發(fā)送給其他人你的信息和摘要

    其他人用相同的方法初始化 , 添加信息 , 最后進(jìn)行比較摘要是否相同

    algb.isEqual(digesta,algb.digest())

    相關(guān) AIP

    java.security.MessageDigest 類

    static getInstance(String algorithm)

    返回一個(gè) MessageDigest 對(duì)象 , 它實(shí)現(xiàn)指定的算法

    參數(shù) : 算法名 , 如 SHA-1 或 MD5

    void update (byte input)

    void update (byte[] input)

    void update(byte[] input, int offset, int len)

    添加要進(jìn)行計(jì)算摘要的信息

    byte[] digest()

    完成計(jì)算 , 返回計(jì)算得到的摘要 ( 對(duì)于 MD5 是 16 位 ,SHA 是 20 位 )

    void reset()

    復(fù)位

    static boolean isEqual(byte[] digesta, byte[] digestb)

    比效兩個(gè)摘要是否相同

    代碼:

    import java.security.*; public class myDigest { public static void main(String[] args) { myDigest my=new myDigest(); my.testDigest(); } public void testDigest() { try { String myinfo="我的測(cè)試信息"; //java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5"); java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1"); alga.update(myinfo.getBytes()); byte[] digesta=alga.digest(); System.out.println("本信息摘要是 :"+byte2hex(digesta)); // 通過某中方式傳給其他人你的信息 (myinfo) 和摘要 (digesta) 對(duì)方可以判斷是否更改或傳輸正常java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1"); algb.update(myinfo.getBytes()); if (algb.isEqual(digesta,algb.digest())) { System.out.println("信息檢查正常"); } else { System.out.println("摘要不相同"); } } catch (java.security.NoSuchAlgorithmException ex) { System.out.println("非法摘要算法"); } } public String byte2hex(byte[] b) // 二行制轉(zhuǎn)字符串{ String hs=""; String stmp=""; for (int n=0;n<b.length;n++) { stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length()==1) hs=hs+"0"+stmp; else hs=hs+stmp; if (n<b.length-1) hs=hs+":"; } return hs.toUpperCase(); } }

    2.3. 數(shù)字簽名 DSA

  • 對(duì)于一個(gè)用戶來講首先要生成他的密鑰對(duì) , 并且分別保存

    生成一個(gè) KeyPairGenerator 實(shí)例

    java.security.KeyPairGenerator keygen=java.security.KeyPairGenerator.getInstance("DSA");//如果設(shè)定隨機(jī)產(chǎn)生器就用如相代碼初始化 SecureRandom secrand=new SecureRandom(); secrand.setSeed("tttt".getBytes()); // 初始化隨機(jī)產(chǎn)生器 keygen.initialize(512,secrand); // 初始化密鑰生成器//否則 keygen.initialize(512); //生成密鑰公鑰 pubkey 和私鑰 prikey KeyPair keys=keygen.generateKeyPair(); // 生成密鑰組 PublicKey pubkey=keys.getPublic(); PrivateKey prikey=keys.getPrivate(); //分別保存在 myprikey.dat 和 mypubkey.dat 中 , 以便下次不在生成 //( 生成密鑰對(duì)的時(shí)間比較長(zhǎng) java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat")); out.writeObject(prikey); out.close(); out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat")); out.writeObject(pubkey); out.close();
  • 用他私人密鑰 (prikey) 對(duì)他所確認(rèn)的信息 (info) 進(jìn)行數(shù)字簽名產(chǎn)生一個(gè)簽名數(shù)組

    從文件中讀入私人密鑰 (prikey)

    java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat")); PrivateKey myprikey=(PrivateKey)in.readObject(); in.close(); 初始一個(gè) Signature 對(duì)象 , 并用私鑰對(duì)信息簽名 java.security.Signature signet=java.security.Signature.getInstance("DSA"); signet.initSign(myprikey); signet.update(myinfo.getBytes()); byte[] signed=signet.sign(); 把信息和簽名保存在一個(gè)文件中 (myinfo.dat) java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat")); out.writeObject(myinfo); out.writeObject(signed); out.close(); 把他的公鑰的信息及簽名發(fā)給其它用戶
  • 其他用戶用他的公共密鑰 (pubkey) 和簽名 (signed) 和信息 (info) 進(jìn)行驗(yàn)證是否由他簽名的信息

    讀入公鑰?
    java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));?
    PublicKey pubkey=(PublicKey)in.readObject();?
    in.close();

    讀入簽名和信息?
    in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));?
    String info=(String)in.readObject();?
    byte[] signed=(byte[])in.readObject();?
    in.close();

    初始一個(gè) Signature 對(duì)象 , 并用公鑰和簽名進(jìn)行驗(yàn)證?
    java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");?
    signetcheck.initVerify(pubkey);?
    signetcheck.update(info.getBytes());?
    if (signetcheck.verify(signed)) { System.out.println("簽名正常");}

    對(duì)于密鑰的保存本文是用對(duì)象流的方式保存和傳送的 , 也可可以用編碼的方式保存 . 注意要?
    import java.security.spec.*?
    import java.security.*

    具休說明如下

    • public key 是用 X.509 編碼的 , 例碼如下 : byte[] bobEncodedPubKey=mypublic.getEncoded(); // 生成編碼// 傳送二進(jìn)制編碼// 以下代碼轉(zhuǎn)換編碼為相應(yīng) key 對(duì)象X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
    • 對(duì)于 Private key 是用 PKCS#8 編碼 , 例碼如下 : byte[] bPKCS=myprikey.getEncoded(); // 傳送二進(jìn)制編碼// 以下代碼轉(zhuǎn)換編碼為相應(yīng) key 對(duì)象PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS); KeyFactory keyf=KeyFactory.getInstance("DSA"); PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);
  • 常用 API

    java.security.KeyPairGenerator 密鑰生成器類?
    public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException?
    以指定的算法返回一個(gè) KeyPairGenerator 對(duì)象?
    參數(shù) : algorithm 算法名 . 如 :"DSA","RSA"

    public void initialize(int keysize)

    以指定的長(zhǎng)度初始化 KeyPairGenerator 對(duì)象 , 如果沒有初始化系統(tǒng)以 1024 長(zhǎng)度默認(rèn)設(shè)置

    參數(shù) :keysize 算法位長(zhǎng) . 其范圍必須在 512 到 1024 之間,且必須為 64 的倍數(shù)

    public void initialize(int keysize, SecureRandom random)?
    以指定的長(zhǎng)度初始化和隨機(jī)發(fā)生器初始化 KeyPairGenerator 對(duì)象?
    參數(shù) :keysize 算法位長(zhǎng) . 其范圍必須在 512 到 1024 之間,且必須為 64 的倍數(shù)?
    random 一個(gè)隨機(jī)位的來源 ( 對(duì)于 initialize(int keysize) 使用了默認(rèn)隨機(jī)器

    public abstract KeyPair generateKeyPair()?
    產(chǎn)生新密鑰對(duì)

    java.security.KeyPair 密鑰對(duì)類?
    public PrivateKey getPrivate()?
    返回私鑰

    public PublicKey getPublic()?
    返回公鑰

    java.security.Signature 簽名類?
    public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException?
    返回一個(gè)指定算法的 Signature 對(duì)象?
    參數(shù) algorithm 如 :"DSA"

    public final void initSign(PrivateKey privateKey)?
    throws InvalidKeyException?
    用指定的私鑰初始化?
    參數(shù) :privateKey 所進(jìn)行簽名時(shí)用的私鑰

    public final void update(byte data)?
    throws SignatureException?
    public final void update(byte[] data)?
    throws SignatureException?
    public final void update(byte[] data, int off, int len)?
    throws SignatureException?
    添加要簽名的信息

    public final byte[] sign()?
    throws SignatureException?
    返回簽名的數(shù)組 , 前提是 initSign 和 update

    public final void initVerify(PublicKey publicKey)?
    throws InvalidKeyException?
    用指定的公鑰初始化?
    參數(shù) :publicKey 驗(yàn)證時(shí)用的公鑰

    public final boolean verify(byte[] signature)?
    throws SignatureException?
    驗(yàn)證簽名是否有效 , 前提是已經(jīng) initVerify 初始化?
    參數(shù) : signature 簽名數(shù)組

    import java.security.*; import java.security.spec.*; public class testdsa { public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception { testdsa my=new testdsa(); my.run(); } public void run() { // 數(shù)字簽名生成密鑰// 第一步生成密鑰對(duì) , 如果已經(jīng)生成過 , 本過程就可以跳過 , // 對(duì)用戶來講 myprikey.dat 要保存在本地// 而 mypubkey.dat 給發(fā)布給其它用戶if ((new java.io.File("myprikey.dat")).exists()==false) { if (generatekey()==false) { System.out.println("生成密鑰對(duì)敗"); return; }; } // 第二步 , 此用戶// 從文件中讀入私鑰 , 對(duì)一個(gè)字符串進(jìn)行簽名后保存在一個(gè)文件 (myinfo.dat) 中// 并且再把 myinfo.dat 發(fā)送出去// 為了方便數(shù)字簽名也放進(jìn)了 myifno.dat 文件中 , 當(dāng)然也可分別發(fā)送try { java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat")); PrivateKey myprikey=(PrivateKey)in.readObject(); in.close(); // java.security.spec.X509EncodedKeySpec pubX509=// new java.security.spec.X509EncodedKeySpec(bX509); //java.security.spec.X509EncodedKeySpec pubkeyEncode=// java.security.spec.X509EncodedKeySpec String myinfo="這是我的信息"; // 要簽名的信息// 用私鑰對(duì)信息生成數(shù)字簽名java.security.Signature signet=java.security.Signature.getInstance("DSA");signet.initSign(myprikey); signet.update(myinfo.getBytes()); byte[] signed=signet.sign(); // 對(duì)信息的數(shù)字簽名System.out.println("signed( 簽名內(nèi)容 )="+byte2hex(signed)); // 把信息和數(shù)字簽名保存在一個(gè)文件中java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat")); out.writeObject(myinfo); out.writeObject(signed); out.close(); System.out.println("簽名并生成文件成功"); } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("簽名并生成文件失敗"); }; // 第三步// 其他人通過公共方式得到此戶的公鑰和文件// 其他人用此戶的公鑰 , 對(duì)文件進(jìn)行檢查 , 如果成功說明是此用戶發(fā)布的信息 . // try { java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat")); PublicKey pubkey=(PublicKey)in.readObject(); in.close(); System.out.println(pubkey.getFormat()); in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat")); String info=(String)in.readObject(); byte[] signed=(byte[])in.readObject(); in.close(); java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");signetcheck.initVerify(pubkey); signetcheck.update(info.getBytes()); if (signetcheck.verify(signed)) { System.out.println("info="+info); System.out.println("簽名正常"); } else System.out.println("非簽名正常"); } catch (java.lang.Exception e) {e.printStackTrace();}; } // 生成一對(duì)文件 myprikey.dat 和 mypubkey.dat--- 私鑰和公鑰 , // 公鑰要用戶發(fā)送 ( 文件 , 網(wǎng)絡(luò)等方法 ) 給其它用戶 , 私鑰保存在本地public boolean generatekey() { try { java.security.KeyPairGenerator keygen = java.security.KeyPairGenerator.getInstance("DSA");// SecureRandom secrand=new SecureRandom(); // secrand.setSeed("tttt".getBytes()); // 初始化隨機(jī)產(chǎn)生器// keygen.initialize(576,secrand); // 初始化密鑰生成器keygen.initialize(512); KeyPair keys=keygen.genKeyPair(); // KeyPair keys=keygen.generateKeyPair(); // 生成密鑰組PublicKey pubkey=keys.getPublic(); PrivateKey prikey=keys.getPrivate(); java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat")); out.writeObject(prikey); out.close(); System.out.println("寫入對(duì)象 prikeys ok"); out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat")); out.writeObject(pubkey); out.close(); System.out.println("寫入對(duì)象 pubkeys ok"); System.out.println("生成密鑰對(duì)成功"); return true; } catch (java.lang.Exception e) { e.printStackTrace(); System.out.println("生成密鑰對(duì)失敗"); return false; }; } public String byte2hex(byte[] b) { String hs=""; String stmp=""; for (int n=0;n<b.length;n++) { stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length()==1) hs=hs+"0"+stmp; else hs=hs+stmp; if (n<b.length-1) hs=hs+":"; } return hs.toUpperCase(); } }
  • 2.4. DESede/DES 對(duì)稱算法

    首先生成密鑰 , 并保存 ( 這里并沒的保存的代碼 , 可參考 DSA 中的方法 )

    KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);

    SecretKey deskey = keygen.generateKey();

    用密鑰加密明文 (myinfo), 生成密文 (cipherByte)

    Cipher c1 = Cipher.getInstance(Algorithm);

    c1.init(Cipher.ENCRYPT_MODE,deskey);

    byte[] cipherByte=c1.doFinal(myinfo.getBytes());

    傳送密文和密鑰 , 本文沒有相應(yīng)代碼可參考 DSA

    .............

    用密鑰解密密文

    c1 = Cipher.getInstance(Algorithm);

    c1.init(Cipher.DECRYPT_MODE,deskey);

    byte[] clearByte=c1.doFinal(cipherByte);

    相對(duì)來說對(duì)稱密鑰的使用是很簡(jiǎn)單的 , 對(duì)于 JCE 來講支技 DES,DESede,Blowfish 三種加密術(shù)

    對(duì)于密鑰的保存各傳送可使用對(duì)象流或者用二進(jìn)制編碼 , 相關(guān)參考代碼如下

    SecretKey deskey = keygen.generateKey(); byte[] desEncode=deskey.getEncoded(); javax.crypto.spec.SecretKeySpec destmp =new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm); SecretKey mydeskey=destmp;

    相關(guān) API

    KeyGenerator 在 DSA 中已經(jīng)說明 , 在添加 JCE 后在 instance 進(jìn)可以如下參數(shù)

    DES,DESede,Blowfish,HmacMD5,HmacSHA1

    javax.crypto.Cipher 加 / 解密器

    public static final Cipher getInstance(java.lang.String transformation) throws java.security.NoSuchAlgorithmException, NoSuchPaddingException

    返回一個(gè)指定方法的 Cipher 對(duì)象

    參數(shù) :transformation 方法名 ( 可用 DES,DESede,Blowfish)

    public final void init(int opmode, java.security.Key key)?
    throws java.security.InvalidKeyException

    用指定的密鑰和模式初始化 Cipher 對(duì)象

    參數(shù) :opmode 方式 (ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)

    key 密鑰

    public final byte[] doFinal(byte[] input) throws java.lang.IllegalStateException, IllegalBlockSizeException, BadPaddingException

    對(duì) input 內(nèi)的串 , 進(jìn)行編碼處理 , 返回處理后二進(jìn)制串 , 是返回解密文還是加解文由 init 時(shí)的 opmode 決定

    注意 : 本方法的執(zhí)行前如果有 update, 是對(duì) updat 和本次 input 全部處理 , 否則是本 inout 的內(nèi)容

    /* 安全程序 DESede/DES 測(cè)試*/ import java.security.*; import javax.crypto.*; public class testdes { public static void main(String[] args){ testdes my=new testdes(); my.run(); } public void run() { // 添加新安全算法 , 如果用 JCE 就要把它添加進(jìn)去Security.addProvider(new com.sun.crypto.provider.SunJCE()); String Algorithm="DES"; // 定義 加密算法 , 可用 DES,DESede,Blowfish String myinfo="要加密的信息"; try { // 生成密鑰KeyGenerator keygen = KeyGenerator.getInstance(Algorithm); SecretKey deskey = keygen.generateKey(); // 加密System.out.println("加密前的二進(jìn)串 :"+byte2hex(myinfo.getBytes())); System.out.println("加密前的信息 :"+myinfo); Cipher c1 = Cipher.getInstance(Algorithm); c1.init(Cipher.ENCRYPT_MODE,deskey); byte[] cipherByte=c1.doFinal(myinfo.getBytes()); System.out.println("加密后的二進(jìn)串 :"+byte2hex(cipherByte)); // 解密c1 = Cipher.getInstance(Algorithm); c1.init(Cipher.DECRYPT_MODE,deskey); byte[] clearByte=c1.doFinal(cipherByte); System.out.println("解密后的二進(jìn)串 :"+byte2hex(clearByte)); System.out.println("解密后的信息 :"+(new String(clearByte))); } catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();} catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();} catch (java.lang.Exception e3) {e3.printStackTrace();} } public String byte2hex(byte[] b) // 二行制轉(zhuǎn)字符串{ String hs=""; String stmp=""; for (int n=0;n<b.length;n++) { stmp=(java.lang.Integer.toHexString(b[n] & 0XFF)); if (stmp.length()==1) hs=hs+"0"+stmp; else hs=hs+stmp; if (n<b.length-1) hs=hs+":"; } return hs.toUpperCase(); } }

    2.5. Diffie-Hellman 密鑰一致協(xié)議

    公開密鑰密碼體制的奠基人 Diffie 和 Hellman 所提出的 "指數(shù)密鑰一致協(xié)議"(Exponential Key Agreement Protocol), 該協(xié)議不要求別的安全性 先決條件 , 允許兩名用戶在公開媒體上交換信息以生成"一致"的 , 可以共享的密鑰。在 JCE 的中實(shí)現(xiàn)用戶 alice 生成 DH 類型的密鑰對(duì) , 如果長(zhǎng)度用 1024 生成的時(shí)間請(qǐng) , 推薦第一次生成后保存 DHParameterSpec, 以便下次使用直接初始化 . 使其速度加快

    System.out.println("ALICE: 產(chǎn)生 DH 對(duì) ..."); KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); aliceKpairGen.initialize(512); KeyPair aliceKpair = aliceKpairGen.generateKeyPair();

    alice 生成公鑰發(fā)送組 bob

    byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();

    bob 從 alice 發(fā)送來的公鑰中讀出 DH 密鑰對(duì)的初始參數(shù)生成 bob 的 DH 密鑰對(duì)

    注意這一步一定要做 , 要保證每個(gè)用戶用相同的初始參數(shù)生成的

    DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams(); KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); bobKpairGen.initialize(dhParamSpec); KeyPair bobKpair = bobKpairGen.generateKeyPair();

    bob 根據(jù) alice 的公鑰生成本地的 DES 密鑰

    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); bobKeyAgree.init(bobKpair.getPrivate()); bobKeyAgree.doPhase(alicePubKey, true); SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");

    bob 已經(jīng)生成了他的 DES 密鑰 , 他現(xiàn)把他的公鑰發(fā)給 alice,

    byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();

    alice 根據(jù) bob 的公鑰生成本地的 DES 密鑰

    ,,,,,, 解碼KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); aliceKeyAgree.init(aliceKpair.getPrivate()); aliceKeyAgree.doPhase(bobPubKey, true); SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");

    bob 和 alice 能過這個(gè)過程就生成了相同的 DES 密鑰 , 在這種基礎(chǔ)就可進(jìn)行安全能信

    常用 API

    java.security.KeyPairGenerator 密鑰生成器類?
    public static KeyPairGenerator getInstance(String algorithm)?
    throws NoSuchAlgorithmException?
    以指定的算法返回一個(gè) KeyPairGenerator 對(duì)象?
    參數(shù) : algorithm 算法名 . 如 : 原來是 DSA, 現(xiàn)在添加了 DiffieHellman(DH)

    public void initialize(int keysize)?
    以指定的長(zhǎng)度初始化 KeyPairGenerator 對(duì)象 , 如果沒有初始化系統(tǒng)以 1024 長(zhǎng)度默認(rèn)設(shè)置?
    參數(shù) :keysize 算法位長(zhǎng) . 其范圍必須在 512 到 1024 之間,且必須為 64 的倍數(shù)?
    注意 : 如果用 1024 生長(zhǎng)的時(shí)間很長(zhǎng) , 最好生成一次后就保存 , 下次就不用生成了

    public void initialize(AlgorithmParameterSpec params)?
    throws InvalidAlgorithmParameterException?
    以指定參數(shù)初始化

    javax.crypto.interfaces.DHPublicKey?
    public DHParameterSpec getParams()?
    返回?
    java.security.KeyFactory

    public static KeyFactory getInstance(String algorithm)?
    throws NoSuchAlgorithmException?
    以指定的算法返回一個(gè) KeyFactory?
    參數(shù) : algorithm 算法名 :DSH,DH

    public final PublicKey generatePublic(KeySpec keySpec)?
    throws InvalidKeySpecException?
    根據(jù)指定的 key 說明 , 返回一個(gè) PublicKey 對(duì)象

    java.security.spec.X509EncodedKeySpec?
    public X509EncodedKeySpec(byte[] encodedKey)?
    根據(jù)指定的二進(jìn)制編碼的字串生成一個(gè) key 的說明?
    參數(shù) :encodedKey 二進(jìn)制編碼的字串 ( 一般能過 PublicKey.getEncoded() 生成 )?
    javax.crypto.KeyAgreement 密碼一至類

    public static final KeyAgreement getInstance(java.lang.String algorithm)?
    throws java.security.NoSuchAlgorithmException?
    返回一個(gè)指定算法的 KeyAgreement 對(duì)象?
    參數(shù) :algorithm 算法名 , 現(xiàn)在只能是 DiffieHellman(DH)

    public final void init(java.security.Key key)?
    throws java.security.InvalidKeyException?
    用指定的私鑰初始化?
    參數(shù) :key 一個(gè)私鑰

    public final java.security.Key doPhase(java.security.Key key,?
    boolean lastPhase)?
    throws java.security.InvalidKeyException,?
    java.lang.IllegalStateException?
    用指定的公鑰進(jìn)行定位 ,lastPhase 確定這是否是最后一個(gè)公鑰 , 對(duì)于兩個(gè)用戶的?
    情況下就可以多次定次 , 最后確定?
    參數(shù) :key 公鑰?
    lastPhase 是否最后公鑰

    public final SecretKey generateSecret(java.lang.String algorithm)?
    throws java.lang.IllegalStateException,?
    java.security.NoSuchAlgorithmException,?
    java.security.InvalidKeyException?
    根據(jù)指定的算法生成密鑰?
    參數(shù) :algorithm 加密算法 ( 可用 DES,DESede,Blowfish)

    */ import java.io.*; import java.math.BigInteger; import java.security.*; import java.security.spec.*; import java.security.interfaces.*; import javax.crypto.*; import javax.crypto.spec.*; import javax.crypto.interfaces.*; import com.sun.crypto.provider.SunJCE; public class testDHKey { public static void main(String argv[]) { try { testDHKey my= new testDHKey(); my.run(); } catch (Exception e) { System.err.println(e); } } private void run() throws Exception { Security.addProvider(new com.sun.crypto.provider.SunJCE()); System.out.println("ALICE: 產(chǎn)生 DH 對(duì) ..."); KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH"); aliceKpairGen.initialize(512); KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); // 生成時(shí)間長(zhǎng)// 張三 (Alice) 生成公共密鑰 alicePubKeyEnc 并發(fā)送給李四 (Bob) , // 比如用文件方式 ,socket..... byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded(); //bob 接收到 alice 的編碼后的公鑰 , 將其解碼KeyFactory bobKeyFac = KeyFactory.getInstance("DH"); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec (alicePubKeyEnc); PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec); System.out.println("alice 公鑰 bob 解碼成功"); // bob 必須用相同的參數(shù)初始化的他的 DH KEY 對(duì) , 所以要從 Alice 發(fā)給他的公開密鑰 , // 中讀出參數(shù) , 再用這個(gè)參數(shù)初始化他的 DH key 對(duì)// 從 alicePubKye 中取 alice 初始化時(shí)用的參數(shù)DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams(); KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH"); bobKpairGen.initialize(dhParamSpec); KeyPair bobKpair = bobKpairGen.generateKeyPair(); System.out.println("BOB: 生成 DH key 對(duì)成功"); KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH"); bobKeyAgree.init(bobKpair.getPrivate()); System.out.println("BOB: 初始化本地 key 成功"); // 李四 (bob) 生成本地的密鑰 bobDesKey bobKeyAgree.doPhase(alicePubKey, true); SecretKey bobDesKey = bobKeyAgree.generateSecret("DES"); System.out.println("BOB: 用 alice 的公鑰定位本地 key, 生成本地 DES 密鑰成功"); // Bob 生成公共密鑰 bobPubKeyEnc 并發(fā)送給 Alice, // 比如用文件方式 ,socket....., 使其生成本地密鑰byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded(); System.out.println("BOB 向 ALICE 發(fā)送公鑰"); // alice 接收到 bobPubKeyEnc 后生成 bobPubKey // 再進(jìn)行定位 , 使 aliceKeyAgree 定位在 bobPubKey KeyFactory aliceKeyFac = KeyFactory.getInstance("DH"); x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc); PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec); System.out.println("ALICE 接收 BOB 公鑰并解碼成功"); ; KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH"); aliceKeyAgree.init(aliceKpair.getPrivate()); System.out.println("ALICE: 初始化本地 key 成功"); aliceKeyAgree.doPhase(bobPubKey, true); // 張三 (alice) 生成本地的密鑰 aliceDesKey SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES"); System.out.println("ALICE: 用 bob 的公鑰定位本地 key, 并生成本地 DES 密鑰"); if (aliceDesKey.equals(bobDesKey)) System.out.println("張三和李四的密鑰相同"); // 現(xiàn)在張三和李四的本地的 deskey 是相同的所以 , 完全可以進(jìn)行發(fā)送加密 , 接收后解密 , 達(dá)到// 安全通道的的目的/* * bob 用 bobDesKey 密鑰加密信息*/ Cipher bobCipher = Cipher.getInstance("DES"); bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey); String bobinfo= "這是李四的機(jī)密信息"; System.out.println("李四加密前原文 :"+bobinfo); byte[] cleartext =bobinfo.getBytes(); byte[] ciphertext = bobCipher.doFinal(cleartext); /* * alice 用 aliceDesKey 密鑰解密*/ Cipher aliceCipher = Cipher.getInstance("DES"); aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey); byte[] recovered = aliceCipher.doFinal(ciphertext); System.out.println("alice 解密 bob 的信息 :"+(new String(recovered))); if (!java.util.Arrays.equals(cleartext, recovered)) throw new Exception("解密后與原文信息不同"); System.out.println("解密后相同"); } }

    ?

    第 3 章小結(jié)

    在加密術(shù)中生成密鑰對(duì)時(shí),密鑰對(duì)的當(dāng)然是越長(zhǎng)越好,但費(fèi)時(shí)也越多,請(qǐng)從中從實(shí)際出發(fā)選取合適的長(zhǎng)度,大部分例碼中的密鑰是每次運(yùn)行就從新生成,在實(shí)際的情況中是生成后在一段時(shí)間保存在文件中,再次運(yùn)行直接從文件中讀入,從而加快速度。當(dāng)然定時(shí)更新和加強(qiáng)密鑰保管的安全性也是必須的。

    總結(jié)

    以上是生活随笔為你收集整理的java实现签名和解签的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。