DSA
DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!也就是说传输中的数据可以不再加密,接收方获得数据后,拿到公钥与签名比对数据是否有效!
通过java代码实现如下:Coder类见 java加密技术(一)
Java代码
importjava.security.Key;importjava.security.KeyFactory;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.security.SecureRandom;importjava.security.Signature;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;importjava.util.HashMap;importjava.util.Map;/*** DSA安全编码组件
**/
public abstract class DSACoder extendsCoder {/*** 可以使用DSA方式获得签名,也可以使用RSA方式获得签名,注意成对儿出现。
*
*
* public static final String KEY_ALGORITHM = "RSA";
* public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
*
**/
public static final String KEY_ALGORITHM = "DSA";public static final String SIGNATURE_ALGORITHM = "DSA";/*** 默认种子*/
private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";private static final String PUBLIC_KEY = "DSAPublicKey";private static final String PRIVATE_KEY = "DSAPrivateKey";/*** 用私钥对信息生成数字签名
*
*@paramdata
* 加密数据
*@paramprivateKey
* 私钥
*@return*@throwsException*/
public static String sign(byte[] data, String privateKey) throwsException {//解密由base64编码的私钥
byte[] keyBytes =decryptBASE64(privateKey);//构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = newPKCS8EncodedKeySpec(keyBytes);//KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory =KeyFactory.getInstance(KEY_ALGORITHM);//取私钥匙对象
PrivateKey priKey =keyFactory.generatePrivate(pkcs8KeySpec);//用私钥对信息生成数字签名
Signature signature =Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);returnencryptBASE64(signature.sign());
}/*** 校验数字签名
*@paramdata
* 加密数据
*@parampublicKey
* 公钥
*@paramsign
* 数字签名
*
*@return校验成功返回true 失败返回false
*@throwsException
**/
public static boolean verify(byte[] data, String publicKey, String sign)throwsException {//解密由base64编码的公钥
byte[] keyBytes =decryptBASE64(publicKey);//构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = newX509EncodedKeySpec(keyBytes);//KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory =KeyFactory.getInstance(KEY_ALGORITHM);//取公钥匙对象
PublicKey pubKey =keyFactory.generatePublic(keySpec);
Signature signature=Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);//验证签名是否正常
returnsignature.verify(decryptBASE64(sign));
}/*** 生成密钥
*
*@paramseed
* 种子
*@return密钥对象
*@throwsException*/
public static Map initKey(String seed) throwsException {
KeyPairGenerator keygen=KeyPairGenerator.getInstance(KEY_ALGORITHM);//初始化随机产生器
SecureRandom secureRandom = newSecureRandom();
secureRandom.setSeed(seed.getBytes());
keygen.initialize(1024, secureRandom);
KeyPair keys=keygen.genKeyPair();
PublicKey publicKey=keys.getPublic();
PrivateKey privateKey=keys.getPrivate();
Map map = new HashMap(2);
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);returnmap;
}/*** 默认生成密钥
*
*@return密钥对象
*@throwsException*/
public static Map initKey() throwsException {returninitKey(DEFAULT_SEED);
}/*** 取得私钥
*
*@paramkeyMap
*@return*@throwsException*/
public static String getPrivateKey(MapkeyMap)throwsException {
Key key=(Key) keyMap.get(PRIVATE_KEY);returnencryptBASE64(key.getEncoded());
}/*** 取得公钥
*
*@paramkeyMap
*@return*@throwsException*/
public static String getPublicKey(MapkeyMap)throwsException {
Key key=(Key) keyMap.get(PUBLIC_KEY);returnencryptBASE64(key.getEncoded());
}
}importjava.security.Key;importjava.security.KeyFactory;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.PrivateKey;importjava.security.PublicKey;importjava.security.SecureRandom;importjava.security.Signature;importjava.security.spec.PKCS8EncodedKeySpec;importjava.security.spec.X509EncodedKeySpec;importjava.util.HashMap;importjava.util.Map;/*** DSA安全编码组件
**/
public abstract class DSACoder extendsCoder {/*** 可以使用DSA方式获得签名,也可以使用RSA方式获得签名,注意成对儿出现。
*
*
* public static final String KEY_ALGORITHM = "RSA";
* public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
*
**/
public static final String KEY_ALGORITHM = "DSA";public static final String SIGNATURE_ALGORITHM = "DSA";/*** 默认种子*/
private static final String DEFAULT_SEED = "0f22507a10bbddd07d8a3082122966e3";private static final String PUBLIC_KEY = "DSAPublicKey";private static final String PRIVATE_KEY = "DSAPrivateKey";/*** 用私钥对信息生成数字签名
*
*@paramdata
* 加密数据
*@paramprivateKey
* 私钥
*@return*@throwsException*/
public static String sign(byte[] data, String privateKey) throwsException {//解密由base64编码的私钥
byte[] keyBytes =decryptBASE64(privateKey);//构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = newPKCS8EncodedKeySpec(keyBytes);//KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory =KeyFactory.getInstance(KEY_ALGORITHM);//取私钥匙对象
PrivateKey priKey =keyFactory.generatePrivate(pkcs8KeySpec);//用私钥对信息生成数字签名
Signature signature =Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);returnencryptBASE64(signature.sign());
}/*** 校验数字签名
*@paramdata
* 加密数据
*@parampublicKey
* 公钥
*@paramsign
* 数字签名
*
*@return校验成功返回true 失败返回false
*@throwsException
**/
public static boolean verify(byte[] data, String publicKey, String sign)throwsException {//解密由base64编码的公钥
byte[] keyBytes =decryptBASE64(publicKey);//构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = newX509EncodedKeySpec(keyBytes);//KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory =KeyFactory.getInstance(KEY_ALGORITHM);//取公钥匙对象
PublicKey pubKey =keyFactory.generatePublic(keySpec);
Signature signature=Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);//验证签名是否正常
returnsignature.verify(decryptBASE64(sign));
}/*** 生成密钥
*
*@paramseed
* 种子
*@return密钥对象
*@throwsException*/
public static Map initKey(String seed) throwsException {
KeyPairGenerator keygen=KeyPairGenerator.getInstance(KEY_ALGORITHM);//初始化随机产生器
SecureRandom secureRandom = newSecureRandom();
secureRandom.setSeed(seed.getBytes());
keygen.initialize(1024, secureRandom);
KeyPair keys=keygen.genKeyPair();
PublicKey publicKey=keys.getPublic();
PrivateKey privateKey=keys.getPrivate();
Map map = new HashMap(2);
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);returnmap;
}/*** 默认生成密钥
*
*@return密钥对象
*@throwsException*/
public static Map initKey() throwsException {returninitKey(DEFAULT_SEED);
}/*** 取得私钥
*
*@paramkeyMap
*@return*@throwsException*/
public static String getPrivateKey(MapkeyMap)throwsException {
Key key=(Key) keyMap.get(PRIVATE_KEY);returnencryptBASE64(key.getEncoded());
}/*** 取得公钥
*
*@paramkeyMap
*@return*@throwsException*/
public static String getPublicKey(MapkeyMap)throwsException {
Key key=(Key) keyMap.get(PUBLIC_KEY);returnencryptBASE64(key.getEncoded());
}
}
不仅可以使用DSA算法,同样也可以使用RSA算法做数字签名,但要注意成对出现:public static final String KEY_ALGORITHM = "RSA";public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
再给出一个测试类:
Java代码import static org.junit.Assert.*;importjava.util.Map;importorg.junit.Test;/****/
public classDSACoderTest {
@Testpublic void test() throwsException {
String inputStr= "abc";byte[] data =inputStr.getBytes();//构建密钥
Map 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);
}
}import static org.junit.Assert.*;importjava.util.Map;importorg.junit.Test;/****/
public classDSACoderTest {
@Testpublic void test() throwsException {
String inputStr= "abc";byte[] data =inputStr.getBytes();//构建密钥
Map 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代码
公钥:
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
公钥:
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