Java加密技术(六)

关键字: dsa, 公钥, 私钥, 数字签名, 非对称加密

    接下来我们介绍DSA数字签名,非对称加密的另一种实现。
DSA
DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!数字签名的作用就是校验数据在传输过程中不被修改。数字签名,是单向加密的升级!


通过java代码实现如下: Coder类见 Java加密技术(一)
Java代码 复制代码
  1. import java.security.Key;   
  2. import java.security.KeyFactory;   
  3. import java.security.KeyPair;   
  4. import java.security.KeyPairGenerator;   
  5. import java.security.PrivateKey;   
  6. import java.security.PublicKey;   
  7. import java.security.SecureRandom;   
  8. import java.security.Signature;   
  9. import java.security.interfaces.DSAPrivateKey;   
  10. import java.security.interfaces.DSAPublicKey;   
  11. import java.security.spec.PKCS8EncodedKeySpec;   
  12. import java.security.spec.X509EncodedKeySpec;   
  13. import java.util.HashMap;   
  14. import java.util.Map;   
  15.   
  16. /**  
  17.  * DSA安全编码组件  
  18.  *   
  19.  * @author 梁栋  
  20.  * @version 1.0  
  21.  * @since 1.0  
  22.  */  
  23. public abstract class DSACoder extends Coder {   
  24.   
  25.     public static final String ALGORITHM = "DSA";   
  26.   
  27.     /**  
  28.      * 默认密钥字节数  
  29.      *   
  30.      * <pre>  
  31.      * DSA   
  32.      * Default Keysize 1024    
  33.      * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).  
  34.      * </pre>  
  35.      */  
  36.     private static final int KEY_SIZE = 1024;   
  37.   
  38.     /**  
  39.      * 默认种子  
  40.      */  
  41.     private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";   
  42.   
  43.     private static final String PUBLIC_KEY = "DSAPublicKey";   
  44.     private static final String PRIVATE_KEY = "DSAPrivateKey";   
  45.   
  46.     /**  
  47.      * 用私钥对信息生成数字签名  
  48.      *   
  49.      * @param data  
  50.      *            加密数据  
  51.      * @param privateKey  
  52.      *            私钥  
  53.      *   
  54.      * @return  
  55.      * @throws Exception  
  56.      */  
  57.     public static String sign(byte[] data, String privateKey) throws Exception {   
  58.         // 解密由base64编码的私钥   
  59.         byte[] keyBytes = decryptBASE64(privateKey);   
  60.   
  61.         // 构造PKCS8EncodedKeySpec对象   
  62.         PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);   
  63.   
  64.         // KEY_ALGORITHM 指定的加密算法   
  65.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);   
  66.   
  67.         // 取私钥匙对象   
  68.         PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);   
  69.   
  70.         // 用私钥对信息生成数字签名   
  71.         Signature signature = Signature.getInstance(keyFactory.getAlgorithm());   
  72.         signature.initSign(priKey);   
  73.         signature.update(data);   
  74.   
  75.         return encryptBASE64(signature.sign());   
  76.     }   
  77.   
  78.     /**  
  79.      * 校验数字签名  
  80.      *   
  81.      * @param data  
  82.      *            加密数据  
  83.      * @param publicKey  
  84.      *            公钥  
  85.      * @param sign  
  86.      *            数字签名  
  87.      *   
  88.      * @return 校验成功返回true 失败返回false  
  89.      * @throws Exception  
  90.      *   
  91.      */  
  92.     public static boolean verify(byte[] data, String publicKey, String sign)   
  93.             throws Exception {   
  94.   
  95.         // 解密由base64编码的公钥   
  96.         byte[] keyBytes = decryptBASE64(publicKey);   
  97.   
  98.         // 构造X509EncodedKeySpec对象   
  99.         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);   
  100.   
  101.         // ALGORITHM 指定的加密算法   
  102.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);   
  103.   
  104.         // 取公钥匙对象   
  105.         PublicKey pubKey = keyFactory.generatePublic(keySpec);   
  106.   
  107.         Signature signature = Signature.getInstance(keyFactory.getAlgorithm());   
  108.         signature.initVerify(pubKey);   
  109.         signature.update(data);   
  110.   
  111.         // 验证签名是否正常   
  112.         return signature.verify(decryptBASE64(sign));   
  113.     }   
  114.   
  115.     /**  
  116.      * 生成密钥  
  117.      *   
  118.      * @param seed  
  119.      *            种子  
  120.      * @return 密钥对象  
  121.      * @throws Exception  
  122.      */  
  123.     public static Map<String, Object> initKey(String seed) throws Exception {   
  124.         KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);   
  125.         // 初始化随机产生器   
  126.         SecureRandom secureRandom = new SecureRandom();   
  127.         secureRandom.setSeed(seed.getBytes());   
  128.         keygen.initialize(KEY_SIZE, secureRandom);   
  129.   
  130.         KeyPair keys = keygen.genKeyPair();   
  131.   
  132.         DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();   
  133.         DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();   
  134.   
  135.         Map<String, Object> map = new HashMap<String, Object>(2);   
  136.         map.put(PUBLIC_KEY, publicKey);   
  137.         map.put(PRIVATE_KEY, privateKey);   
  138.   
  139.         return map;   
  140.     }   
  141.   
  142.     /**  
  143.      * 默认生成密钥  
  144.      *   
  145.      * @return 密钥对象  
  146.      * @throws Exception  
  147.      */  
  148.     public static Map<String, Object> initKey() throws Exception {   
  149.         return initKey(DEFAULT_SEED);   
  150.     }   
  151.   
  152.     /**  
  153.      * 取得私钥  
  154.      *   
  155.      * @param keyMap  
  156.      * @return  
  157.      * @throws Exception  
  158.      */  
  159.     public static String getPrivateKey(Map<String, Object> keyMap)   
  160.             throws Exception {   
  161.         Key key = (Key) keyMap.get(PRIVATE_KEY);   
  162.   
  163.         return encryptBASE64(key.getEncoded());   
  164.     }   
  165.   
  166.     /**  
  167.      * 取得公钥  
  168.      *   
  169.      * @param keyMap  
  170.      * @return  
  171.      * @throws Exception  
  172.      */  
  173.     public static String getPublicKey(Map<String, Object> keyMap)   
  174.             throws Exception {   
  175.         Key key = (Key) keyMap.get(PUBLIC_KEY);   
  176.   
  177.         return encryptBASE64(key.getEncoded());   
  178.     }   
  179. }  
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * DSA安全编码组件
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public abstract class DSACoder extends Coder {

	public static final String ALGORITHM = "DSA";

	/**
	 * 默认密钥字节数
	 * 
	 * <pre>
	 * DSA 
	 * Default Keysize 1024  
	 * Keysize must be a multiple of 64, ranging from 512 to 1024 (inclusive).
	 * </pre>
	 */
	private static final int KEY_SIZE = 1024;

	/**
	 * 默认种子
	 */
	private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";

	private static final String PUBLIC_KEY = "DSAPublicKey";
	private static final String PRIVATE_KEY = "DSAPrivateKey";

	/**
	 * 用私钥对信息生成数字签名
	 * 
	 * @param data
	 *            加密数据
	 * @param privateKey
	 *            私钥
	 * 
	 * @return
	 * @throws Exception
	 */
	public static String sign(byte[] data, String privateKey) throws Exception {
		// 解密由base64编码的私钥
		byte[] keyBytes = decryptBASE64(privateKey);

		// 构造PKCS8EncodedKeySpec对象
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

		// KEY_ALGORITHM 指定的加密算法
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

		// 取私钥匙对象
		PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);

		// 用私钥对信息生成数字签名
		Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
		signature.initSign(priKey);
		signature.update(data);

		return encryptBASE64(signature.sign());
	}

	/**
	 * 校验数字签名
	 * 
	 * @param data
	 *            加密数据
	 * @param publicKey
	 *            公钥
	 * @param sign
	 *            数字签名
	 * 
	 * @return 校验成功返回true 失败返回false
	 * @throws Exception
	 * 
	 */
	public static boolean verify(byte[] data, String publicKey, String sign)
			throws Exception {

		// 解密由base64编码的公钥
		byte[] keyBytes = decryptBASE64(publicKey);

		// 构造X509EncodedKeySpec对象
		X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

		// ALGORITHM 指定的加密算法
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);

		// 取公钥匙对象
		PublicKey pubKey = keyFactory.generatePublic(keySpec);

		Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
		signature.initVerify(pubKey);
		signature.update(data);

		// 验证签名是否正常
		return signature.verify(decryptBASE64(sign));
	}

	/**
	 * 生成密钥
	 * 
	 * @param seed
	 *            种子
	 * @return 密钥对象
	 * @throws Exception
	 */
	public static Map<String, Object> initKey(String seed) throws Exception {
		KeyPairGenerator keygen = KeyPairGenerator.getInstance(ALGORITHM);
		// 初始化随机产生器
		SecureRandom secureRandom = new SecureRandom();
		secureRandom.setSeed(seed.getBytes());
		keygen.initialize(KEY_SIZE, secureRandom);

		KeyPair keys = keygen.genKeyPair();

		DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
		DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();

		Map<String, Object> map = new HashMap<String, Object>(2);
		map.put(PUBLIC_KEY, publicKey);
		map.put(PRIVATE_KEY, privateKey);

		return map;
	}

	/**
	 * 默认生成密钥
	 * 
	 * @return 密钥对象
	 * @throws Exception
	 */
	public static Map<String, Object> initKey() throws Exception {
		return initKey(DEFAULT_SEED);
	}

	/**
	 * 取得私钥
	 * 
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPrivateKey(Map<String, Object> keyMap)
			throws Exception {
		Key key = (Key) keyMap.get(PRIVATE_KEY);

		return encryptBASE64(key.getEncoded());
	}

	/**
	 * 取得公钥
	 * 
	 * @param keyMap
	 * @return
	 * @throws Exception
	 */
	public static String getPublicKey(Map<String, Object> keyMap)
			throws Exception {
		Key key = (Key) keyMap.get(PUBLIC_KEY);

		return encryptBASE64(key.getEncoded());
	}
}


再给出一个测试类:
Java代码 复制代码
  1. import static org.junit.Assert.*;   
  2.   
  3. import java.util.Map;   
  4.   
  5. import org.junit.Test;   
  6.   
  7. /**  
  8.  *   
  9.  * @author 梁栋  
  10.  * @version 1.0  
  11.  * @since 1.0  
  12.  */  
  13. public class DSACoderTest {   
  14.   
  15.     @Test  
  16.     public void test() throws Exception {   
  17.         String inputStr = "abc";   
  18.         byte[] data = inputStr.getBytes();   
  19.   
  20.         // 构建密钥   
  21.         Map<String, Object> keyMap = DSACoder.initKey();   
  22.   
  23.         // 获得密钥   
  24.         String publicKey = DSACoder.getPublicKey(keyMap);   
  25.         String privateKey = DSACoder.getPrivateKey(keyMap);   
  26.   
  27.         System.err.println("公钥:/r" + publicKey);   
  28.         System.err.println("私钥:/r" + privateKey);   
  29.   
  30.         // 产生签名   
  31.         String sign = DSACoder.sign(data, privateKey);   
  32.         System.err.println("签名:/r" + sign);   
  33.   
  34.         // 验证签名   
  35.         boolean status = DSACoder.verify(data, publicKey, sign);   
  36.         System.err.println("状态:/r" + status);   
  37.         assertTrue(status);   
  38.   
  39.     }   
  40.   
  41. }  
import static org.junit.Assert.*;

import java.util.Map;

import org.junit.Test;

/**
 * 
 * @author 梁栋
 * @version 1.0
 * @since 1.0
 */
public class DSACoderTest {

	@Test
	public void test() throws Exception {
		String inputStr = "abc";
		byte[] data = inputStr.getBytes();

		// 构建密钥
		Map<String, Object> keyMap = DSACoder.initKey();

		// 获得密钥
		String publicKey = DSACoder.getPublicKey(keyMap);
		String privateKey = DSACoder.getPrivateKey(keyMap);

		System.err.println("公钥:/r" + publicKey);
		System.err.println("私钥:/r" + privateKey);

		// 产生签名
		String sign = DSACoder.sign(data, privateKey);
		System.err.println("签名:/r" + sign);

		// 验证签名
		boolean status = DSACoder.verify(data, publicKey, sign);
		System.err.println("状态:/r" + status);
		assertTrue(status);

	}

}

控制台输出:
Console代码 复制代码
  1. 公钥:   
  2. MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp   
  3. RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn   
  4. xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE   
  5. C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ   
  6. FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo   
  7. g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv   
  8. 5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9   
  9. 21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=   
  10.   
  11. 私钥:   
  12. MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2   
  13. USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4   
  14. O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC   
  15. ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB   
  16. gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR   
  17. kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q   
  18.   
  19. 签名:   
  20. MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=   
  21.   
  22. 状态:   
  23. true  


注意状态为true,就验证成功!

相关链接:
Java加密技术(一)
Java加密技术(二)
Java加密技术(三)
Java加密技术(四)
Java加密技术(五)
Java加密技术(六)
Java加密技术(七)
Java加密技术(八)
Java加密技术(九)
Java加密技术(十)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值