Common digital signature algorithms RSA and DSA Java program implementation examples
- 2020-05-07 19:52:09
- OfStack
RSA encryption algorithm
let's review the encryption algorithm of RSA in 1. Starting from the definition of public key encryption algorithm and signature algorithm, we describe the 1 algorithm in a relatively standard language.
RSA public-key cryptography consists of three algorithms: KeyGen (key generation algorithm), Encrypt (encryption algorithm), and Decrypt (decryption algorithm).
The key generation algorithm takes the security constant as the input and outputs 1 public key PK and 1 private key SK. The security constant is used to determine how secure the encryption algorithm is, 1 generally depending on the size of the prime number p used by the encryption algorithm. The larger the number, the larger the prime number p1, the higher the security of the system. In RSA, the key generation algorithm is as follows: the algorithm first generates two different large prime Numbers p and q randomly, and calculates N=pq. Then the algorithm computes the euler function. Next, the algorithm randomly selects an integer e that is smaller than e, and computes the modular inverse element d of e. Finally, the public key is PK=(N, e), and the private key is SK= (N, d).
The encryption algorithm takes the public key PK and the message M to be encrypted as input and outputs the ciphertext CT. In RSA, the encryption algorithm is as follows: the algorithm directly outputs the ciphertext as
The decryption algorithm takes the private key SK and the ciphertext CT as input and outputs the message M. In RSA, the decryption algorithm is as follows: the algorithm directly outputs the plaintext as. Since e and d are inverses at the bottom, we have:
Therefore, we can also see from the algorithm description that the public key is used to encrypt the data, and the private key is used to decrypt the data. Of course, this also makes intuitive sense: the public key is the public key, and you can use it to encrypt data if it's public. The private key is the private key, who has this key can decrypt the ciphertext. Otherwise, if everyone can see the private key, they can decrypt it.
Let's take a look at 1 simple implementation in Java:
package com.stone.security;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Arrays;
import javax.crypto.Cipher;
/**
* RSA algorithm Public key encryption Asymmetric encryption
*/
public class RSA {
public static final String KEY_ALGORITHM = "RSA";
public static final String CIPHER_ALGORITHM_ECB1 = "RSA/ECB/PKCS1Padding";
public static final String CIPHER_ALGORITHM_ECB2 = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; // Can't use
public static final String CIPHER_ALGORITHM_ECB3 = "OAEPWithSHA-256AndMGF1Padding"; // Can't use
static PublicKey publicKey;
static PrivateKey privateKey;
static Cipher cipher;
static KeyPair keyPair;
public static void main(String[] args) throws Exception {
method1(" skoda U*(Sfsad7f()*^%%$");
method2(" skoda U*(Sfsad7f()*^%%$");
method3(" skoda U*(Sfsad7f()*^%%$");
}
/**
* Public key encryption, private key decryption Use the default CIPHER_ALGORITHM_ECB1
* @param str
* @throws Exception
*/
static void method1(String str) throws Exception {
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
KeyPair keyPair = keyGenerator.generateKeyPair();
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey); // Public key encryption
byte[] encrypt = cipher.doFinal(str.getBytes());
System.out.println(" After public key encryption 1 : " + Arrays.toString(encrypt));
cipher.init(Cipher.DECRYPT_MODE, privateKey);// Private key to decrypt the
byte[] decrypt = cipher.doFinal(encrypt);
System.out.println(" After the private key is decrypted 1 : " + new String(decrypt));
}
/**
* The private key is encrypted and the public key is decrypted Use the default CIPHER_ALGORITHM_ECB1
* @param str
* @throws Exception
*/
static void method2(String str) throws Exception {
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
KeyPair keyPair = keyGenerator.generateKeyPair();
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, privateKey); // The private key encryption
byte[] encrypt = cipher.doFinal(str.getBytes());
System.out.println(" After the private key is encrypted 2 : " + Arrays.toString(encrypt));
cipher.init(Cipher.DECRYPT_MODE, publicKey);// A public key to decrypt
byte[] decrypt = cipher.doFinal(encrypt);
System.out.println(" Public key decrypted 2 : " + new String(decrypt));
}
/**
* The private key is encrypted and the public key is decrypted use CIPHER_ALGORITHM_ECB1 = RSA/ECB/PKCS1Padding
* @param str
* @throws Exception
*/
static void method3(String str) throws Exception {
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
KeyPair keyPair = keyGenerator.generateKeyPair();
publicKey = keyPair.getPublic();
privateKey = keyPair.getPrivate();
cipher = Cipher.getInstance(CIPHER_ALGORITHM_ECB1);
cipher.init(Cipher.ENCRYPT_MODE, privateKey); // The private key encryption
byte[] encrypt = cipher.doFinal(str.getBytes());
System.out.println(" After the private key is encrypted 3 : " + Arrays.toString(encrypt));
cipher.init(Cipher.DECRYPT_MODE, publicKey);// A public key to decrypt
byte[] decrypt = cipher.doFinal(encrypt);
System.out.println(" Public key decrypted 3 : " + new String(decrypt));
}
}
DSA algorithm and digital signature
DSA 1 is commonly used for digital signatures and authentication.
DSA is a variant of Schnorr and ElGamal signature algorithms, and is used by NIST as DSS (DigitalSignature Standard).
DSA is based on the discrete logarithm problem of integer finite field, and its security is similar to RSA.
In DSA digital signature and authentication, the sender signs the file or message using his private key, and the receiver receives the message using the sender's public key
To verify the authenticity of the signature. DSA is just one algorithm. Unlike RSA, it cannot be used for encryption and decryption, and it cannot be used for key exchange.
For signature only, it is much faster than RSA.
package com.stone.security;
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;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
/**
* DSA-Digital Signature Algorithm is Schnorr and ElGamal A variant of the signature algorithm, by the United States NIST As a DSS(DigitalSignature Standard) .
* In short, this is 1 A more advanced verification method used as a digital signature. Not only the public key, the private key, but also the digital signature. Private key encryption generates digital signature, public key verification data and signature.
* If the data and signature do not match, the validation fails! namely Data in transit Can no longer encrypt, after receiving the data, get the public key and signature Verify that the data is valid
*/
public class DSA {
/**
* Not only can you use DSA The algorithm, again, can be used RSA Algorithms do digital signatures
*/
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";
public static final String DEFAULT_SEED = "$%^*%^()(HJG8awfjas7"; // The default seed
public static final String PUBLIC_KEY = "DSAPublicKey";
public static final String PRIVATE_KEY = "DSAPrivateKey";
public static void main(String[] args) throws Exception {
String str = "!@#$!#^$#&ZXVDF Dang military road loves you *()_+";
byte[] data = str.getBytes();
Map<String, Object> keyMap = initKey();// Construction of the key
PublicKey publicKey = (PublicKey) keyMap.get(PUBLIC_KEY);
PrivateKey privateKey = (PrivateKey) keyMap.get(PRIVATE_KEY);
System.out.println(" The private key format : " + privateKey.getFormat());
System.out.println(" The public key format : " + publicKey.getFormat());
// Generate the signature
String sign = sign(data, getPrivateKey(keyMap));
// Verify the signature
boolean verify1 = verify("aaa".getBytes(), getPublicKey(keyMap), sign);
System.err.println(" verified Data and signature match :" + verify1);
boolean verify = verify(data, getPublicKey(keyMap), sign);
System.err.println(" verified Data and signature match :" + verify);
}
/**
* Generate the key
*
* @param seed seeds
* @return The key object
* @throws Exception
*/
public static Map<String, Object> initKey(String seed) throws Exception {
System.out.println(" Generate the key ");
KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = new SecureRandom();
secureRandom.setSeed(seed.getBytes());
//Modulus size must range from 512 to 1024 and be a multiple of 64
keygen.initialize(640, secureRandom);
KeyPair keys = keygen.genKeyPair();
PrivateKey privateKey = keys.getPrivate();
PublicKey publicKey = keys.getPublic();
Map<String, Object> map = new HashMap<String, Object>(2);
map.put(PUBLIC_KEY, publicKey);
map.put(PRIVATE_KEY, privateKey);
return map;
}
/**
* Generate default key
*
* @return The key object
* @throws Exception
*/
public static Map<String, Object> initKey() throws Exception {
return initKey(DEFAULT_SEED);
}
/**
* Get the private key
*
* @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()); //base64 Encryption private key
}
/**
* In public key
*
* @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()); //base64 Encryption, public key
}
/**
* The information is digitally signed with the private key
* @param data Encrypt the data
* @param privateKey The private key -base64 encrypted
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
System.out.println(" The information is digitally signed with the private key ");
byte[] keyBytes = decryptBASE64(privateKey);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory factory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey priKey = factory.generatePrivate(keySpec);// generate The private key
// The information is digitally signed with the private key
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* BASE64Encoder encryption
* @param data The data to be encrypted
* @return The encrypted string
*/
private static String encryptBASE64(byte[] data) {
BASE64Encoder encoder = new BASE64Encoder();
String encode = encoder.encode(data);
return encode;
}
/**
* BASE64Decoder decryption
* @param data The string to decrypt
* @return decrypted byte[]
* @throws Exception
*/
private static byte[] decryptBASE64(String data) throws Exception {
BASE64Decoder decoder = new BASE64Decoder();
byte[] buffer = decoder.decodeBuffer(data);
return buffer;
}
/**
* Check digital signature
* @param data Encrypt the data
* @param publicKey
* @param sign A digital signature
* @return
* @throws Exception
*/
public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
byte[] keyBytes = decryptBASE64(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
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)); // Verify the signature
}
}