DSA为非对称加密,非对称加密指加密与解密所使用的密钥不同,分为公钥和私钥,DSA还有数字签名。例如:app发起支付时,使用私钥(私钥一般放服务器用时获取)对订单串生成签名,然后将订单串与签名一起传给服务器,服务器使用公钥和订单串进行签名校验,返回true表示校验通过,否则订单信息就是伪造的。
使用:
public class DSAUtil {
private static final String algorithm = "DSA";
private static final String KEY_PUBLIC = "PublicKey";
private static final String KEY_PRIVATE = "PrivateKey";
/**
* 生成公钥串、私钥串
*
* @return Base64编码过的公钥串、Base64编码过的私钥串
*/
public static Map<String, String> generatorKey() {
Map<String, String> map = new HashMap<String, String>();
try {
KeyPairGenerator keygen = KeyPairGenerator.getInstance(algorithm);
// 创建随机产生器
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed("abcdefg".getBytes());
keygen.initialize(1024, secureRandom);
KeyPair keys = keygen.genKeyPair();
// 生成公钥
DSAPublicKey publicKey = (DSAPublicKey) keys.getPublic();
map.put(KEY_PUBLIC, Base64.encode(publicKey.getEncoded()));
// 生成私钥
DSAPrivateKey privateKey = (DSAPrivateKey) keys.getPrivate();
map.put(KEY_PRIVATE, Base64.encode(privateKey.getEncoded()));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return map;
}
/**
* 用私钥对订单串进行签名
*
* @param orderInfo 未加密订单串
* @param privateKey Base64编码过的私钥串
*
* @return Base64编码过的签名串
*/
public static String generatorSign(String orderInfo, String privateKey) {
try {
// 根据私钥byte[]创建PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
// 指定DSA加密算法
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
// 取得私钥对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对订单串进行签名
Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
signature.initSign(priKey);
signature.update(orderInfo.getBytes());
// 对私钥进行Base64编码
return Base64.encode(signature.sign());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 校验数字签名
*
* @param orderInfo 未加密订单串
* @param publicKey Base64编码过的公钥串
* @param sign Base64编码过的签名串
*
* @return 校验成功返回true, 校验失败返回false
*/
public static boolean verifySign(String orderInfo, String publicKey, String sign) {
try {
// 根据公钥byte[]创建X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decode(publicKey));
// 指定DSA加密算法
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
// 取公钥对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
// 根据公钥和待加密串初始化Signature
Signature signature = Signature.getInstance(keyFactory.getAlgorithm());
signature.initVerify(pubKey);
signature.update(orderInfo.getBytes());
// 根据公钥和订单串进行签名校验,通过表示正常,否则表示订单串是伪造的。
return signature.verify(Base64.decode(sign));
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
// // 产生公钥和私钥,保存起来下次使用
// Map<String, String> keyMap = generatorKey();
// // 获得公钥
// String publicKey = keyMap.get(KEY_PUBLIC);
// // 获得私钥
// String privateKey = keyMap.get(KEY_PRIVATE);
// System.err.println("公钥 : " + publicKey);
// System.err.println("私钥 : " + privateKey);
String privateKey = "MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoEFgIUFzPw6lbL1g8H4Nj89G55StSxqPQ=";
String publicKey = "MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUjC8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAdFQMgDfhSx4MMvmtjRBvEnS+Q6RVLqbi2aweBsQKpsg48FtnJed/MaPhNWonsXltK/9rdeh59rws61FsoLy7A6AA+jYydqIcOG2vK9u94HDg3ueEttZ5of3/KP6bsFLiivfLqMefi9MOGyIafaffpGA+UPI4tPh1E0GH53TnCaI=";
// 待签名的订单串
String orderInfo = "orderId=1001&price=10.1&desc=书本&num=1";
// 产生签名
String sign = generatorSign(orderInfo, privateKey);
System.err.println("签名 : " + sign);
// 验证签名
boolean result = verifySign(orderInfo, publicKey, sign);
System.err.println("签名校验结果: " + result);
}
}