使用java keytool 生成自签名证书。
过程如下:
参数如下:
-genkeypair 生成密钥对
-keyalg 指定密钥算法
-keysize 指定密钥长度
-sigalg 指定签名算法
-validity 证书有效期
-alias 别名
-keystore 密钥库存储位置
注:本文目的不在于生成及导出密钥库证书,故不做详细说明
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
生成并导出获得2份证书: JumpFly.cer JumpFly2.cer
单程序上模拟服务端与客户端利用证书进行加解密交换信息-------------------------
定义密钥库相关信息:(模拟中两端存于同一密钥库下,实际上应该是双方自己的独立密钥库)
private static String password = "123456";
private static String alias = "www.JumpFly.org";
private static String Calias = "www.JumpFly2.org";
private static String certificatePath = "D:/FileBox/CerBox/JumpFly.cer";
private static String CcertificatePath = "D:/FileBox/CerBox/JumpFly2.cer";
private static String keyStorePath = "C:/Windows/System32/JumpFly.keystore";
定义文件路径:
String FilePath="D:\\FileBox\\JAVA3D.zip"; //原始待加密文件路径
String EnFilePath="D:\\FileBox\\EnJAVA3D.zip";//加密后文件路径
String DeFilePath="D:\\FileBox\\DeJAVA3D.zip";//解密后文件路径
文件摘要使用Commons Codec下的DigestUtils类进行摘要处理(可自行查阅Commons Codec相关内容)
由于证书中无秘密密钥(即对称密钥) 所以需要一方生成 然后加密通知另一方获得对称密钥
具体实现如下:
public static void main(String[] args) throws Exception{
String md5Hex;
String FilePath="D:\\FileBox\\JAVA3D.zip";
String EnFilePath="D:\\FileBox\\EnJAVA3D.zip";
String DeFilePath="D:\\FileBox\\DeJAVA3D.zip";
//生成摘要
FileInputStream fileIn=new FileInputStream(FilePath);
md5Hex = DigestUtils.md5Hex(fileIn);
System.out.println("文件摘要:"+md5Hex);
//产生签名--JumpFly的私钥
byte[] sign = CertificateCoder
.sign(md5Hex.getBytes(), keyStorePath, alias, password);
System.err.println("数字签名:\n" + Hex.encodeHexString(sign));
//文件加密
byte[] Key=AESCoder.initKey();//二进制对称密钥key
AESCoder.encryptFile(FilePath, EnFilePath, Key);
//对称密钥加密--用JumpFly2的公钥
byte[] EnKey=CertificateCoder.encryptByPublicKey(Key, CcertificatePath);
System.out.println("以上是JumpFly端加密文件发送.....sign、Key、EnFile、EnKey");
//对称密钥解密--用JumpFly2的私钥
byte[] DeKey=CertificateCoder.decryptByPrivateKey(EnKey, keyStorePath, Calias, password);
//文件解密
AESCoder.decryptFile(EnFilePath, DeFilePath, DeKey);
//验证签名--用JumpFly证书公钥
FileInputStream fileIn2=new FileInputStream(DeFilePath);
String md5Hex2 = DigestUtils.md5Hex(fileIn2);
boolean flag=CertificateCoder.verify(md5Hex2.getBytes(), sign, certificatePath);
System.out.println("文件摘要:"+md5Hex2+"\t 验证签名:"+flag);
System.out.println("以上是JumpFly2端接收文件解密.....");
//生成摘要
String msString="这是JumpFly2端发送的消息";
String sha1Hex=DigestUtils.sha1Hex(msString.getBytes());
System.out.println("消息内容:"+msString+"\t 消息摘要:"+sha1Hex);
//产生签名--JumpFly2的私钥
byte[] sign2 = CertificateCoder
.sign(sha1Hex.getBytes(), keyStorePath, Calias, password);
System.err.println("数字签名:\n" + Hex.encodeHexString(sign2));
//消息加密
byte[] EnMsg=AESCoder.encrypt(msString.getBytes(), DeKey);
//对称密钥加密--用JumpFly的证书公钥
byte[] EnKey2=CertificateCoder.encryptByPublicKey(DeKey, certificatePath);
System.out.println("以上是JumpFly2端加密消息发送.....sign2、EnMsg、EnKey2");
//对称密钥解密--用JumpFly的私钥
byte[] DeKey2=CertificateCoder.decryptByPrivateKey(EnKey2, keyStorePath, alias, password);
//消息解密
byte[] DeMsg=AESCoder.decrypt(EnMsg, DeKey2);
String msgString=new String(DeMsg);
//签名验证--用JumpFly2证书公钥
String sha1Hex2 = DigestUtils.sha1Hex(DeMsg);
boolean flag2=CertificateCoder.verify(sha1Hex2.getBytes(), sign2, CcertificatePath);
System.out.println("消息内容:"+msgString+"\t 消息摘要:"+sha1Hex2+"\t 验证签名:"+flag2);
System.out.println("以上是JumpFly端接收消息解密.....");
}相关函数如下:
AESCoder :(在java加密与解密的艺术2相关代码中加以修改)
private static final String KEY_ALGORITHM="AES";
private static final String CIPHER_ALGORITHM="AES/ECB/PKCS5Padding";
private static byte[] getKey(String key)throws Exception{
return Base64.decodeBase64(key);
}
private static Key toKey(byte[] key)throws Exception{
//实例化密钥材料
SecretKey secretKey=new SecretKeySpec(key, KEY_ALGORITHM);
return secretKey;
}
public static byte[] decrypt(byte[] data,byte[] key)throws Exception{
//还原密钥
Key K=toKey(key);
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, K);
return cipher.doFinal(data);
}
public static byte[] decrypt(byte[] data,String key)throws Exception{
return decrypt(data, getKey(key));
}
public static byte[] encrypt(byte[] data,byte[] key)throws Exception{
//还原密钥
Key K=toKey(key);
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, K);
return cipher.doFinal(data);
}
public static byte[] encrypt(byte[] data,String key)throws Exception{
return encrypt(data, getKey(key));
}
public static void encryptFile(String FilePath,String EnFilePath,byte[] key)throws Exception{
FileInputStream fileIn= new FileInputStream(FilePath);
FileOutputStream fileOut=new FileOutputStream(EnFilePath);
Key K=toKey(key);
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, K);
crypt(fileIn, fileOut, cipher);
}
public static void encryptFile(String FilePath,String EnFilePath,String key)throws Exception{
encryptFile(FilePath, EnFilePath, getKey(key));
}
public static void decryptFile(String EnFilePath,String DeFilePath,byte[] key)throws Exception{
FileInputStream fileIn= new FileInputStream(EnFilePath);
FileOutputStream fileOut=new FileOutputStream(DeFilePath);
Key K=toKey(key);
Cipher cipher=Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, K);
crypt(fileIn, fileOut, cipher);
}
public static void decryptFile(String EnFilePath,String DeFilePath,String key)throws Exception{
decryptFile(EnFilePath, DeFilePath, getKey(key));
}
public static byte[] initKey()throws Exception{
KeyGenerator kg=KeyGenerator.getInstance(KEY_ALGORITHM);
kg.init(256);
//生成秘密密钥
SecretKey secretKey=kg.generateKey();
return secretKey.getEncoded();
}
public static String initKeyString()throws Exception{
return Base64.encodeBase64String(initKey());
}
public static void crypt(FileInputStream in,FileOutputStream out,Cipher cipher)throws IOException,GeneralSecurityException{
FileChannel fcIn=null;
MappedByteBuffer mbbfIn=null;
int blockSize=cipher.getBlockSize();
int outputSize=cipher.getOutputSize(blockSize);
byte[] inBytes=new byte[blockSize];
byte[] outBytes=new byte[outputSize];
int len=0,outLenth;
fcIn=in.getChannel();
mbbfIn=fcIn.map(FileChannel.MapMode.READ_ONLY, 0, fcIn.size());
boolean more=true;
while(more){
len=mbbfIn.limit()-mbbfIn.position();
if(len>blockSize)
{ mbbfIn.get(inBytes, 0, blockSize);
outLenth=cipher.update(inBytes, 0, blockSize, outBytes);
out.write(outBytes,0,outLenth);
}else{
more=false;
}
}
if(len>0){mbbfIn.get(inBytes, 0, len);
outBytes=cipher.doFinal(inBytes,0,len);
}else outBytes=cipher.doFinal();
out.write(outBytes);
if(fcIn!=null)
fcIn.close();
}CertificateCoder:
public static byte[] sign(byte[] sign, String keyStorePath, String alias,
String password) throws Exception {
// 获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(
keyStorePath, alias, password);
// 构建签名,由证书指定签名算法
Signature signature = Signature.getInstance(x509Certificate
.getSigAlgName());
// 获取私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath, alias,
password);
// 初始化签名,由私钥构建
signature.initSign(privateKey);
signature.update(sign);
return signature.sign();
}public static byte[] encryptByPublicKey(byte[] data, String certificatePath)
throws Exception {
// 取得公钥
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
// 对数据加密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}public static byte[] decryptByPrivateKey(byte[] data, String keyStorePath,
String alias, String password) throws Exception {
// 取得私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath, alias,
password);
// 对数据加密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}输出结果:
文件摘要:5417f2fe5eafc7b531a91ed391dbec89
数字签名:
c9a7884f64848c2e04c31a501c7f3301b504c8f7f5066f20800295808e28d3e20373b74466406590665107095fcb1afa413ca2d32cdf1c37ce23d61f6ca12e4aa7c6640aec07e92e837d43f9b65db0ce5e7d14dc893ce4271aa21027bdb660db2884e64e64ced5c208b0e7a8625e669cc23e247d02160e48dc7de6d164f591f2c99abb132a1afeb652af59d313e3b377eda46f4b74057d0e6cf59815461e6b99e37b3adac6e2295f499e4942db0eb5d81bee49304a4541c895b3647dd998690b249361e4b6bf34ceff01b172157057e4f224e5f6065a2bc748cfcb0c7fbf37066402164907a64ee7ad6d404ce3e3bd1f42939fa209f1a9c931f4a4c2d3567685
文件加密耗时: 12153 ms
以上是JumpFly端加密文件发送.....sign、Key、EnFile、EnKey
文件解密耗时: 12075 ms
文件摘要:5417f2fe5eafc7b531a91ed391dbec89 验证签名:true
以上是JumpFly2端接收文件解密.....
消息内容:这是JumpFly2端发送的消息 消息摘要:d5193b828c60194ef91c8af5617df68f6aa0cde4
数字签名:
6a43c3851407777c8b09f7c62899afecc1cc3c85a3f4037e1ef071dcd26c3380cb8db4b7d989756cc3247e9c44cbc4f9b68f77fa5379293a2b24ff4a2f8bbe2812b84a6a6861e9aad19ad3b0ed9e553f5cd1654aa146387d7b4354bebe126de00bff6990e7acb89f9b15f189c8b345498e7b0f7964c96d0156e88f473c9f23d97905d848a812ed7c1f1099f6f86d75aee67566b6f3aa8c60d52cf6127f43bd211f063503436e0535c9d6315e313feadac15eec604502645448e1e582079fb9e97d0059fa382db141c01e3183e6a7f45cd2f025846c0a01e0c10202f1e13397b605783df3b69a4f440c1ad9513c75dfcf72bc3543a76b8779edbb0394cab06ee1
以上是JumpFly2端加密消息发送.....sign2、EnMsg、EnKey2
消息内容:这是JumpFly2端发送的消息 消息摘要:d5193b828c60194ef91c8af5617df68f6aa0cde4
验证签名:true
以上是JumpFly端接收消息解密.....
本文介绍了使用Java进行证书加解密的过程,包括生成密钥对、设置参数、模拟服务端与客户端之间的加解密信息交换。通过示例展示了如何进行文件的加密和解密,以及数字签名的验证。

6550

被折叠的 条评论
为什么被折叠?



