Question8:Android下如何使用AES和RSA加密解密文件

Android下使用加解密很大程度上依賴於java。AES和RSA加解密對數據格式有一定的要求,單次加密數據長度有限制。加解密文件在處理數據時,需注意保真的問題。所以對文件加解密前,需要將文件內容進行統一編碼或解碼,避免特殊符號或轉義符號的丟失問題。除此之外,還需對文本內容進行一定格式的填充,以保證每次加密解密的數據長度的一致性和規範性。

SecFile.java: 

<Android>
package android.sec.stream;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import android.sec.Sec;
import android.util.Base64;

import com.cx.mm.web.lokoo.io.FileIO;
import com.cx.mm.web.lokoo.sec.Cypher;

public final class SecFile {

	public static final String SUFFIX_SECURE_FILE = ".sec";
	public static final String SUFFIX_SECURE_FILE_2 = ".secx";

	public static boolean isEncoded(String arg0) {
		if (isEncodedSuffix(arg0)) {
			File tempFile = new File(arg0);
			if (tempFile != null && tempFile.exists() && tempFile.isFile()) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	public static boolean isEncodedSuffix(String arg0) {
		String suffix = FileIO.getFileNameSuffix(arg0);
		if (suffix.endsWith(SecFile.SUFFIX_SECURE_FILE)
				|| suffix.endsWith(SecFile.SUFFIX_SECURE_FILE_2)) {
			return true;
		} else {
			return false;
		}
	}

	public static boolean isMultiEncoded(String arg0) {
		String suffix = FileIO.getFileNameSuffix(arg0);
		if (suffix.endsWith(SecFile.SUFFIX_SECURE_FILE_2)) {
			return true;
		} else {
			return false;
		}
	}

	public static void decode(String tempdir, RSAPrivateKey privateKey)
			throws IOException, InvalidKeyException, NoSuchAlgorithmException,
			NoSuchPaddingException, IllegalBlockSizeException,
			BadPaddingException {
		// TODO Auto-generated method stub
		File secFile = new File(tempdir);
		File tempFile = new File(tempdir.substring(0,
				tempdir.indexOf(SUFFIX_SECURE_FILE_2)));
		FileInputStream raf = new FileInputStream(secFile);
		byte[] buffer = new byte[1024];
		ByteArrayOutputStream sb = new ByteArrayOutputStream();
		FileOutputStream fos = new FileOutputStream(tempFile);
		int readSize = 0;
		while ((readSize = raf.read(buffer)) > 0) {
			sb.write(buffer, 0, readSize);
		}
		sb.flush();
		sb.close();

		// Basic conversion for Image files.
		byte[] a = decodeBase64(Sec.decryptByteStream(privateKey,
				sb.toByteArray()));
		for (int l = 0; l < a.length;) {
			int len = a.length - l;
			if (len > 1024)
				len = 1024;
			fos.write(a, l, len);
			l += len;
		}
		fos.flush();
		fos.close();
		raf.close();
		secFile.delete();
	}

	public static void decode(String tempdir, String key) throws Exception {
		// TODO Auto-generated method stub
		File secFile = new File(tempdir);
		File tempFile = new File(tempdir.substring(0,
				tempdir.indexOf(SUFFIX_SECURE_FILE)));
		FileInputStream raf = new FileInputStream(secFile);
		byte[] buffer = new byte[1024];
		ByteArrayOutputStream sb = new ByteArrayOutputStream();
		FileOutputStream fos = new FileOutputStream(tempFile);
		int readSize = 0;
		while ((readSize = raf.read(buffer)) > 0) {
			sb.write(buffer, 0, readSize);
		}
		sb.flush();
		sb.close();

		byte[] a = Cypher.decrypt(sb.toByteArray(), key);
		for (int l = 0; l < a.length;) {
			int len = a.length - l;
			if (len > 1024)
				len = 1024;
			fos.write(a, l, len);
			l += len;
		}
		fos.flush();
		fos.close();
		raf.close();
		secFile.delete();
	}

	public static void encode(String tempdir, RSAPublicKey publicKey)
			throws IOException, InvalidKeyException, NoSuchAlgorithmException,
			NoSuchPaddingException, IllegalBlockSizeException,
			BadPaddingException {
		// TODO Auto-generated method stub
		File secFile = new File(tempdir + SUFFIX_SECURE_FILE_2);
		File tempFile = new File(tempdir);
		FileInputStream raf = new FileInputStream(tempFile);
		ByteArrayOutputStream sb = new ByteArrayOutputStream();
		FileOutputStream fos = new FileOutputStream(secFile);

		byte[] buffer = new byte[1024];
		int readSize = 0;
		while ((readSize = raf.read(buffer)) > 0) {
			sb.write(buffer, 0, readSize);
		}

		sb.flush();
		sb.close();

		// Basic conversion for Image files.
		byte[] a = Sec.encryptByteStream(publicKey,
				encodeToBase64(sb.toByteArray()));
		for (int l = 0; l < a.length;) {
			int len = a.length - l;
			if (len > 1024)
				len = 1024;
			fos.write(a, l, len);
			l += len;
		}
		fos.flush();
		fos.close();
		raf.close();
		tempFile.delete();
	}

	public static void encode(String tempdir, String key) throws Exception {
		// TODO Auto-generated method stub
		File secFile = new File(tempdir + SUFFIX_SECURE_FILE);
		File tempFile = new File(tempdir);
		FileInputStream raf = new FileInputStream(tempFile);
		byte[] buffer = new byte[1024];
		ByteArrayOutputStream sb = new ByteArrayOutputStream();
		FileOutputStream fos = new FileOutputStream(secFile);
		int readSize = 0;
		while ((readSize = raf.read(buffer)) > 0) {
			sb.write(buffer, 0, readSize);
		}
		sb.flush();
		sb.close();

		byte[] a = Cypher.encrypt(sb.toByteArray(), key);
		for (int l = 0; l < a.length;) {
			int len = a.length - l;
			if (len > 1024)
				len = 1024;
			fos.write(a, l, len);
			l += len;
		}
		fos.flush();
		fos.close();
		raf.close();
		tempFile.delete();
	}

	public static byte[] decodeBase64(byte[] input) throws IOException {
		return Base64.decode(input, Base64.NO_WRAP);
	}

	public static byte[] encodeToBase64(byte[] input) throws IOException {
		return Base64.encodeToString(input, Base64.NO_WRAP).getBytes("UTF-8");
	}
}

</Android>

Sec.java: 

<Android>
package android.sec;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import android.util.Base64;

import com.cx.cm.log.Logs;

public final class Sec {
    // Recommend: 1024 or more in actual cases.
    private static final int KEY_BITS = 1024;
    // Reserve block for encryption key of specified key length(KEY_SIZE);
    private static final int RESERVE_BLOCK_SIZE = 11;
    @SuppressWarnings("unused")
    private static final int ENCRYPT_BLOCK_SIZE = 117;
    @SuppressWarnings("unused")
    private static final int DECRYPT_BLOCK_SIZE = 128;
    private static final String KEY_ALGORITHM = "RSA";
    private static final String CIPHER_ALGORITHM = "RSA";
    public static final int KEY_PUBLIC = 0;
    public static final int KEY_PRIVATE = 1;
    public static final int KEY_PUBLIC_EXP = 2;
    public static final int KEY_PRIVATE_EXP = 3;
    public static final int KEY_SECRET = 4;
    public static final int KEY_PUBLIC_X = 5;
    public static final int KEY_PRIVATE_X = 6;

    public static void init() throws NoSuchAlgorithmException {
        String[] args = initLog();
        Logs.log(0, args[0]);
        Logs.log(1, args[1]);
        Logs.log(2, args[2]);
        Logs.log(3, args[3]);
    }

    public static String[] initLog() throws NoSuchAlgorithmException {
        KeyPair keyPair = Sec.getKeyPair();
        String arg0 = Sec.getPublicModulus(keyPair);
        String arg1 = Sec.getPrivateModulus(keyPair);
        String arg2 = Sec.getPublicExponent(keyPair);
        String arg3 = Sec.getPrivateExponent(keyPair);
        return new String[] { arg0, arg1, arg2, arg3 };
    }

    public static void $init() throws NoSuchAlgorithmException {
        KeyPair keyPair = Sec.getKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Logs.log(KEY_PUBLIC_X, $getPublicKeyBase64(publicKey));
        Logs.log(KEY_PRIVATE_X, $getPrivateKeyBase64(privateKey));
    }

    public static void initSec() throws Exception {
        KeyPair keyPair = Sec.getKeyPair();
        String arg0 = Sec.getPublicModulus(keyPair);
        Logs.log(4, arg0);
    }

    public static RSAPublicKey getPublicKey() throws NoSuchAlgorithmException,
            InvalidKeySpecException {
        return Logs.logValid(KEY_PUBLIC) ? Sec.getPublicKey(
                Logs.getLog(Sec.KEY_PUBLIC), Logs.getLog(Sec.KEY_PUBLIC_EXP))
                : null;
    }

    public static boolean isValidPublicKey() {
        return Logs.getLog(Sec.KEY_PUBLIC).length() <= KEY_BITS
                && Logs.getLog(Sec.KEY_PUBLIC_EXP).length() > 0
                && Logs.getLog(Sec.KEY_PUBLIC_EXP).length() <= KEY_BITS;
    }

    public static RSAPrivateKey getPrivateKey()
            throws NoSuchAlgorithmException, InvalidKeySpecException {
        return Logs.logValid(KEY_PRIVATE) ? Sec.getPrivateKey(
                Logs.getLog(Sec.KEY_PRIVATE), Logs.getLog(Sec.KEY_PRIVATE_EXP))
                : null;
    }

    public static boolean $isValidPublicKey() {
        return Logs.getLog(Sec.KEY_PUBLIC_X).length() > 0;
    }

    public static boolean isValidPrivateKey() {
        return Logs.getLog(Sec.KEY_PRIVATE).length() <= KEY_BITS
                && Logs.getLog(Sec.KEY_PRIVATE_EXP).length() > 0
                && Logs.getLog(Sec.KEY_PRIVATE_EXP).length() <= KEY_BITS;
    }

    public static RSAPrivateKey $getPrivateKey()
            throws NoSuchAlgorithmException, InvalidKeySpecException,
            UnsupportedEncodingException {
        if (Logs.logValid(KEY_PRIVATE_X)) {
            PKCS8EncodedKeySpec keySpec1 = new PKCS8EncodedKeySpec(
                    $getPrivateKeyEncoded());
            KeyFactory keyFactory1 = KeyFactory.getInstance(KEY_ALGORITHM);
            return (RSAPrivateKey) keyFactory1.generatePrivate(keySpec1);
        } else
            return null;
    }

    public static RSAPublicKey $getPublicKey() throws NoSuchAlgorithmException,
            InvalidKeySpecException, UnsupportedEncodingException {
        if (Logs.logValid(KEY_PRIVATE_X)) {
            X509EncodedKeySpec keySpec1 = new X509EncodedKeySpec(
                    $getPublicKeyEncoded());
            KeyFactory keyFactory1 = KeyFactory.getInstance(KEY_ALGORITHM);
            return (RSAPublicKey) keyFactory1.generatePublic(keySpec1);
        } else
            return null;
    }

    public static boolean $isValidPrivateKey() {
        return Logs.getLog(Sec.KEY_PRIVATE_X).length() > 0;
    }

    public static String getSecretKey() {
        return Logs.logValid(KEY_SECRET) ? Logs.getLog(KEY_SECRET) : null;
    }

    public static KeyPair getKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGen = KeyPairGenerator
                .getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(KEY_BITS);
        KeyPair keyPair = (KeyPair) keyPairGen.generateKeyPair();
        return keyPair;
    }

    public static RSAPublicKey $getPublicKey(KeyPair keyPair) {
        return (RSAPublicKey) keyPair.getPublic();
    }

    public static RSAPrivateKey $getPrivateKey(KeyPair keyPair) {
        return (RSAPrivateKey) keyPair.getPrivate();
    }

    public static byte[] $getPublicKeyEncoded()
            throws UnsupportedEncodingException {
        return $getBase64Decoded(Logs.getLog(Sec.KEY_PUBLIC_X));
    }

    public static byte[] $getPrivateKeyEncoded()
            throws UnsupportedEncodingException {
        return $getBase64Decoded(Logs.getLog(Sec.KEY_PRIVATE_X));
    }

    public static String $getPublicKeyBase64(RSAPublicKey publicKey) {
        return Base64.encodeToString(publicKey.getEncoded(), Base64.NO_WRAP);
    }

    public static String $getPrivateKeyBase64(RSAPrivateKey privateKey) {
        return Base64.encodeToString(privateKey.getEncoded(), Base64.NO_WRAP);
    }

    public static byte[] $getBase64Decoded(String arg0)
            throws UnsupportedEncodingException {
        return Base64.decode(arg0.getBytes("UTF-8"), Base64.NO_WRAP);
    }

    public static byte[] $encrypt(RSAPublicKey publicKey, byte[] input)
            throws IllegalBlockSizeException, BadPaddingException,
            InvalidKeyException, NoSuchAlgorithmException,
            NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(input);
    }

    public static byte[] $decrypt(RSAPrivateKey privateKey, byte[] input)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(input);
    }

    public static String getPublicModulus(KeyPair keyPair) {
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        return publicKey.getModulus().toString(16);
    }

    public static String getPublicModulus(RSAPublicKey publicKey) {
        return publicKey.getModulus().toString(16);
    }

    public static String getPrivateModulus(KeyPair keyPair) {
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        return privateKey.getModulus().toString(16);
    }

    public static String getPrivateModulus(RSAPrivateKey privateKey) {
        return privateKey.getModulus().toString(16);
    }

    public static String getPrivateExponent(KeyPair keyPair) {
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        return privateKey.getPrivateExponent().toString(16);
    }

    public static String getPrivateExponent(RSAPrivateKey privateKey) {
        return privateKey.getPrivateExponent().toString(16);
    }

    public static String getPublicExponent(KeyPair keyPair) {
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        return publicKey.getPublicExponent().toString(16);
    }

    public static String getPublicExponent(RSAPublicKey publicKey) {
        return publicKey.getPublicExponent().toString(16);
    }

    public static RSAPublicKey getPublicKey(String modulus,
                                            String publicExponent) throws NoSuchAlgorithmException,
            InvalidKeySpecException {
        BigInteger bigIntModulus = new BigInteger(modulus, 16);
        BigInteger bigIntPrivateExponent = new BigInteger(publicExponent, 16);
        RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,
                bigIntPrivateExponent);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        RSAPublicKey publicKey = (RSAPublicKey) keyFactory
                .generatePublic(keySpec);

        // X509EncodedKeySpec keySpec2 = new X509EncodedKeySpec(
        // publicKey.getEncoded());
        // return (RSAPublicKey) keyFactory.generatePublic(keySpec2);
        return publicKey;
    }

    public static RSAPrivateKey getPrivateKey(String modulus,
                                              String privateExponent) throws NoSuchAlgorithmException,
            InvalidKeySpecException {
        BigInteger bigIntModulus = new BigInteger(modulus, 16);
        BigInteger bigIntPublicExponent = new BigInteger(privateExponent, 16);
        RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,
                bigIntPublicExponent);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        RSAPrivateKey privateKey = (RSAPrivateKey) keyFactory
                .generatePrivate(keySpec);

        return privateKey;
    }

    public static byte[] encrypt(RSAPublicKey key, byte[] input)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(input);
    }

    public static byte[] decrypt(RSAPrivateKey key, byte[] input)
            throws InvalidKeyException, NoSuchAlgorithmException,
            NoSuchPaddingException, IllegalBlockSizeException,
            BadPaddingException {
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(input);
    }

    public static byte[] encryptByteStream(RSAPublicKey key, byte[] arg0)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            IllegalBlockSizeException, BadPaddingException,
            InvalidKeyException, IOException {
        // Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // cipher.init(Cipher.ENCRYPT_MODE, key);
        // byte[] input = arg0;
        // int blocks = input.length / ENCRYPT_BLOCK_SIZE;
        // if (input.length % ENCRYPT_BLOCK_SIZE != 0) {
        // blocks++;
        // }
        // ByteArrayOutputStream outBuffer = new ByteArrayOutputStream(blocks
        // * DECRYPT_BLOCK_SIZE);
        // byte[] encryptedBlock;
        // for (int cursor = 0; cursor < input.length;) {
        // int inputLength = input.length - cursor;
        // if (inputLength > ENCRYPT_BLOCK_SIZE)
        // inputLength = ENCRYPT_BLOCK_SIZE;
        // encryptedBlock = cipher.doFinal(input, cursor, inputLength);
        // outBuffer.write(encryptedBlock, 0, DECRYPT_BLOCK_SIZE);
        // cursor += ENCRYPT_BLOCK_SIZE;
        // }
        // outBuffer.flush();
        // outBuffer.close();
        // return outBuffer.toByteArray();
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        int decryptBlock = KEY_BITS / 8; // 128 bytes
        int encryptBlock = decryptBlock - RESERVE_BLOCK_SIZE; // 117 bytes
        int nBlock = (arg0.length / encryptBlock);
        if ((arg0.length % encryptBlock) != 0) {
            nBlock += 1;
        }
        ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock
                * decryptBlock);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        // cryptedBase64Str =
        // Base64.encodeBase64String(cipher.doFinal(plaintext.getBytes()));
        ByteArrayInputStream bas = new ByteArrayInputStream(arg0);
        for (int offset = 0; offset < arg0.length; offset += encryptBlock) {
            int inputLen = (arg0.length - offset);
            if (inputLen > encryptBlock) {
                inputLen = encryptBlock;
            }
            byte[] buffer = new byte[inputLen];
            bas.read(buffer);
            byte[] encryptedBlock = cipher.doFinal(buffer, 0, inputLen);
            outbuf.write(encryptedBlock);
        }
        return outbuf.toByteArray();
    }

    public static byte[] decryptByteStream(RSAPrivateKey key, byte[] arg0)
            throws NoSuchAlgorithmException, NoSuchPaddingException,
            IllegalBlockSizeException, BadPaddingException,
            InvalidKeyException, IOException {
        // Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // cipher.init(Cipher.DECRYPT_MODE, key);
        // byte[] input = arg0;
        // // if (input.length % DECRYPT_BLOCK_SIZE != 0) {
        // // throw new IllegalBlockSizeException(
        // // "blocks are invalid or damaged.");
        // // }
        // int blocks = (input.length / DECRYPT_BLOCK_SIZE);
        // ByteArrayOutputStream outBuffer = new ByteArrayOutputStream(blocks
        // * ENCRYPT_BLOCK_SIZE);
        // cipher.init(Cipher.DECRYPT_MODE, key);
        // for (int cursor = 0; cursor < input.length;) {
        // int inputLength = (input.length - cursor);
        // if (inputLength > DECRYPT_BLOCK_SIZE) {
        // inputLength = DECRYPT_BLOCK_SIZE;
        // }
        //
        // byte[] decryptedBlock = cipher.doFinal(input, cursor, inputLength);
        // outBuffer.write(decryptedBlock, 0, ENCRYPT_BLOCK_SIZE);
        // cursor += DECRYPT_BLOCK_SIZE;
        // }
        // outBuffer.flush();
        // outBuffer.close();

        // return outBuffer.toByteArray();
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        int decryptBlock = KEY_BITS / 8; // 128 bytes
        int encryptBlock = decryptBlock - RESERVE_BLOCK_SIZE; // 117 bytes
        int nBlock = (arg0.length / decryptBlock);
        ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock
                * encryptBlock);
        cipher.init(Cipher.DECRYPT_MODE, key);
        // plaintext = new
        // String(cipher.doFinal(Base64.decodeBase64(cryptedBase64Str)));
        ByteArrayInputStream bas = new ByteArrayInputStream(arg0);
        for (int offset = 0; offset < arg0.length; offset += decryptBlock) {
            int inputLen = (arg0.length - offset);
            if (inputLen > decryptBlock) {
                inputLen = decryptBlock;
            }

            byte[] buffer = new byte[inputLen];
            bas.read(buffer);
            byte[] decryptedBlock = cipher.doFinal(buffer, 0, inputLen);
            outbuf.write(decryptedBlock);
        }
        outbuf.flush();
        outbuf.close();
        return outbuf.toByteArray();

    }

}
</Android>

Cipher.java:

<Android>
package com.cx.mm.web.lokoo.sec;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import android.util.Base64;
import android.util.Log;

import com.cx.cm.log.Logs;

public class Cypher {

	private static final String TAG = "Cypher";
	private Cipher mCipher;
	private SecretKeySpec mSecretKey;
	public static final String SHA256 = "SHA256";
	public static final String SHA512 = "SHA512";
	public static final String SHA1024 = "SHA1024";
	public static final int SHA_256 = 0;
	public static final int SHA_512 = 1;
	public static final int SHA_1024 = 2;
	public static final int SECURITY_LOW = -10000;
	public static final int SECURITY_NORMAL = -10001;
	public static final int SECURITY_HIGH = -10002;

	public Cypher(String param) {
		this.mSecretKey = new SecretKeySpec(generateKey(param), "AES");
		instantiate(this.mSecretKey, 1);
	}

	public static String md5(String message) {
		try {
			MessageDigest a = MessageDigest.getInstance("MD5");
			a.update(message.getBytes());
			return getString(a);
		} catch (NoSuchAlgorithmException e) {
			Log.e(TAG, e.getMessage());
		}
		return null;
	}

	private static String getString(MessageDigest a) {
		try {
			String s;
			for (Object n = new BigInteger(1, a.digest()).toString(16);; n = s) {
				if (((String) n).length() >= 32)
					return (String) n;
				s = "0" + (String) n;
			}
		} catch (Exception unknown) {
			Log.e(TAG, unknown.getMessage());
		}
		return (String) "";
	}

	public static byte[] generateKey(String param) {
		try {
			return MessageDigest.getInstance("SHA256").digest(
					param.getBytes("UTF-8"));
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		return null;
	}

	public static byte[] generateKey(String param, int security) {
		try {
			switch (security) {
			case SHA_256:
			case SECURITY_LOW:
				return MessageDigest.getInstance(SHA256).digest(
						param.getBytes("UTF-8"));
			case SHA_512:
			case SECURITY_NORMAL:
			case SECURITY_HIGH:
				return MessageDigest.getInstance(SHA512).digest(
						param.getBytes("UTF-8"));
			case SHA_1024:
				return MessageDigest.getInstance(SHA1024).digest(
						param.getBytes("UTF-8"));
			default:
				return MessageDigest.getInstance("SHA256").digest(
						param.getBytes("UTF-8"));
			}
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		return null;
	}

	public void instantiate(SecretKey key, int mode) {
		byte[] params = new byte[16];
		params[1] = 1;
		params[2] = 2;
		params[3] = 3;
		params[4] = 4;
		params[5] = 5;
		params[6] = 6;
		params[7] = 7;
		params[8] = 8;
		params[9] = 9;
		params[10] = 10;
		params[11] = 11;
		params[12] = 12;
		params[13] = 13;
		params[14] = 14;
		params[15] = 15;
		IvParameterSpec ivParameterSpec = new IvParameterSpec(params);
		try {
			this.mCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			this.mCipher.init(mode, key, ivParameterSpec);
			return;
		} catch (Exception e) {
			this.mCipher = null;
			Log.e(TAG, e.getMessage());
		}
	}

	public static Cipher instantiate(SecretKey key, int mode, int arg0) {
		byte[] params = new byte[16];
		params[1] = 1;
		params[2] = 2;
		params[3] = 3;
		params[4] = 4;
		params[5] = 5;
		params[6] = 6;
		params[7] = 7;
		params[8] = 8;
		params[9] = 9;
		params[10] = 10;
		params[11] = 11;
		params[12] = 12;
		params[13] = 13;
		params[14] = 14;
		params[15] = 15;
		IvParameterSpec ivParameterSpec = new IvParameterSpec(params);
		try {
			Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
			cipher.init(mode, key, ivParameterSpec);
			return cipher;
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
			return null;
		}
	}

	public String encrypt(String msg) {
		if (null == this.mCipher)
			return "";
		try {
			String str = Base64.encodeToString(
					this.mCipher.doFinal(msg.getBytes()), Base64.NO_WRAP);
			return str;
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		return "";
	}

	public static byte[] encrypt(byte[] msg, String param)
			throws UnsupportedEncodingException, IllegalBlockSizeException,
			BadPaddingException {
		return encrypt(msg, param, SECURITY_LOW);
	}

	public static byte[] encrypt(byte[] msg, String param, int security)
			throws UnsupportedEncodingException, IllegalBlockSizeException,
			BadPaddingException {
		SecretKeySpec key = new SecretKeySpec(generateKey(param, security),
				"AES");
		Cipher cipher = instantiate(key, Cipher.ENCRYPT_MODE, -1);
		if (null == cipher)
			return null;

		return Base64.encodeToString(cipher.doFinal(msg), Base64.NO_WRAP)
				.getBytes("UTF-8");
	}

	public String decrypt(String e) {
		instantiate(this.mSecretKey, 2);
		if (null == this.mCipher)
			return "";
		try {
			String str = new String(this.mCipher.doFinal(Base64.decode(e,
					Base64.NO_WRAP)));
			return str;
		} catch (Exception e1) {
			Logs.ef(TAG, e1);
		}
		return "";
	}

	public static byte[] decrypt(byte[] e, String param)
			throws UnsupportedEncodingException, IllegalBlockSizeException,
			BadPaddingException {
		return decrypt(e, param, SECURITY_LOW);
	}

	public static byte[] decrypt(byte[] e, String param, int security)
			throws UnsupportedEncodingException, IllegalBlockSizeException,
			BadPaddingException {
		SecretKeySpec key = new SecretKeySpec(generateKey(param, security),
				"AES");
		Cipher cipher = instantiate(key, Cipher.DECRYPT_MODE, -1);
		if (null == cipher)
			return null;
		return cipher.doFinal(Base64.decode(e, Base64.NO_WRAP));
	}
}
</Android>

 不論是在Android還是純Java、PHP或Python等其他編程語言環境下,其原理走的是幾乎一致的路線:數據的編碼和填充。編碼是爲了是數據的加密和解密能避免因平臺的差異而導致數據失真,填充是爲了保證加解密的數據一致性。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章