DSA?
DSA-Digital Signature Algorithm 是Schnorr和ElGamal簽名算法的變種,被美國NIST作為DSS(DigitalSignature Standard)。簡單的說,這是一種更高級的驗證方式,用作數字簽名。不單單只有公鑰、私鑰,還有數字簽名。私鑰加密生成數字簽名,公鑰驗證數據及簽名。如果數據和簽名不匹配則認為驗證失敗!也就是說傳輸中的數據可以不再加密,接收方獲得數據后,拿到公鑰與簽名比對數據是否有效!?
通過java代碼實現如下:Coder類見 java加密技術(一)?
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.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map; /**
* DSA安全編碼組件
*
*/
public abstract class DSACoder
extends Coder { /** * 可以使用DSA方式獲得簽名,也可以使用RSA方式獲得簽名,注意成對兒出現。 * * <code> * public static final String KEY_ALGORITHM = "RSA"; * public static final String SIGNATURE_ALGORITHM = "MD5withRSA"; * </code> **/ 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"
; /** * 用私鑰對信息生成數字簽名 * * @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(KEY_ALGORITHM); // 取私鑰匙對象 PrivateKey priKey =
keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對信息生成數字簽名 Signature signature =
Signature.getInstance(SIGNATURE_ALGORITHM); 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); // 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); // 驗證簽名是否正常 return signature.verify(decryptBASE64(sign)); } /** * 生成密鑰 * * @param seed * 種子 * @return 密鑰對象 * @throws Exception */ public static Map<String, Object> initKey(String seed)
throws Exception { KeyPairGenerator keygen =
KeyPairGenerator.getInstance(KEY_ALGORITHM); // 初始化隨機產生器 SecureRandom secureRandom =
new SecureRandom(); secureRandom.setSeed(seed.getBytes()); keygen.initialize(1024
, secureRandom); KeyPair keys =
keygen.genKeyPair(); PublicKey publicKey =
keys.getPublic(); PrivateKey privateKey =
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.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map; /**
* DSA安全編碼組件
*
*/
public abstract class DSACoder
extends Coder {
/**
* 可以使用DSA方式獲得簽名,也可以使用RSA方式獲得簽名,注意成對兒出現。
*
* <code>
* public static final String KEY_ALGORITHM = "RSA";
* public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
* </code>
**/
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"
; /**
* 用私鑰對信息生成數字簽名
*
* @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(KEY_ALGORITHM); // 取私鑰匙對象
PrivateKey priKey =
keyFactory.generatePrivate(pkcs8KeySpec); // 用私鑰對信息生成數字簽名
Signature signature =
Signature.getInstance(SIGNATURE_ALGORITHM);
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); // 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); // 驗證簽名是否正常
return signature.verify(decryptBASE64(sign));
} /**
* 生成密鑰
*
* @param seed
* 種子
* @return 密鑰對象
* @throws Exception
*/
public static Map<String, Object> initKey(String seed)
throws Exception {
KeyPairGenerator keygen =
KeyPairGenerator.getInstance(KEY_ALGORITHM);
// 初始化隨機產生器
SecureRandom secureRandom =
new SecureRandom();
secureRandom.setSeed(seed.getBytes());
keygen.initialize(1024
, secureRandom); KeyPair keys =
keygen.genKeyPair(); PublicKey publicKey =
keys.getPublic();
PrivateKey privateKey =
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());
}
} 不僅可以使用DSA算法,同樣也可以使用RSA算法做數字簽名,但要注意成對出現:
public static final String KEY_ALGORITHM = "RSA"
;
public static final String SIGNATURE_ALGORITHM = "MD5withRSA"
; 再給出一個測試類:
Java代碼
import static org.junit.Assert.*
; import java.util.Map; import org.junit.Test; /**
*
*/
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; /**
*
*/
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代碼?
公鑰:???
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?
總結
以上是生活随笔為你收集整理的JAVA加密算法(DSA)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。