`

Java加密技术(六)——数字签名算法DSA

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


通过java代码实现如下:Coder类见 Java加密技术(一)
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());
	}
}


再给出一个测试类:
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);

	}

}

控制台输出:
公钥:
MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZp
RV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fn
xqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuE
C/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJ
FnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImo
g9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAIu4RUlcQLp49PI0MrbssOY+3uySVnp0TULSv
5T4VaHoKzsLHgGTrwOvsGA+V3yCNl2WDu3D84bSLF7liTWgOj+SMOEaPk4VyRTlLXZWGPsf1Mfd9
21XAbMeVyKDSHHVGbMjBScajf3bXooYQMlyoHiOt/WrCo+mv7efstMM0PGo=

私钥:
MIIBTAIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2
USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4
O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmC
ouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCB
gLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhR
kImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFwIVAIegLUtmm2oQKQJTOiLugHTSjl/q

签名:
MC0CFQCMg0J/uZmF8GuRpr3TNq48w60nDwIUJCyYNah+HtbU6NcQfy8Ac6LeLQs=

状态:
true


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



相关链接:
Java加密技术(一)——BASE64与单向加密算法MD5&SHA&MAC
Java加密技术(二)——对称加密DES&AES
Java加密技术(三)——PBE算法
Java加密技术(四)——非对称加密算法RSA
Java加密技术(五)——非对称加密算法的由来
Java加密技术(六)——数字签名算法DSA
Java加密技术(七)——非对称加密算法最高ECC
Java加密技术(八)——数字证书
Java加密技术(九)——初探SSL
Java加密技术(十)——单向认证
Java加密技术(十一)——双向认证
Java加密技术(十二)——*.PFX(*.p12)&个人信息交换文件
  • 描述: DSA交互序列图 1 ——甲方发送数据
  • 大小: 12.7 KB
  • 描述: DSA交互序列图 2 ——甲方发送数据
  • 大小: 19.1 KB
25
2
分享到:
评论
3 楼 jieweier733 2014-11-13  
2 楼 bsc2xp 2013-11-27  
如果能获取到 certificate 的签名算法,那 KeyFactory 的算法实际也就已经确定了,也就是说对于一个 sign(.....) 方法来说,参数里只需要一个证书的签名算法就够了对么?
1 楼 bsc2xp 2013-11-27  
KeyFactory.getInstance("DSA");
Signature.getInstane("DSA");

后者的 DSA 实际是 SHA1withDSA 的别名对么?这么写是不是不算标准?
查看 jvm 的 Provider 信息能看到算法为 DSA 的 服务类型没有 Cipher,那意思就是说不能用做加密,而算法为 RSA 的服务类型没有 signature,所以不能用作签名,能用作签名的算法只有 XXXXwithRSA,这么理解对么?

相关推荐

    Java密码学(5)——数字签名算法

    总结来说,Java中的数字签名算法是通过非对称加密和散列函数相结合的方式,提供了数据完整性和发送者身份验证的能力。`CoderUtil.java`可能是一个辅助工具,用于简化数字签名的生成和验证过程。了解并熟练掌握数字...

    网络安全技术应用——数字签名技术在Java中的实现.pdf

    其核心是采用加密技术的加、解密算法体制来实现对信息的数字签名。数字签名技术的应用范围非常广泛,在保障电子数据交换的安全性上是一个突破性的进展。 在数字签名技术中,发送者使用秘密密钥对报文进行加密,将...

    非对称加密算法 数字签名算法

    同时,文件中的`非对称加密算法 数字签名算法——RSA - 信息安全 - ITeye知识库频道_files`可能包含更多示例代码和详细解释,有助于进一步学习和实践。 总之,非对称加密算法和数字签名是保障网络通信安全的重要...

    java各种加密算法

    DSA(Digital Signature Algorithm)是一种基于离散对数问题的数字签名算法,主要用于创建数字签名而非加密数据。在Java中,可以使用`java.security.KeyPairGenerator`类生成DSA密钥对,并通过`java.security....

    pdf.rar_java数字水印_pdf_pdf签名_数字签名_签名

    它通过使用公钥加密技术,将签名者的私钥与文档的哈希值结合,形成一个数字签名。用户可以使用PDF阅读器检查签名,确保文档自签名后未被修改。签名还可以包含证书信息,提供签发者身份的可信度。在Java中,可以使用...

    基于java的数字签名、数字证书生成源码.zip

    这个过程包括选择合适的算法(如RSA或DSA),对原始数据进行哈希运算,然后使用私钥对哈希结果进行加密,生成的就是数字签名。 数字证书则是一种包含公钥和相关身份信息的电子文档,通常由可信的第三方机构——证书...

    JAVA的加密算法及应用

    ### JAVA的加密算法及应用 #### 一、引言 随着信息技术的快速发展,信息安全成为了企业和个人关注的重点。...随着技术的发展,新的加密技术和算法也将不断涌现,未来的信息安全领域将会更加丰富多彩。

    基于Java的实例源码-数字签名、数字证书生成源码.zip

    在Java中,`java.security`包提供了实现数字签名的相关类,如`Signature`,它支持各种算法,如RSA、DSA等。 数字证书则是一种包含公钥和相关身份信息的电子文档,通常由可信的第三方机构——证书颁发机构(CA)签署...

    Java经典算法--加密算法

    ### Java经典算法——加密算法详解 #### 一、概述 在现代信息技术中,加密技术扮演着至关重要的角色,尤其是在保障数据安全与隐私方面。本文将详细介绍几种常用的加密算法及其在Java中的实现方式。 #### 二、对称...

    Java 数字签名、数字证书生成源码

    数字签名是一种用于验证电子信息完整性的方法,它结合了非对称加密技术。在Java中,我们可以使用`java.security`包中的类来实现这一功能。例如,`Signature`类提供了数字签名的生成和验证接口。生成数字签名通常包括...

    Java加密解密方法大全

    - DSA(Digital Signature Algorithm):专门用于数字签名的标准算法。 ##### 3.3 单向加密算法 单向加密算法(也称为哈希函数)主要用于验证数据的完整性和一致性。一旦数据被哈希处理,就无法从哈希值反推出...

    JAVA上加密算法的实现用例

    数字签名是利用公钥加密原理来确认信息来源和保障信息未被篡改的技术。发送方使用私钥对信息的摘要进行加密,形成数字签名。接收方则使用发送方的公钥验证签名,确保信息的完整性和发送方的身份。这一过程中,HASH...

    基于Java的实例源码-加密库 BeeCrypt.zip

    2. **非对称加密**:如RSA、DSA(数字签名算法)或ECC(椭圆曲线加密),使用一对公钥和私钥,公钥用于加密,私钥用于解密,增强了安全性。 3. **哈希函数**:如MD5、SHA-1或SHA-256,用于生成数据的固定长度摘要,...

    java加密代码

    ### Java加密技术概览 在Java中实现加密通常涉及到对称加密、非对对称加密(公钥/私钥加密)以及散列函数等多种方式。这些加密方法被广泛应用于保护数据安全、确保通信隐私等领域。 #### 1. 对称加密 对称加密是...

    java源代码Java课程设计Java

    在本Java课程设计中,我们将深入探讨Java编程语言的核心特性,包括线程管理和加密技术,同时结合实际项目经验,提供一份详细的实验报告和课程设计。这些主题是Java开发者必备的知识,无论是在学术研究还是在软件开发...

    非对称加密传输文件相关技术理论浅析

    在非对称加密中,常见的算法有RSA、ECC(椭圆曲线加密)和DSA(数字签名算法)。RSA是最早被广泛应用的非对称加密算法,它的安全性基于大整数因子分解的难度;ECC则以其更高的安全性与效率成为一种现代选择,尽管...

    非对称加密的案例

    在Java中,非对称加密的实现主要包括RSA、DSA和ECC等算法。RSA是最常见的一种,它基于数论上的大数因子分解难题。Java的`java.security`包提供了实现这些算法的接口和类,如`KeyPairGenerator`用于生成密钥对,`...

Global site tag (gtag.js) - Google Analytics