Java&keytool生成RSA密鑰?

Tags: 證書, 密鑰,

一個項目中先使用了AES對稱加密,之後覺得密鑰、摘要等還是不安全,所以又需要使用非對稱加密RSA,加密密鑰、摘要等信息。

之前沒有接觸過,實際使用過程中遇到的最大疑惑就是:

找了一堆資料,大家都在說明keytool怎麼生成密鑰、導出證書、各個參數是什麼含義》...,keytool 生成的密鑰庫KeyStore中包含密鑰(私鑰/公鑰)、證書。

可惜, 無法通過keytool工具來提取私鑰...

那怎麼獲得私鑰、公鑰?

以Java為例:通過KeyStore類getEntry() 或者getKey()來提取私鑰;通過Certificate類getPublicKey()獲取公鑰

Java&keytool生成RSA密鑰

工具/原料

keytool

Eclipse

Keytool生成KeyStore文件

-- 生成密碼倉庫Hearty.store

keytool -genkey -v -alias Hearty -dname "CN=Hearty,OU=HE,O=CUI,L=HAIDIAN,ST=BEIJING,C=CN" -keyalg RSA -keysize 2048 -keypass 5201314 -keystore Hearty.store -storepass 5201314 -validity 10000 -storetype JCEKS

-- 導出證書HRFax.crt

keytool -exportcert -alias Hearty -file Hearty.crt -keystore Hearty.store -storepass 5201314 -rfc -storetype JCEKS

keytool更多使用方法 及 參數說明自行查閱資料(一查一大把)

Java&keytool生成RSA密鑰

Java&keytool生成RSA密鑰

生成私鑰、公鑰

獲取私鑰:

private static PrivateKey getPrivateKeyFromStore() throws Exception

{

String alias = "Hearty"; // KeyTool中生成KeyStore時設置的alias

String storeType = "JCEKS"; // KeyTool中生成KeyStore時設置的storetype

char[] pw = "5201314".toCharArray(); // KeyTool中生成KeyStore時設置的storepass

String storePath = "E:/key/Hearty.store"; // KeyTool中已生成的KeyStore文件

storeType = null == storeType ? KeyStore.getDefaultType() : storeType;

KeyStore keyStore = KeyStore.getInstance(storeType);

InputStream is = new FileInputStream(storePath);

keyStore.load(is, pw);

// 由密鑰庫獲取密鑰的兩種方式

// KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(pw));

// return pkEntry.getPrivateKey();

return (PrivateKey) keyStore.getKey(alias, pw);

}

保存私鑰之文件:

String privatePath = "E:/key/HeartyPri.key"; // 準備導出的私鑰

private static void createKeyFile(Object key, String filePath) throws Exception

{

FileOutputStream fos = new FileOutputStream(filePath);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(key);

oos.flush();

oos.close();

}

獲取公鑰:

private static PublicKey getPublicKeyFromCrt() throws Exception

{

String crtPath = "E:/key/Hearty.crt"; // KeyTool中已生成的證書文件

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

FileInputStream in = new FileInputStream(crtPath);

Certificate crt = cf.generateCertificate(in);

return crt.getPublicKey();

}

保存公鑰至文件:

String privatePath = "E:/key/HeartyPub.key"; // 準備導出的私鑰

private static void createKeyFile(Object key, String filePath) throws Exception

{

FileOutputStream fos = new FileOutputStream(filePath);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(key);

oos.flush();

oos.close();

}

測試加密、解密

1、一般公鑰加密、私鑰解密

2、私鑰加密、公鑰解密也是可以的

Java&keytool生成RSA密鑰

完整源碼

import java.io.ByteArrayOutputStream;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.ObjectOutputStream;

import java.security.Key;

import java.security.KeyStore;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.cert.Certificate;

import java.security.cert.CertificateException;

import java.security.cert.CertificateFactory;

import javax.crypto.Cipher;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import org.bouncycastle.util.encoders.Base64;

public class KeyStoreHelper

{

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

{

String privatePath = "E:/key/HeartyPri.key"; // 準備導出的私鑰

String publicPath = "E:/key/HeartyPub.key"; // 準備導出的公鑰

PrivateKey privateKey = getPrivateKeyFromStore();

createKeyFile(privateKey, privatePath);

PublicKey publicKey = getPublicKeyFromCrt();

createKeyFile(publicKey, publicPath);

test(privateKey, publicKey);

test(publicKey, privateKey);

test(privateKey, privateKey);

test(publicKey, publicKey);

}

private static PrivateKey getPrivateKeyFromStore() throws Exception

{

String alias = "Hearty"; // KeyTool中生成KeyStore時設置的alias

String storeType = "JCEKS"; // KeyTool中生成KeyStore時設置的storetype

char[] pw = "5201314".toCharArray(); // KeyTool中生成KeyStore時設置的storepass

String storePath = "E:/key/Hearty.store"; // KeyTool中已生成的KeyStore文件

storeType = null == storeType ? KeyStore.getDefaultType() : storeType;

KeyStore keyStore = KeyStore.getInstance(storeType);

InputStream is = new FileInputStream(storePath);

keyStore.load(is, pw);

// 由密鑰庫獲取密鑰的兩種方式

// KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(pw));

// return pkEntry.getPrivateKey();

return (PrivateKey) keyStore.getKey(alias, pw);

}

private static PublicKey getPublicKeyFromCrt() throws CertificateException, FileNotFoundException

{

String crtPath = "E:/key/Hearty.crt"; // KeyTool中已生成的證書文件

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

FileInputStream in = new FileInputStream(crtPath);

Certificate crt = cf.generateCertificate(in);

PublicKey publicKey = crt.getPublicKey();

return publicKey;

}

private static void test(Key encryptKey, Key decryptKey) throws Exception

{

System.out.println();

String data = encryptKey.getClass().getSimpleName() + "加密" + " ~ " + decryptKey.getClass().getSimpleName() + "解密";

System.out.println("明文 ~ " + data);

byte[] enb = Base64.encode(RSAencrypt(encryptKey, data.getBytes()));

String en = new String(enb);

System.out.println("加密結果 ~ " + new String(enb));

byte[] deb = Base64.decode(en);

byte[] result = RSAdecrypt(decryptKey, deb);

System.out.println("解密結果 ~ " + new String(result));

}

private static byte[] RSAencrypt(Key pk, byte[] data) throws Exception

{

Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());

cipher.init(Cipher.ENCRYPT_MODE, pk);

int blockSize = cipher.getBlockSize();

int outputSize = cipher.getOutputSize(data.length);

int leavedSize = data.length % blockSize;

int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;

byte[] raw = new byte[outputSize * blocksSize];

int i = 0;

while (data.length - i * blockSize > 0)

{

if (data.length - i * blockSize > blockSize)

{

cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);

}

else

{

cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);

}

i++;

}

return raw;

}

private static byte[] RSAdecrypt(Key pk, byte[] raw) throws Exception

{

Cipher cipher = Cipher.getInstance("RSA", new BouncyCastleProvider());

cipher.init(Cipher.DECRYPT_MODE, pk);

ByteArrayOutputStream bout = null;

try

{

bout = new ByteArrayOutputStream(64);

int j = 0;

int blockSize = cipher.getBlockSize();

while (raw.length - j * blockSize > 0)

{

bout.write(cipher.doFinal(raw, j * blockSize, blockSize));

j++;

}

return bout.toByteArray();

}

catch (Exception e)

{

throw e;

}

finally

{

if (bout != null)

{

try

{

bout.close();

}

catch (IOException e)

{

e.printStackTrace();

}

}

}

}

private static void createKeyFile(Object key, String filePath) throws Exception

{

FileOutputStream fos = new FileOutputStream(filePath);

ObjectOutputStream oos = new ObjectOutputStream(fos);

oos.writeObject(key);

oos.flush();

oos.close();

}

}

Java&keytool生成RSA密鑰

注意事項

代碼格式無法格式化,罪過罪過~~~

相關問題答案