接下來咱們介紹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 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);
-
- }
-
- }
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
公鑰:
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,就驗證成功!