DSA
DSA-Digital Signature Algorithm 是Schnorr和ElGamal簽名算法的變種,被美國NIST做爲DSS(DigitalSignature Standard)。簡單的說,這是一種更高級的驗證方式,用做數字簽名。不僅僅只有公鑰、私鑰,還有數字簽名。私鑰加密生成數字簽名,公鑰驗證數據及簽名。若是數據和簽名不匹配則認爲驗證失敗!也就是說傳輸中的數據能夠再也不加密,接收方得到數據後,拿到公鑰與簽名比對數據是否有效!
經過java代碼實現以下:Coder類見 java加密技術(一)
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 git