Whether user data is stored in SharePreferences or in a SQLite database, it is necessary to encrypt key data. There are many encryption algorithms. Commonly used are MD5, RSA, AES, and 3DES.
MD5 is an irreversible encryption algorithm, that is, it cannot be decrypted. It is mainly used for user password encryption on the client side. The encryption code of the MD5 algorithm is as follows:
public class MD5Util{
public static String encryp(String raw){
String md5Str=raw;
try{
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(raw.getBytes());
byte[] encryContext=md.digets();
int i;
StringBuffer buf=new StringBuffer("");
for(int offset=0;offset<encryContext.length;offset++){
i=encryContext[offset];
if(i<0){
i+=256;
}
if(i<16){
buf.append("0");
}
buf.append(Integer.toHexString(i));
}
md5Str=buf.toString();
}catch(NOSuchAlgorithmException e){
e.printStackTrace();
}
return md5Str;
}
}
The RSA algorithm uses public key encryption on the client side and private key decryption on the server side. In this way, even if the encrypted public key is compromised, no private key can still be decrypted.
The following are three considerations for RSA encryption.
(1) The dependency package bcprov-jdk16-1.46.jar of the encryption algorithm needs to be imported, and the jar package should be placed in the libs directory of the current module.
(2) The result of RSA encryption is a byte array, which can be encoded by BASE64 to form the final encrypted string.
(3) Reverse reverse processing of the string before encryption according to requirements.
public class RSAUtil {
private static final String TAG = "RSAUtil";
private static final String Algorithm = "RSA";
private static String RSAKeyStore = "E:/RSAKey.txt";
////Generate key pair
private static KeyPair generateKeyPair() throws Exception {
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(Algorithm,
new org.bouncycastle.jce.provider.BouncyCastleProvider());
//// This value is related to the size of the block encryption and can be changed, but not too big, otherwise the efficiency will decrease.
final int KEY_SIZE = 1024;
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
saveKeyPair(keyPair);
return keyPair;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
private static KeyPair getKeyPair() throws Exception {
FileInputStream fis = new FileInputStream(RSAKeyStore);
ObjectInputStream oos = new ObjectInputStream(fis);
KeyPair kp = (KeyPair) oos.readObject();
oos.close();
fis.close();
return kp;
}
private static void saveKeyPair(KeyPair kp) throws Exception {
FileOutputStream fos = new FileOutputStream(RSAKeyStore);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(kp);
oos.close();
fos.close();
}
////Generate public key
private static RSAPublicKey generateRSAPublicKey(byte[] modulus,
byte[] publicExponent) throws Exception {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance(Algorithm,
new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
modulus), new BigInteger(publicExponent));
try {
return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
////Generate private key
private static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
byte[] privateExponent) throws Exception {
KeyFactory keyFac = null;
try {
keyFac = KeyFactory.getInstance(Algorithm,
new org.bouncycastle.jce.provider.BouncyCastleProvider());
} catch (NoSuchAlgorithmException ex) {
throw new Exception(ex.getMessage());
}
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(
modulus), new BigInteger(privateExponent));
try {
return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
} catch (InvalidKeySpecException ex) {
throw new Exception(ex.getMessage());
}
}
//// Restore the public key by public key byte[], suitable for RSA algorithm
private static PublicKey getPublicKey(byte[] keyBytes)
throws NoSuchAlgorithmException, InvalidKeySpecException {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(Algorithm);
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
//// Restore the public key with the private key byte[], suitable for RSA algorithm
private static PrivateKey getPrivateKey(byte[] keyBytes)
throws NoSuchAlgorithmException, InvalidKeySpecException {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(Algorithm);
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
////Encryption
private static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
try {
Cipher cipher = Cipher.getInstance(Algorithm,
new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, pk);
int blockSize = cipher.getBlockSize();
int outputSize = cipher.getOutputSize(data.length);
int leavedSize = data.length % blockSize;
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
: data.length / blockSize;
byte[] raw = new byte[outputSize * blocksSize];
int i = 0;
while (data.length - i * blockSize > 0) {
if (data.length - i * blockSize > blockSize) {
cipher.doFinal(data, i * blockSize, blockSize, raw, i * outputSize);
} else {
cipher.doFinal(data, i * blockSize, data.length - i * blockSize, raw, i * outputSize);
}
i++;
}
return raw;
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
//decrypt
private static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
try {
Cipher cipher = Cipher.getInstance(Algorithm,
new org.bouncycastle.jce.provider.BouncyCastleProvider());
cipher.init(cipher.DECRYPT_MODE, pk);
int blockSize = cipher.getBlockSize();
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
int j = 0;
while (raw.length - j * blockSize > 0) {
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
j++;
}
return bout.toByteArray();
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
/ / Use the N, e value to restore the public key
private static PublicKey getPublicKey(String modulus, String publicExponent, int radix)
throws NoSuchAlgorithmException, InvalidKeySpecException {
BigInteger bigIntModulus = new BigInteger(modulus, radix);
BigInteger bigIntPrivateExponent = new BigInteger(publicExponent, radix);
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,
bigIntPrivateExponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/ / Use N, d values to restore the private key
private static PrivateKey getPrivateKey(String modulus, String privateExponent, int radix)
throws NoSuchAlgorithmException, InvalidKeySpecException {
BigInteger bigIntModulus = new BigInteger(modulus, radix);
BigInteger bigIntPrivateExponent = new BigInteger(privateExponent, radix);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,
bigIntPrivateExponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/ / encryption function
public static String encodeRSA(RSAKeyData key_data, String src) {
if (key_data == null) {
//Default key pair
key_data = new RSAKeyData();
key_data.public_key = "10001";
key_data.private_key = "";
key_data.modulus = "c7f668eccc579bb75527424c21be31c104bb44c921b4788ebc82cddab5042909eaea2dd706431531392d79890f9091e13714285a7e79e9d1836397f847046ef2519c9b65022b48bf157fe409f8a42155734e65467d04ac844dfa0c2ae512517102986ba9b62d67d4c920eae40b2f11c363b218a703467d342faa81719f57e2c3";
key_data.radix = 16;
}
try {
PublicKey key = getPublicKey(key_data.modulus, key_data.public_key, key_data.radix);
String rev = encodeURL(new StringBuilder(src).reverse().toString());
byte[] en_byte = encrypt(key, rev.getBytes());
String base64 = encodeURL(ConvertBytesToBase64.BytesToBase64String(en_byte));
return base64;
} catch (Exception e) {
e.printStackTrace();
Return "RSA encryption failed";
}
}
//URL encoding
private static String encodeURL(String str) {
String encode_str = str;
try {
encode_str = URLEncoder.encode(str, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return encode_str;
}
//URL decoding
private static String decodeURL(String str) {
String decode_str = str;
try {
decode_str = URLDecoder.decode(str, "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return decode_str;
}
public static class RSAKeyData {
public String modulus;
public String public_key;
public String private_key;
public int radix;
public RSAKeyData() {
modulus = "";
public_key = "";
private_key = "";
radix = 0;
}
}
}
AES is an advanced encryption algorithm designed to replace DES. (The algorithm is a reversible algorithm that supports decryption of encrypted strings, provided that the decryption is that the key must be identical to the encryption).
Below is the code for encryption and decryption of the algorithm.
public class AesUtil {
private static final String Algorithm = "AES";
private final static String HEX = "0123456789ABCDEF";
//Encryption function. Key is the key
public static String encrypt(String key, String src) throws Exception {
byte[] rawKey = getRawKey(key.getBytes());
byte[] result = encrypt(rawKey, src.getBytes());
return toHex(result);
}
/ / Decrypt function. The key value must match the key at the time of encryption.
public static String decrypt(String key, String encrypted) throws Exception {
byte[] rawKey = getRawKey(key.getBytes());
byte[] enc = toByte(encrypted);
byte[] result = decrypt(rawKey, enc);
return new String(result);
}
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance(Algorithm);
// SHA1PRNG strong random seed algorithm, to distinguish the calling method of Android 4.2.2 or later
SecureRandom sr = null;
if (android.os.Build.VERSION.SDK_INT >= 17) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(seed);
Kgen.init(256, sr); // 256-bit or 128-bit or 192-bit
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] key, byte[] src) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm);
Cipher cipher = Cipher.getInstance(Algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(src);
return encrypted;
}
private static byte[] decrypt(byte[] key, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm);
Cipher cipher = Cipher.getInstance(Algorithm);
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
private static byte[] toByte(String hexString) {
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++) {
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
}
return result;
}
private static String toHex(byte[] buf) {
if (buf == null) {
return "";
}
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
}
3DES (tripe DES) is a triple data encryption algorithm, which is equivalent to applying 3 DES encryption algorithms to each data block. The 3DE algorithm prevents encrypted data from being cracked by increasing the length of the key. In actual development, the 3DES key must be a 24-bit byte array. If it is too short or too long, it will report java.security.InvalidKeyException at runtime. In addition, 3DES encryption generates a byte array, and it is also necessary to encode the encrypted string in the form of bit text through BASE64.
The encryption and decryption code for this algorithm is as follows:
public class Des3Util {
// Define the encryption algorithm, DESede is 3DES
private static final String Algorithm = "DESede";
//Encryption function. Key is the key
public static String encrypt(String key, String raw) {
byte[] enBytes = encryptMode(key, raw.getBytes());
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(enBytes);
}
/ / Decrypt function. The key value must match the key at the time of encryption.
public static String decrypt(String key, String enc) {
try {
BASE64Decoder decoder = new BASE64Decoder();
byte[] enBytes = decoder.decodeBuffer(enc);
byte[] deBytes = decryptMode(key, enBytes);
return new String(deBytes);
} catch (IOException e) {
e.printStackTrace();
return enc;
}
}
private static byte[] encryptMode(String key, byte[] src) {
try {
SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm);
Cipher cipher = Cipher.getInstance(Algorithm);
cipher.init(Cipher.ENCRYPT_MODE, deskey);
return cipher.doFinal(src);
}catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static byte[] decryptMode(String key, byte[] src) {
try {
SecretKey deskey = new SecretKeySpec(build3DesKey(key), Algorithm);
Cipher cipher = Cipher.getInstance(Algorithm);
cipher.init(Cipher.DECRYPT_MODE, deskey);
return cipher.doFinal(src);
}catch (Exception e) {
e.printStackTrace();
return null;
}
}
/ / Generate a 24-bit byte array of keys based on the string
private static byte[] build3DesKey(String keyStr) throws UnsupportedEncodingException {
byte[] key = new byte[24];
byte[] temp = keyStr.getBytes("UTF-8");
if (key.length > temp.length) {
System.arraycopy(temp, 0, key, 0, temp.length);
}else {
System.arraycopy(temp, 0, key, 0, key.length);
}
return key;
}
}
The next section will analyze the security hardening process for the APK installation package.
Here are a few common methods involved in the tool approach. 1. Base64 encryption algorithm The Base64 encryption algorithm is one of the most common encoding methods for transmitting 8-bit byte code ...
reference: http://www.ehcoo.com/cryptology.html Foreword The encryption algorithm is divided into symmetric encryption and asymmetric algorithm. The encryption and decryption keys of the symmetric enc...
Encryption and decryption are often used in development, and it is good to be familiar with it. Article Directory One-way hashing algorithm md5 DigestUtils (spring) implement md5 Symmetric encryption ...
The essence of data encryption is to confuse and conceal the original information content to make it difficult to understand or reverse decryption, or it cannot be decrypted in a short period of time ...
Common encryption algorithms BASE64, MD5, SHA, and HMAC are several encryption algorithms. The BASE64 encoding algorithm is not a real encryption algorithm. MD5, SHA, HMAC these three encryption algor...
Message summary Message Digest is also known as Digital Digest It is a fixed-length value that uniquely corresponds to a message or text, which is generated by a one-way Hash encryption function actin...
Commonly non-reversible juvenile algorithm (is an encryption algorithm, not encrypted rules): Commonly symmetrical encryption (encrypted decryption is the same key): Commonly used asymmetrical encrypt...
Encryption algorithms and protocols Symmetric encryption Introduction: Encryption and decryption use the same key Common algorithms: - DES:Data Encryption Standard; - 3DES:Triple DES; - AES:Advanced E...
Foreword: Many other blog contents are used in the summary of this article. I originally wanted to attach the original link, but I haven't found it for a long time. The originality here comes from the...