1. 程式人生 > 其它 >java實現RSA公私鑰PKCS#1與PKCS#8之間的相互轉換(java rsa pkcs8轉pkcs1,rsa pkcs1轉pkcs8),PKCS8和PKCS1公私鑰byte陣列還原為java物件

java實現RSA公私鑰PKCS#1與PKCS#8之間的相互轉換(java rsa pkcs8轉pkcs1,rsa pkcs1轉pkcs8),PKCS8和PKCS1公私鑰byte陣列還原為java物件

技術標籤:數字簽名pkcspkirsa加密解密演算法

目錄


前言

專案中底層生成的公私鑰都是pkcs1格式的,但是java中使用的都是pkcs8的,需要轉換。在網上找了很多方法, 但都不是很全面。並且網上大部分方法已經被標為過時了,寫在程式碼裡全是橫線,看著很不舒服。如圖中的RSAPrivateKeyStructure類已經不推薦使用,網上大部分還是用這種方式。在這裡插入圖片描述


因此結合兩種標準的格式規定和bouncycastle的原始碼,自己寫了以下的方法。


引入依賴

依賴bcprov-jdk15on包,以下方法均出自這個包。本人使用的1.51版本,親測可行。
方法一:

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.51</version>
        <
/dependency>

或引入下面的包,會自動引入上面的bcprov-jdk15on包
方法二:

        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcpkix-jdk15on</artifactId>
            <version>1.51</version>
        </dependency>

因專案中使用了bcpkix-jdk15on包中的方法,所以需要兩個包都引入,採用第二種方法引入。

匯入的類

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

一、公鑰轉換

公鑰PKCS1轉PKCS8

    public static byte[] formatPublicKeyPKCS1ToPKCS8(byte[] pkcs1PublicKeyByte) {
            
        RSAPublicKey rsaPub = RSAPublicKey.getInstance(pkcs1PublicKeyByte);
        
        byte[] pkcs8Bytes = null;
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
             
            PublicKey generatePublic = kf.generatePublic(new RSAPublicKeySpec(rsaPub.getModulus(), rsaPub.getPublicExponent()));
            
            pkcs8Bytes = generatePublic.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
         
        return pkcs8Bytes;
            
    }

公鑰PKCS8轉PKCS1

    public static byte[] formatPublicKeyPKCS8ToPKCS1(byte[] pkcs8PublicKeyByte) {
        
        ASN1Sequence publicKeyASN1Object = ASN1Sequence.getInstance(pkcs8PublicKeyByte);
        
        ASN1Encodable derBitStringASN1Encodable = publicKeyASN1Object.getObjectAt(1);
        
        DERBitString derBitStringObject = DERBitString.getInstance(derBitStringASN1Encodable);
        
        return derBitStringObject.getBytes();
        
    }

二、私鑰轉換

私鑰PKCS1轉PKCS8

    public static byte[] formatPrivateKeyPKCS1ToPKCS8(byte[] pkcs1PrivateKeyByte) {
            
        AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag);        
       
        RSAPrivateKey privateKey = RSAPrivateKey.getInstance(pkcs1PrivateKeyByte);
        //另一種方式
        //ASN1Sequence privateKey = ASN1Sequence.getInstance(pkcs1PrivateKeyByte);
        
        byte[] pkcs8Bytes = null;
        
        try {
            PrivateKeyInfo privKeyInfo = new PrivateKeyInfo(algorithmIdentifier, privateKey);            
            pkcs8Bytes = privKeyInfo.getEncoded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return pkcs8Bytes;
            
    }

私鑰PKCS8轉PKCS1

方法一

    public static byte[] formatPrivateKeyPKCS8ToPKCS1(byte[] pksc8PrivateKeyByte) {
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pksc8PrivateKeyByte);
        byte[] pkcs1Bytes = null;
        
        try {
            ASN1Encodable parsePrivateKey = pki.parsePrivateKey();
            
            pkcs1Bytes = parsePrivateKey.toASN1Primitive().getEncoded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pkcs1Bytes;
        
    }

方法二

    public static byte[] formatPrivateKeyPKCS8ToPKCS1(byte[] pksc8PrivateKeyByte) {
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pksc8PrivateKeyByte);
        byte[] pkcs1Bytes = null;
        
        try {
            RSAPrivateKey parsePrivateKey = RSAPrivateKey.getInstance(pki.parsePrivateKey());
            
            pkcs1Bytes = parsePrivateKey.getEncoded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pkcs1Bytes;
        
    }

三、公鑰還原

公鑰byte陣列還原為PKCS1 java物件

方法一(推薦)

    public static RSAPublicKey formatPKCS1PublicKey(byte[] pkcs1PublicKeyByte) {
        
        RSAPublicKey publicKey = RSAPublicKey.getInstance(pkcs1PublicKeyByte);
        
        return publicKey;
    }

方法二

    public static ASN1Encodable formatPKCS1PublicKey(byte[] pkcs1PublicKeyByte) {
        
        ASN1Sequence publicKey = ASN1Sequence.getInstance(pkcs1PublicKeyByte);
        
        return publicKey;
    }

公鑰byte陣列還原為PKCS8 java物件

	public static PublicKey formatPKCS8PublicKey(byte[] pkcs8PublicKeyByte) {
		
	    PublicKey publicKey = null;
	    
	    EncodedKeySpec keySpec = new X509EncodedKeySpec(pkcs8PublicKeyByte);
		try {
			
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			
			publicKey = keyFactory.generatePublic(keySpec);
			
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		return publicKey;
		
	}

四、私鑰還原

私鑰byte陣列還原為PKCS1 java物件

方法一(推薦)

    public static RSAPrivateKey formatPKCS1PrivateKey(byte[] pkcs1PrivateKeyByte) {
        
        RSAPrivateKey privateKey = RSAPrivateKey.getInstance(pkcs1PrivateKeyByte);
        
        return privateKey;
    }

方法二

    public static ASN1Encodable formatPKCS1PrivateKey_2(byte[] pkcs1PrivateKeyByte) {
        
        ASN1Sequence privateKey = ASN1Sequence.getInstance(pkcs1PrivateKeyByte);
        
        return privateKey;
    }

私鑰byte陣列還原為PKCS8 java物件

    public static PrivateKey formatPKCS8PrivateKey(byte[] pkcs8PrivateKeyByte) {
        
        PrivateKey privateKey = null;
        
        EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8PrivateKeyByte);
        try {
            
             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
             
             privateKey = keyFactory.generatePrivate(keySpec);
             
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return privateKey;
        
    }

五、呼叫示例

    static byte[] pkcs1PrivateKeyByte=Base64.decode("MIICXgIBAAKBgQC/Iv5ebLS2QoU/F88jSvrTpMxh0S3fKFy9/VOvdasZ3Bro+sf6kU//WI5crqidiQA4m2NxckMHUc/FUPazAQto/bPJDVagk9rB+UahTZ6gzxfTa4GkpM3jTXAppJfls9Qu1IzLLXoKgsT91wYdm21e1/4otmagTYa5pwAiwfACEQIDAQABAoGBAIy1/1uWXad760pahdSuo19iCFDOxR1vQm9f6tbWIoNkJa90x/owNht+nzeeIWXwcOg7hQcEnlHqKbJSe3umfjWjk35MoV06imNwDa3joF5shVGBVGtKHPcboDGniCONO+HyIc9UNNi84pWXHFlijV5fDmec6odUpsqWmkxXPQetAkEA63V/cnns4W//0ZQLMv0OnJg5fDECAFB189OTj0A6kILfBuTfUpDPA/ioUGU4r8r2jHy+1b6cUD68gvbAAGVgmwJBAM/PpZhLuIKQYNcTwYbmOGCb9OMoxezAXI2mzzsTIU0fHEVnWYvssTYDf5PqRMeaOzECJnUbjvFWMRnCbbRvBMMCQCTUVSIH1jiQ9zfF61aHZKCz4tH9LG32J+0CnCMdDcwK3G3MoO3ePrNFUrZ4jrxYh+YDoSn3zaVzmrL1e6TUNp8CQQCgw7cL1qhq+V6xhKsWvUuoEX6lrYlQ2o+/VejDfs0oaITqfEWeJgICEzrDJ10GPZ7FDzDJMASpV1Cs6OkNyUUZAkEAuSkubxXXJTqaTha8JI+Fa6Db6XUqv0A2f4hmt8hqFgBbUCZRkayKVRo0J9roSffGCvt/T4MKcXbUss7/OEVaKg==");
    static byte[] pkcs1PublicKeyByte=Base64.decode("MIGJAoGBAL8i/l5stLZChT8XzyNK+tOkzGHRLd8oXL39U691qxncGuj6x/qRT/9YjlyuqJ2JADibY3FyQwdRz8VQ9rMBC2j9s8kNVqCT2sH5RqFNnqDPF9NrgaSkzeNNcCmkl+Wz1C7UjMstegqCxP3XBh2bbV7X/ii2ZqBNhrmnACLB8AIRAgMBAAE=");
 
    public static void getKeyPair() {
    
        
        //pkcs1公鑰轉pkcs8  pkcs8公鑰還原
        PublicKey publicKey2 = formatPKCS8PublicKey(formatPublicKeyPKCS1ToPKCS8(pkcs1PublicKeyByte));

		//pkcs1私鑰轉pkcs8 pkcs8私鑰還原
        PrivateKey privateKey2 = formatPKCS8PrivateKey(formatPrivateKeyPKCS1ToPKCS8(pkcs1PrivateKeyByte));
        
        //pkcs8私鑰轉pkcs1 pkcs1私鑰還原
        formatPKCS1PrivateKey(formatPrivateKeyPKCS8ToPKCS1(privateKey2.getEncoded()));

		//pkcs8公鑰轉pkcs1 pkcs1公鑰還原
        formatPKCS1PublicKey(formatPublicKeyPKCS8ToPKCS1(publicKey2.getEncoded()));
        
    }

完整程式碼,包括RSA加解密、簽名驗籤

package com.CryptTest;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;

import cn.hutool.core.codec.Base64;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 *    RSA演算法實現過程為:
 
        1. 隨意選擇兩個大的質數p和q,p不等於q,計算N=pq。
        2. 根據尤拉函式,不大於N且與N互質的整數個數為(p-1)(q-1)。
        3. 選擇一個整數e與(p-1)(q-1)互質,並且e小於(p-1)(q-1)。
        4. 用以下這個公式計算d:d× e ≡ 1 (mod (p-1)(q-1))。
        5. 將p和q的記錄銷燬。
 
        以上內容中,(N,e)是公鑰,(N,d)是私鑰。
 * @author Administrator
 *
 */
public class RSADemo {
	
	/** *//** 
     * RSA最大加密明文大小 
     */  
    private static final int MAX_ENCRYPT_BLOCK = 117;  
    
    static byte[] pkcs1PrivateKeyByte=Base64.decode("MIICXgIBAAKBgQC/Iv5ebLS2QoU/F88jSvrTpMxh0S3fKFy9/VOvdasZ3Bro+sf6kU//WI5crqidiQA4m2NxckMHUc/FUPazAQto/bPJDVagk9rB+UahTZ6gzxfTa4GkpM3jTXAppJfls9Qu1IzLLXoKgsT91wYdm21e1/4otmagTYa5pwAiwfACEQIDAQABAoGBAIy1/1uWXad760pahdSuo19iCFDOxR1vQm9f6tbWIoNkJa90x/owNht+nzeeIWXwcOg7hQcEnlHqKbJSe3umfjWjk35MoV06imNwDa3joF5shVGBVGtKHPcboDGniCONO+HyIc9UNNi84pWXHFlijV5fDmec6odUpsqWmkxXPQetAkEA63V/cnns4W//0ZQLMv0OnJg5fDECAFB189OTj0A6kILfBuTfUpDPA/ioUGU4r8r2jHy+1b6cUD68gvbAAGVgmwJBAM/PpZhLuIKQYNcTwYbmOGCb9OMoxezAXI2mzzsTIU0fHEVnWYvssTYDf5PqRMeaOzECJnUbjvFWMRnCbbRvBMMCQCTUVSIH1jiQ9zfF61aHZKCz4tH9LG32J+0CnCMdDcwK3G3MoO3ePrNFUrZ4jrxYh+YDoSn3zaVzmrL1e6TUNp8CQQCgw7cL1qhq+V6xhKsWvUuoEX6lrYlQ2o+/VejDfs0oaITqfEWeJgICEzrDJ10GPZ7FDzDJMASpV1Cs6OkNyUUZAkEAuSkubxXXJTqaTha8JI+Fa6Db6XUqv0A2f4hmt8hqFgBbUCZRkayKVRo0J9roSffGCvt/T4MKcXbUss7/OEVaKg==");
    static byte[] pkcs1PublicKeyByte=Base64.decode("MIGJAoGBAL8i/l5stLZChT8XzyNK+tOkzGHRLd8oXL39U691qxncGuj6x/qRT/9YjlyuqJ2JADibY3FyQwdRz8VQ9rMBC2j9s8kNVqCT2sH5RqFNnqDPF9NrgaSkzeNNcCmkl+Wz1C7UjMstegqCxP3XBh2bbV7X/ii2ZqBNhrmnACLB8AIRAgMBAAE=");
    
    
    private PublicKey publicKey;
    private PrivateKey privateKey;

    public static void main(String[] args) {
        
    	
    	signTest();
        
        getKeyPair();
	}
    
    public static void signTest() {
        
      RSADemo rsa=new RSADemo();
  
      byte[] data="123".getBytes();
      
      //加密  此處用公鑰加密 也可以反過來 用私鑰加密 用公鑰解密
      byte []eData=rsa.encryptData(data, rsa.publicKey);
      String eDataEncode=new BASE64Encoder().encode(eData);
      
      System.out.println("加密後: "+eDataEncode);
      
      //解密
      try {
          byte[] dData=rsa.decryptData(new BASE64Decoder().decodeBuffer(eDataEncode), rsa.privateKey);
          System.out.println("解密後: "+new String(dData));
      } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
      
      String SIGN_sha256 = "SHA256WithRSA";  
      String SIGN_sh1 = "SHA1WithRSA";  
      
      String sign = rsa.sign(data,SIGN_sha256);
      String sign2 = rsa.sign(data,SIGN_sh1);
      //簽名
      System.out.println(SIGN_sha256+"簽名:"+sign);
      System.out.println(SIGN_sh1+"  簽名:"+sign2);
      
      boolean verify = rsa.verify(data,sign,SIGN_sha256);
      boolean verify2 = rsa.verify(data,sign2,SIGN_sh1);
      
      System.out.println(SIGN_sha256+"驗籤:"+verify);
      System.out.println(SIGN_sh1+"驗籤:"+verify2);
    }
    
    public static void getKeyPair() {
        
        //通過byte[]可以再度將公鑰或私鑰還原出來
        PublicKey publicKey2 = formatPKCS8PublicKey(formatPublicKeyPKCS1ToPKCS8(pkcs1PublicKeyByte));
        
        PrivateKey privateKey2 = formatPKCS8PrivateKey(formatPrivateKeyPKCS1ToPKCS8(pkcs1PrivateKeyByte));
        
        RSAPrivateKey formatPKCS1PrivateKey = formatPKCS1PrivateKey(formatPrivateKeyPKCS8ToPKCS1(privateKey2.getEncoded()));
        
        RSAPrivateKey formatPKCS1PrivateKey_2 = formatPKCS1PrivateKey(formatPrivateKeyPKCS8ToPKCS1_2(privateKey2.getEncoded()));
        
        ASN1Encodable formatPKCS1PrivateKey_2_2 = formatPKCS1PrivateKey_2(formatPrivateKeyPKCS8ToPKCS1_2(privateKey2.getEncoded()));
        
        RSAPublicKey formatPKCS1PublicKey = formatPKCS1PublicKey(formatPublicKeyPKCS8ToPKCS1(publicKey2.getEncoded()));
        
        ASN1Encodable formatPKCS1PublicKey_2 = formatPKCS1PublicKey_2(formatPublicKeyPKCS8ToPKCS1(publicKey2.getEncoded()));
        
        
    }
    
    public static byte[] formatPrivateKeyPKCS1ToPKCS8(byte[] pkcs1PrivateKeyByte) {
            
        AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.pkcs8ShroudedKeyBag);        
       
        RSAPrivateKey privateKey = RSAPrivateKey.getInstance(pkcs1PrivateKeyByte);
        //另一種方式
        ASN1Sequence privateKey1 = ASN1Sequence.getInstance(pkcs1PrivateKeyByte);
        
        byte[] pkcs8Bytes = null;
        
        try {
            PrivateKeyInfo privKeyInfo = new PrivateKeyInfo(algorithmIdentifier, privateKey);            
            PrivateKeyInfo privKeyInfo1 = new PrivateKeyInfo(algorithmIdentifier, privateKey1);            
            pkcs8Bytes = privKeyInfo.getEncoded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return pkcs8Bytes;
            
    }
    
    public static byte[] formatPrivateKeyPKCS8ToPKCS1(byte[] pksc8PrivateKeyByte) {
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pksc8PrivateKeyByte);
        byte[] pkcs1Bytes = null;
        
        try {
            ASN1Encodable parsePrivateKey = pki.parsePrivateKey();
            
            pkcs1Bytes = parsePrivateKey.toASN1Primitive().getEncoded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pkcs1Bytes;
        
    }
    
    public static byte[] formatPrivateKeyPKCS8ToPKCS1_2(byte[] pksc8PrivateKeyByte) {
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pksc8PrivateKeyByte);
        byte[] pkcs1Bytes = null;
        
        try {
            RSAPrivateKey parsePrivateKey = RSAPrivateKey.getInstance(pki.parsePrivateKey());
            
            pkcs1Bytes = parsePrivateKey.getEncoded();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pkcs1Bytes;
        
    }
    
    public static byte[] formatPublicKeyPKCS1ToPKCS8(byte[] pkcs1PublicKeyByte) {
            
        RSAPublicKey rsaPub = RSAPublicKey.getInstance(pkcs1PublicKeyByte);
        
        byte[] pkcs8Bytes = null;
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
             
            PublicKey generatePublic = kf.generatePublic(new RSAPublicKeySpec(rsaPub.getModulus(), rsaPub.getPublicExponent()));
            
            pkcs8Bytes = generatePublic.getEncoded();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
         
        return pkcs8Bytes;
            
    }
    
    public static RSAPrivateKeyStructure formatPkcs8ToPkcs1(String rawKey) throws Exception {
        PrivateKeyInfo pki = PrivateKeyInfo.getInstance(pkcs1PrivateKeyByte);
        RSAPrivateKeyStructure pkcs1Key = RSAPrivateKeyStructure.getInstance(pki.getPrivateKey());
        return pkcs1Key;
    }
	
    public static byte[] formatPublicKeyPKCS8ToPKCS1(byte[] pkcs8PublicKeyByte) {
        
        ASN1Sequence publicKeyASN1Object = ASN1Sequence.getInstance(pkcs8PublicKeyByte);
        
        ASN1Encodable derBitStringASN1Encodable = publicKeyASN1Object.getObjectAt(1);
        
        DERBitString derBitStringObject = DERBitString.getInstance(derBitStringASN1Encodable);
        
        return derBitStringObject.getBytes();
        
    }
    
    public static RSAPublicKey formatPKCS1PublicKey(byte[] pkcs1PublicKeyByte) {
        
        RSAPublicKey publicKey = RSAPublicKey.getInstance(pkcs1PublicKeyByte);
        
        return publicKey;
    }
    
    public static ASN1Encodable formatPKCS1PublicKey_2(byte[] pkcs1PublicKeyByte) {
        
        ASN1Sequence publicKey = ASN1Sequence.getInstance(pkcs1PublicKeyByte);
        
        return publicKey;
    }
    
    public static RSAPrivateKey formatPKCS1PrivateKey(byte[] pkcs1PrivateKeyByte) {
        
        RSAPrivateKey privateKey = RSAPrivateKey.getInstance(pkcs1PrivateKeyByte);
        
        return privateKey;
    }
    
    public static ASN1Encodable formatPKCS1PrivateKey_2(byte[] pkcs1PrivateKeyByte) {
        
        ASN1Sequence privateKey = ASN1Sequence.getInstance(pkcs1PrivateKeyByte);
        
        return privateKey;
    }
    
    
	public RSADemo() {
		
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
			
			keyPairGen.initialize(1024);// 金鑰位數
			
			// 動態生成金鑰對
			KeyPair keyPair = keyPairGen.generateKeyPair();
			
	        
			// 公鑰
			publicKey =  keyPair.getPublic();
			
			// 私鑰
			privateKey = keyPair.getPrivate();
			
			//獲得公鑰私鑰的位元編碼
			byte[] publicKeyByte=publicKey.getEncoded();
			byte[] privateKeyByte=privateKey.getEncoded();
			
			//通過byte[]可以再度將公鑰或私鑰還原出來
			formatPKCS8PublicKey(publicKeyByte);
			formatPKCS8PrivateKey(privateKeyByte);
			
			
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 用公鑰加密
	 * @param publicKey
	 * @return 
	 */
	public byte[] encryptData(byte[] data,PublicKey publicKey) {
		
		try {
			
			Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
			 // 加密前設定加密方式及金鑰
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			
			// 傳入編碼資料並返回編碼結果
            int inputLen = data.length;  
            ByteArrayOutputStream out = new ByteArrayOutputStream();  
            int offSet = 0;  
            byte[] cache;  
            int i = 0;  
            
            // 對資料分段加密  
            while (inputLen - offSet > 0) {  
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {  
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);  
                } else {  
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);  
                }  
                out.write(cache, 0, cache.length);  
                i++;  
                offSet = i * MAX_ENCRYPT_BLOCK;  
            }  
            byte[] encryptedData = out.toByteArray();  
            out.close();  
            
            //不分段加密
            //encryptedData=cipher.doFinal(data);
            
            return encryptedData;  
            
			
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BadPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
     * 用私鑰解密
     *
     * @param encryptedData 經過encryptedData()加密返回的byte資料
     * @param privateKey 私鑰
     * @return
     */
    public byte[] decryptData(byte[] encryptedData, PrivateKey privateKey)
    {
        try
        {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(encryptedData);
        } catch (Exception e)
        {	
        	e.printStackTrace();
            return null;
        }
    }
 
	
	
	
	/**
	 * 通過公鑰byte[]將公鑰還原,適用於RSA演算法
	 * @param pkcs8PublicKeyByte
	 * @return
	 */
	public static PublicKey formatPKCS8PublicKey(byte[] pkcs8PublicKeyByte) {
		
	    PublicKey publicKey = null;
	    
	    EncodedKeySpec keySpec = new X509EncodedKeySpec(pkcs8PublicKeyByte);
		try {
			
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			
			publicKey = keyFactory.generatePublic(keySpec);
			
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		}
		return publicKey;
		
	}
	
	   /**
     * 通過私鑰byte[]將公鑰還原,適用於RSA演算法
     * @param pkcs8PrivateKeyByte
     * @return
     */
    public static PrivateKey formatPKCS8PrivateKey(byte[] pkcs8PrivateKeyByte) {
        
        PrivateKey privateKey = null;
        
        EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8PrivateKeyByte);
        try {
            
             KeyFactory keyFactory = KeyFactory.getInstance("RSA");
             
             privateKey = keyFactory.generatePrivate(keySpec);
             
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return privateKey;
        
    }
	
	public String sign(byte[] data,String SIGN_ALGORITHMS) {
	    try {
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
            
            signature.initSign(privateKey);  
            signature.update(data);
            
            byte[] signed = signature.sign();  
            
            return Base64.encode(signed);
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SignatureException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null; 
	}
	
    public boolean verify(byte[] srcData, String sign,String SIGN_ALGORITHMS)  
    {  
        try  
        {  
           
            java.security.Signature signature = java.security.Signature  
            .getInstance(SIGN_ALGORITHMS);  
           
            signature.initVerify(publicKey);  
            signature.update(srcData);  
           
            boolean bverify = signature.verify( Base64.decode(sign) );  
            return bverify;  
               
        }   
        catch (Exception e)   
        {  
            e.printStackTrace();  
        }  
           
        return false;  
    }  
	
	
}

總結

以上同一個轉換有兩種方法的,其實原理都一樣。區別在於一個轉為標準中規定的結構體,便於獲取其中的資料。另一個轉為ASN1Encodable,是一個ASN1結構體,同樣可以根據資料索引獲取其中的資料。

PKCS #1 RSA公鑰的ASN.1型別

RSAPublicKey ::= SEQUENCE { 
   modulus           INTEGER,  -- n 
   publicExponent    INTEGER   -- e 
} 

RSAPublic的屬性有如下意義:
modulus是RSA的模數n。
publicExponent是RSA的公共指數e。

PKCS #1 RSA私鑰的ASN.1型別

RSAPrivateKey ::= SEQUENCE { 
   version           Version, 
   modulus           INTEGER,  -- n 
   publicExponent    INTEGER,  -- e 
   privateExponent   INTEGER,  -- d 
   prime1            INTEGER,  -- p 
   prime2            INTEGER,  -- q 
   exponent1         INTEGER,  -- d mod (p-1) 
   exponent2         INTEGER,  -- d mod (q-1) 
   coefficient       INTEGER,  -- (inverse of q) mod p 
   otherPrimeInfos   OtherPrimeInfos OPTIONAL 
} 

RSAPrivateKey的屬性有如下意義:
#version 為了相容未來的修訂提出的版本號。本文的版本,多質數為1,其它則為0.
Version ::= INTEGER { two-prime(0), multi(1) }
(CONSTRAINED BY {-- version must be multi if otherPrimeInfos present --})
# modulus 是RSA模數n
# publicExponent 是RSA公有指數e
# privateExponent 是RSA私有質數d
# prime1 是n的質數因子p
# prime2 是n的質數因子q
# exponent1 是d mod(p-1)
# exponent2 是d mod(q-1)
# coefficient 是CRT係數 q-1 mod p
# otherPrimeInfos 按順序包含了附加的質數 r3----ru。它在版本0的時候不存在,將包含在版本1中最少一個例項。

     OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo 
OtherPrimeInfo ::= SEQUENCE { 
   prime             INTEGER,  -- ri 
   exponent          INTEGER,  -- di 
   coefficient       INTEGER   -- ti 
} 

OtherPrimeInfo的屬性有如下的含義:
#prime是n的質數因子ri,i>=3.
#exponent是 di = d mod(ri-1)
#coefficient是CRT係數 ti = (r1r2…ri-1) mod ri

PKCS #8 RSA私鑰的ASN.1型別
在這裡插入圖片描述

名詞解釋
pkcs1:PKCS #1 RSA密碼編譯標準(RSA Cryptography Standard)2.1版本。定義了RSA的數理基礎、公/私鑰格式,以及加/解密、籤/驗章的流程。1.5版本曾經遭到攻擊。
pkcs8:PKCS #8 私鑰訊息表示標準(Private-Key Information Syntax Standard) 1.2版本。