总结Java常用到的六个加密技术和代码

加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知解密的方法,仍然无法了解信息的内容。大体上分为双向加密和单向加密,而双向加密又分为对称加密和非对称加密(有些资料将加密直接分为对称加密和非对称加密)。

双向加密大体意思就是明文加密后形成密文,可以通过算法还原成明文。而单向加密只是对信息进行了摘要计算,不能通过算法生成明文,单向加密从严格意思上说不能算是加密的一种,应该算是摘要算法吧。

具体来说:
系统必须可用,非数学上不可译码。
系统不一定要保密,可以轻易落入敌人手中。
密匙必须可以不经书写的资料交换和记忆,且双方可以改变密匙。
系统可以用于电讯。
系统可以转移位置,它的功能必须不用经过几个人之手才可达到。
系统容易使用,不要求使用者的脑力过份操劳或有很多的规则。

一、主要的加密方式代码提供方
JDK:代码在java安装目录下的jre\lib\jce.jar包里;
CC:Apache公司提供的org.apache.commons.codec
主页: http://commons.apache.org/proper/commons-codec/
BC:org.bouncecastle
主页: http://www.bouncycastle.org/java.html
基本常用的使用JDK就够了。

二、Base64算法
1、从现在加密算法的复杂性来看Base64这种都不好意思说自己是加密,不过对于完全不懂计算机的人来说也够用了。采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
Base64编码一般用于url的处理,或者说任何你不想让普通人一眼就知道是啥的东西都可以用Base64编码处理后再发布在网络上。

package com.amuro.strategy.base64;

import java.util.Base64;

import com.amuro.strategy.IStrategy;

/**
 * Base64算法基于64个基本字符,加密后的string中只包含这64个字符
 * @author Amuro
 *
 */
public class Base64Strategy implements IStrategy
{
 public String encode(String src)
 {
 byte[] encodeBytes = Base64.getEncoder().encode(src.getBytes());
 return new String(encodeBytes);
 }

 public String decode(String src)
 {
 byte[] decodeBytes = Base64.getDecoder().decode(src.getBytes());
 return new String(decodeBytes);
 }
}

2、Base64编码对应关系表

三、消息摘要算法(Message Digest)
消息摘要(Message Digest)又称为数字摘要(Digital Digest)。它是一个唯一对应一个消息或文本的固定长度的值,它由一个单向Hash加密函数对消息进行作用而产生。HASH函数的抗冲突性使得如果一段明文稍有变化,哪怕只更改该段落的一个字母,通过哈希算法作用后都将产生不同的值。而HASH算法的单向性使得要找到哈希值相同的两个不同的输入消息,在计算上是不可能的。所以数据的哈希值,即消息摘要,可以检验数据的完整性。
用大白话来说,任何一段数据应该都和人一样是唯一的,唯一的标识是什么,人类的话目前就是指纹,而数据的指纹是什么呢?没错,就是消息摘要算法产生的这一段String。比如我们在注册网站的时候,客户端向服务器传输的,应该是我们输入的密码进行消息摘要处理后的内容,这样就算服务器被攻破,Hack也无法知道用户真实的密码是什么。不过有说现在MD5和SHA已经被攻破了,具体大家可以谷歌。
1、MD5

package com.amuro.strategy.message_digest;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

/**
 * 消息摘要算法
 * @author Amuro
 *
 */
public class MD5Strategy implements IStrategy
{

 public String encode(String src)
 {
 try
 {
  MessageDigest md = MessageDigest.getInstance("MD5");
  byte[] encodeBytes = md.digest(src.getBytes());

  return Hex.encodeHexString(encodeBytes);
 }
 catch (NoSuchAlgorithmException e)
 {
  e.printStackTrace();
 }
 return null;
 }

 public String decode(String src)
 {
 throw new RuntimeException("MD5 no decode");
 }

}

2、SHA

package com.amuro.strategy.message_digest;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

/**
 * 安全散列算法
 * @author Amuro
 *
 */
public class SHAStrategy implements IStrategy
{

 public String encode(String src)
 {
 try
 {
  MessageDigest md = MessageDigest.getInstance("SHA");
  md.update(src.getBytes());
  return Hex.encodeHexString(md.digest());
 }
 catch (NoSuchAlgorithmException e)
 {
  e.printStackTrace();
 }
 return null;
 }

 public String decode(String src)
 {
 throw new RuntimeException("SHA no decode");
 }

}

四、对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。而因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。当然,安全性较低带来的优点就是优计算量小、加密速度快、加密效率高。
然并卵,现代计算机对这种级别的计算量早就不care了,安全才是最重要的。
1、DES
DES,全称为“Data Encryption Standard”,中文名为“数据加密标准”,是一种使用密钥加密的块算法。DES 算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是 1972 年美国 IBM 公司研制的对称密码体制加密算法。 明文按 64 位进行分组,密钥长 64 位,密钥事实上是 56 位参与 DES 运算(第8、16、24、32、40、48、56、64 位是校验位, 使得每个密钥都有奇数个 1)分组后的明文组和 56 位的密钥按位替代或交换的方法形成密文组的加密方法。

package com.amuro.strategy.des;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

/**
 *
 * @author Amuro
 *
 */
public class DESStrategy implements IStrategy
{
 private Cipher cipher;
 private SecretKey generateKey;

 public String encode(String src)
 {
 try
 {
  KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
  keyGenerator.init(56);//size
  SecretKey secretKey = keyGenerator.generateKey();
  byte[] keyBytes = secretKey.getEncoded();

  DESKeySpec desKeySpec = new DESKeySpec(keyBytes);
  SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
  generateKey = secretKeyFactory.generateSecret(desKeySpec);

  cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
  cipher.init(Cipher.ENCRYPT_MODE, generateKey);
  byte[] resultBytes = cipher.doFinal(src.getBytes());

  return Hex.encodeHexString(resultBytes);
 }
 catch (Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

 public String decode(String src)
 {
 try
 {
  cipher.init(Cipher.DECRYPT_MODE, generateKey);
  byte[] result = Hex.decodeHex(src.toCharArray());
  return new String(cipher.doFinal(result));
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

}

2、3DES3DES,也就是“Triple DES”,中文名“三重数据加密算法”,它相当于是对每个数据块应用三次 DES 加密算法。由于计算机运算能力的增强,原版 DES 密码的密钥长度变得容易被暴力破解;3DES 即是设计用来提供一种相对简单的方法,即通过增加 DES 的密钥长度来避免类似的攻击,而不是设计一种全新的块密码算法。

package com.amuro.strategy.des;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

public class _3DESStrategy implements IStrategy
{
 private Cipher cipher;
 private SecretKey generateKey;

 public String encode(String src)
 {
 try
 {
  KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
  keyGenerator.init(168);//size
  SecretKey secretKey = keyGenerator.generateKey();
  byte[] keyBytes = secretKey.getEncoded();

  DESedeKeySpec desKeySpec = new DESedeKeySpec(keyBytes);
  SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DESede");
  generateKey = secretKeyFactory.generateSecret(desKeySpec);

  cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
  cipher.init(Cipher.ENCRYPT_MODE, generateKey);
  byte[] resultBytes = cipher.doFinal(src.getBytes());

  return Hex.encodeHexString(resultBytes);
 }
 catch (Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

 public String decode(String src)
 {
 try
 {
  cipher.init(Cipher.DECRYPT_MODE, generateKey);
  byte[] result = Hex.decodeHex(src.toCharArray());
  return new String(cipher.doFinal(result));
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }
}

3、AESAES,全称为“Advanced Encryption Standard”,中文名“高级加密标准”,在密码学中又称 Rijndael 加密法,是美国联邦政府采用的一种区块加密标准。AES 加密算法作为新一代的数据加密标准汇聚了强安全性、高性能、高效率、易用和灵活等优点。AES 设计有三个密钥长度:128,192,256 位。相对而言,AES 的 128 密钥比 DES 的 56 密钥强了 1021 倍。

package com.amuro.strategy.des;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

public class AESStrategy implements IStrategy
{
 private Cipher cipher;
 private SecretKey generateKey;

 public String encode(String src)
 {
 try
 {
  KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
  keyGenerator.init(128);//size
  SecretKey secretKey = keyGenerator.generateKey();
  byte[] keyBytes = secretKey.getEncoded();

  generateKey = new SecretKeySpec(keyBytes, "AES");

  cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
  cipher.init(Cipher.ENCRYPT_MODE, generateKey);
  byte[] resultBytes = cipher.doFinal(src.getBytes());

  return Hex.encodeHexString(resultBytes);
 }
 catch (Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

 public String decode(String src)
 {
 try
 {
  cipher.init(Cipher.DECRYPT_MODE, generateKey);
  byte[] result = Hex.decodeHex(src.toCharArray());
  return new String(cipher.doFinal(result));
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }
}

4、PBE
PBE,全称为“Password Base Encryption”,中文名“基于口令加密”,是一种基于密码的加密算法,其特点是使用口令代替了密钥,而口令由用户自己掌管,采用随机数杂凑多重加密等方法保证数据的安全性。
PBE算法没有密钥的概念,把口令当做密钥了。因为密钥长短影响算法安全性,还不方便记忆,这里我们直接换成我们自己常用的口令就大大不同了,便于我们的记忆。但是单纯的口令很容易被字典法给穷举出来,所以我们这里给口令加了点“盐”,这个盐和口令组合,想破解就难了。同时我们将盐和口令合并后用消息摘要算法进行迭代很多次来构建密钥初始化向量的基本材料,使破译更加难了。

package com.amuro.strategy.pbe;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

/**
 * 基于口令的加密(password),对称 + 消息摘要
 * @author Amuro
 *
 */
public class PBEStrategy implements IStrategy
{
 private Cipher cipher;
 private SecretKey generateKey;
 private PBEParameterSpec pbeParameterSpec;

 public String encode(String src)
 {
 try
 {
  SecureRandom secureRandom = new SecureRandom();
  byte[] salt = secureRandom.generateSeed(8);

  String password = "amuro";
  PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
  SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
  generateKey = secretKeyFactory.generateSecret(pbeKeySpec);

  pbeParameterSpec = new PBEParameterSpec(salt, 100);
  cipher = Cipher.getInstance("PBEWITHMD5andDES");
  cipher.init(Cipher.ENCRYPT_MODE, generateKey, pbeParameterSpec);
  byte[] resultBytes = cipher.doFinal(src.getBytes());
  return Hex.encodeHexString(resultBytes);
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

 public String decode(String src)
 {
 try
 {
  cipher.init(Cipher.DECRYPT_MODE, generateKey, pbeParameterSpec);
  byte[] result = Hex.decodeHex(src.toCharArray());
  return new String(cipher.doFinal(result));
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

}

五、非对称加密
非对称加密算法需要两个密钥来进行加密和解密,分别是公钥和私钥。需要注意的一点,这个公钥和私钥必须是一对的,如果用公钥对数据进行加密,那么只有使用对应的私钥才能解密,反之亦然。由于加密和解密使用的是两个不同的密钥,因此,这种算法叫做非对称加密算法。
1、RSA
其实,在早在 1978 年的时候,RSA就已经出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。其原理就如上面的工作过程所述。RSA 算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

package com.amuro.strategy.asymmetric;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

public class RSAStrategy implements IStrategy
{
 private RSAPublicKey rsaPublicKey;
 private RSAPrivateKey rsaPrivateKey;

 public String encode(String src)
 {
 try
 {
  //初始化密钥
  KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  keyPairGenerator.initialize(512);
  KeyPair keyPair = keyPairGenerator.generateKeyPair();
  rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
  rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();

  //私钥加密 公钥解密
  PKCS8EncodedKeySpec pkcs8EncodedKeySpec
  = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.ENCRYPT_MODE, privateKey);
  byte[] resultBytes = cipher.doFinal(src.getBytes());

  //私钥解密 公钥加密
//  X509EncodedKeySpec x509EncodedKeySpec =
//   new X509EncodedKeySpec(rsaPublicKey.getEncoded());
//  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//  PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
//  Cipher cipher = Cipher.getInstance("RSA");
//  cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//  byte[] resultBytes = cipher.doFinal(src.getBytes());

  return Hex.encodeHexString(resultBytes);
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

 public String decode(String src)
 {
 try
 {
  //私钥加密 公钥解密
  X509EncodedKeySpec x509EncodedKeySpec =
   new X509EncodedKeySpec(rsaPublicKey.getEncoded());
  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
  Cipher cipher = Cipher.getInstance("RSA");
  cipher.init(Cipher.DECRYPT_MODE, publicKey);
  byte[] resultBytes = cipher.doFinal(Hex.decodeHex(src.toCharArray()));

  //私钥解密 公钥加密
//  PKCS8EncodedKeySpec pkcs8EncodedKeySpec
//  = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
//  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//  PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//  Cipher cipher = Cipher.getInstance("RSA");
//  cipher.init(Cipher.DECRYPT_MODE, privateKey);
//  byte[] resultBytes = cipher.doFinal(Hex.decodeHex(src.toCharArray()));

  return new String(resultBytes);
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }
 return null;
 }

}

2、DH算法
DH,全称为“Diffie-Hellman”,他是一种确保共享KEY安全穿越不安全网络的方法,也就是常说的密钥一致协议。由公开密钥密码体制的奠基人Diffie和Hellman所提出的一种思想。简单的说就是允许两名用户在公开媒体上交换信息以生成“一致”的、可以共享的密钥。也就是由甲方产出一对密钥(公钥、私钥),乙方依照甲方公钥产生乙方密钥对(公钥、私钥)。
以此为基线,作为数据传输保密基础,同时双方使用同一种对称加密算法构建本地密钥(SecretKey)对数据加密。这样,在互通了本地密钥(SecretKey)算法后,甲乙双方公开自己的公钥,使用对方的公钥和刚才产生的私钥加密数据,同时可以使用对方的公钥和自己的私钥对数据解密。不单单是甲乙双方两方,可以扩展为多方共享数据通讯,这样就完成了网络交互数据的安全通讯!

package com.amuro.strategy.asymmetric;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

import org.apache.commons.codec.binary.Hex;

import com.amuro.strategy.IStrategy;

public class DHStrategy implements IStrategy
{
 private Cipher cipher;
 private SecretKey receiverSecretKey;

 public String encode(String src)
 {
 try
 {
  //初始化发送方密钥
  KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
  senderKeyPairGenerator.initialize(512);
  KeyPair senderkeyPair = senderKeyPairGenerator.generateKeyPair();
  PrivateKey senderPrivateKey = senderkeyPair.getPrivate();
  byte[] senderPublicKeyBytes = senderkeyPair.getPublic().getEncoded();//发送方的公钥

  //初始化接收方密钥,用发送方的公钥
  KeyFactory receiverKeyFactory = KeyFactory.getInstance("DH");
  X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyBytes);
  PublicKey receiverPublicKey = receiverKeyFactory.generatePublic(x509EncodedKeySpec);
  DHParameterSpec dhParameterSpec =
   ((DHPublicKey)receiverPublicKey).getParams();
  KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
  receiverKeyPairGenerator.initialize(dhParameterSpec);
  KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
  PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate();
  byte[] receiverPublicKeyBytes = receiverKeyPair.getPublic().getEncoded();

  KeyAgreement receiverKeyAgreement = KeyAgreement.getInstance("DH");
  receiverKeyAgreement.init(receiverPrivateKey);
  receiverKeyAgreement.doPhase(receiverPublicKey, true);
  receiverSecretKey = receiverKeyAgreement.generateSecret("DES");

  //发送方拿到接收方的public key就可以做加密了
  KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
  x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyBytes);
  PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
  KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
  senderKeyAgreement.init(senderPrivateKey);
  senderKeyAgreement.doPhase(senderPublicKey, true);
  SecretKey senderSecretKey = senderKeyAgreement.generateSecret("DES");

  if(Objects.equals(receiverSecretKey, senderSecretKey))
  {
  cipher = Cipher.getInstance("DES");
  cipher.init(Cipher.ENCRYPT_MODE, senderSecretKey);
  byte[] result = cipher.doFinal(src.getBytes());
  return Hex.encodeHexString(result);
  }

 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

 public String decode(String src)
 {
 try
 {
  cipher.init(Cipher.DECRYPT_MODE, receiverSecretKey);
  byte[] result = Hex.decodeHex(src.toCharArray());
  return new String(cipher.doFinal(result));
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return null;
 }

}

六、数字签名证书
非对称加密已经灰常安全了,但是还有一个破绽:
服务器A公布了自己的公钥,我的电脑是用服务器A的公钥加密数据后再发给服务器A的;这时候服务器B侵入了我的电脑,把我用来加密的公钥换成了它的公钥,于是我发出去的数据就会被服务器B的私钥破解了。肿么防止公钥被篡改呢?
对,我们想到了前面的消息摘要,服务器A把公钥丢给我的时候,同时去CA申请一份数字证书,其实主要就是公钥的消息摘要,有了这份证书,当我再用公钥加密的时候,我就可以先验证一下当前的公钥是否确定是服务器A发送给我的。
这里就贴一种RSA的:

package com.amuro.strategy.signature;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSASign
{
 public static boolean verifySign(String src)
 {
 try
 {
  KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  keyPairGenerator.initialize(512);
  KeyPair keyPair = keyPairGenerator.generateKeyPair();
  PublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
  PrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate();

  PKCS8EncodedKeySpec pkcs8EncodedKeySpec
  = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded());
  KeyFactory keyFactory = KeyFactory.getInstance("RSA");
  PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
  Signature signature = Signature.getInstance("MD5withRSA");
  signature.initSign(privateKey);
  signature.update(src.getBytes());
  //生成签名bytes
  byte[] signBytes = signature.sign();

  X509EncodedKeySpec x509EncodedKeySpec =
   new X509EncodedKeySpec(rsaPublicKey.getEncoded());
  keyFactory = KeyFactory.getInstance("RSA");
  PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
  signature = Signature.getInstance("MD5withRSA");
  signature.initVerify(publicKey);
  signature.update(src.getBytes());
  boolean isVerified = signature.verify(signBytes);

  return isVerified;
 }
 catch(Exception e)
 {
  e.printStackTrace();
 }

 return false;
 }

}

关于数字签名和非对称加密算法的使用,还看到一个非常棒的例子,分享给大家:
唉,这个月买了太多的书,到月底揭不开锅了。正巧在QQ上遇到了Clark:
1-2-3:“Clark,我需要200两纹银,能否借给我?”
Clark:“没问题。我这就给你转账。请给我一张借条。”
1-2-3:“太谢谢了,我这就用Word写一个借条给你。”
然后,我新建一个Word文档,写好借条,存盘。然后,然后怎么办呢?我不能直接把借条发送给Clark,原因有:
1. 我无法保证Clark不会在收到借条后将“纹银200两”改为“纹银2000两”。
2. 如果我赖账,Clark无法证明这个借条就是我写的。
3. 普通的Word文档不能作为打官司的证据。
好在我早就申请了数字证书。我先用我的私钥对借条进行加密,然后将加密后的密文用QQ发送给Clark。Clark收到了借条的密文后,在数字证书认证中心的网站上下载我的公钥,然后使用我的公钥将密文解密,发现确实写的是“借纹银200两”,Clark就可以把银子放心的借给我了,我也不会担心Clark会篡改我的借条,原因是:
1. 由于我发给Clark的是密文,Clark无法进行修改。Clark倒是可以修改解密后的借条,但是Clark没有我的私钥,没法模仿我对借条进行加密。这就叫防篡改。
2. 由于用我的私钥进行加密的借条,有且只有我的公钥可以解密。反过来讲,能用我的公钥解密的借条,一定是使用我的私钥加密的,而只有我才拥有我的私钥,这样Clark就可以证明这个借条就是我写的。这就叫防抵赖。
3. 如果我一直赖着不还钱,Clark把我告上了法庭,这个用我的私钥加密过的Word文档就可以当作程堂证供。因为我国已经出台了《中华人民共和国电子签名法》,使数字签名具有了法律效力。
您一定已经注意到了,这个使用我的私钥进行了加密的借条,具有了防篡改、防抵赖的特性,并且可以作为程堂证供,就跟我对这个借条进行了“签名”的效果是一样的。对了,“使用我的私钥对借条进行加密”的过程就叫做数字签名。

这是一篇总结类文章,把一些常用的Java加密技术和核心代码写在这边,供给需要朋友参考。

(0)

相关推荐

  • 你应该知道的21个Java核心技术

    写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能分享给刚刚入门的Java程序员和打算入Java开发这个行当的准新手们,希望可以给大家一些经验,能让大家更好学习和使用Java. 这次介绍的主要内容是和J2SE相关的部分,另外,会在以后再介绍些J2EE相关的.和Java中各个框架相关的内容. 经过这么多年的Java开发,以及结合平时面试Java开发者的一些经验,我觉得对于J2SE方面主要就是要掌握以下的一些内容. 1. JVM相

  • PHP、JAVA、.NET这三种技术的区别分析

    其实这三种编程技术各有优势,我们大概可以从语言.平台这二点来区分: 一.语言: PHP:PHP产生与1994年,其语法混合了C.Java.Perl 和他自创的一些编程语法:PHP是嵌入在HTML中执行的:它也是一种解释性语言.早期的PHP并非完全的面向对象编程语言,到了PHP4以后的版本才开始有了面向对象的概念. JAVA:JAVA产生与1995年,JAVA语言和JAVA平台统称为JAVA:它语法与C语言和C++语言很接近,并且JAVA是面向对象编程语言,JAVA是编译性语言,可以先将JAVA源

  • Java UrlRewriter伪静态技术运用深入分析

    通常我们为了更好的缓解服务器压力,和增强搜索引擎的友好面,都将文章内容生成静态页面. 但是有时为了能实时的显示一些信息,或者还想运用动态脚本解决一些问题,不能用静态的方式来展示网站内容,必须用到动态页面显示. 这样以来,就损失了对搜索引擎的友好面,怎么样在两者之间找个中间方法呢,如何增强你网站中地址的可读性和让搜索引擎快速的收录到你的站点? 这就需要你美化你的网页的地址,这就产生了伪静态技术,也就是我们常说的Url Rewriter重写技术.就是当我们访问一个页面时,地址栏中展示出来的是以".h

  • 识别率很高的java文字识别技术

    java文字识别程序的关键是寻找一个可以调用的OCR引擎.tesseract-ocr就是一个这样的OCR引擎,在1985年到1995年由HP实验室开发,现在在Google.tesseract-ocr 3.0发布,支持中文.不过tesseract-ocr 3.0不是图形化界面的客户端,别人写的FreeOCR图形化客户端还不支持导入新的 3.0 traineddata.但这标志着,现在有自由的中文OCR软件了. java中使用tesseract-ocr3.01的步骤如下: 1.下载安装tessera

  • Java中四种XML解析技术

    在平时工作中,难免会遇到把 XML 作为数据存储格式.面对目前种类繁多的解决方案,哪个最适合我们呢?在这篇文章中,我对这四种主流方案做一个不完全评测,仅仅针对遍历 XML 这块来测试,因为遍历 XML 是工作中使用最多的(至少我认为). 预 备 测试环境: AMD 毒龙1.4G OC 1.5G.256M DDR333.Windows2000 Server SP4.Sun JDK 1.4.1+Eclipse 2.1+Resin 2.1.8,在 Debug 模式下测试. XML 文件格式如下: <?

  • JAVA使用JDBC技术操作SqlServer数据库实例代码

    JDBC(Java Data Base Connectivity,Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成.JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序. JDBC并不能直接访问数据库,需要借助于数据库厂商提供的JDBC驱动程序. 数据库连接 如果要在Java访问数据库,首先要加载一个数据库驱动,数据库驱动只需要在第一次访问时加载一次.然后再每次访问

  • 分页技术原理与实现之Java+Oracle代码实现分页(二)

    紧接着上篇-分页技术原理与实现之分页的意义及方法(一) ,本篇继续分析分页技术.上篇讲的是分页技术的简单原理与介绍,这篇深入分析一下分页技术的代码实现. 上篇最后讲到了分页的最佳实现是在数据库层进行分页,而且不同的数据库有不同的分页实现,比如Oracle是用三层sql嵌套实现分页的.MySQL是用limit关键字实现的(上篇已讲到). 这篇以Java+Oracle为基础,讲解代码层的实现. 就如平时我们很在分页中看到的,分页的时候返回的不仅包括查询的结果集(List),而且还包括总的页数(pag

  • Java实现远程控制技术完整源代码分享

    Java实现远程控制技术 java自带的java.net.和java.awt.robot. 的混合可以用于实现通过网络对另一台计算机的远程控制,其中包括控制远程计算机鼠标的动作和键盘的输入,以及实时获得远程计算机屏幕的图像.本文将用简洁的语言和由浅入深的逻辑,教大家如何掌握这个技术. 首先先看一下效果图: 远程端计算机界面: 控制端计算机界面: 控制端输入: 远程端输入: 一下开始详细介绍远程控制的技术思路. 首先两台计算机通过java.net的Socket来进行连接. 一端先打开一个Serve

  • java的poi技术读取和导入Excel实例

    报表输出是Java应用开发中经常涉及的内容,而一般的报表往往缺乏通用性,不方便用户进行个性化编辑.Java程序由于其跨平台特性,不能直接操纵Excel.因此,本文探讨一下POI视线Java程序进行Excel的读取和导入. 项目结构: java_poi_excel 用到的Excel文件: xls XlsMain .java 类 //该类有main方法,主要负责运行程序,同时该类中也包含了用poi读取Excel(2003版) import java.io.FileInputStream; impor

  • JAVA Web实时消息后台服务器推送技术---GoEasy

    越来越多的项目需要用到实时消息的推送与接收,我这里推荐大家使用GoEasy, 它是一款第三方推送服务平台,使用它的API可以轻松搞定实时推送! 浏览器兼容性:GoEasy推送 支持websocket 和polling两种连接方式,从而可以支持IE6及其以上的所有版本,同时还支持其它浏览器诸如Firefox, Chrome, Safari等等. 支持不同的开发语言:GoEasy推送 提供了Restful API接口,无论你的后台程序用的是哪种语言都可以通过Restful API来实现后台实时推送.

随机推荐