Android 中資料加密 ---- RSA加密
阿新 • • 發佈:2018-11-24
前言:
對於RSA加密,在博文 RSA 加密 已經有了詳細說明,這邊博文將其用Android 實現。
更多的加密可以看:
例項:
實現的詳細程式碼同 AES 加密的例項
public class RSAEncryption extends BlockEncryption { private static final String ALGORITHM = "RSA"; private static final String PADDING = "/ECB/PKCS1Padding"; private static final int DEFAULT_KEY_SIZE = 1024; private static final int RSA_BLOCK_SIZE = 11; public static final int TYPE_ENCRYPTION_WITH_PUBLIC = 0; public static final int TYPE_ENCRYPTION_WITH_PRIVATE = 1; private int mEncryptionType = TYPE_ENCRYPTION_WITH_PUBLIC; private int mKeyLength = DEFAULT_KEY_SIZE; private PublicKey mPublicKey; private PrivateKey mPrivateKey; public RSAEncryption() { } public void setEncryptionType(int type) { mEncryptionType = type; } public void setKeyLength(int keyLength) { mKeyLength = keyLength; } private KeyPair generateRSAKeyPair(int keyLength) { try { KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM); kpg.initialize(keyLength); return kpg.genKeyPair(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public void generateKeys() { KeyPair keyPair = generateRSAKeyPair(mKeyLength); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); try { // get public key X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey.getEncoded()); KeyFactory kf = KeyFactory.getInstance(ALGORITHM); mPublicKey = kf.generatePublic(keySpec); // get private key PKCS8EncodedKeySpec keySpec1 = new PKCS8EncodedKeySpec(privateKey.getEncoded()); mPrivateKey = kf.generatePrivate(keySpec1); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidKeySpecException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private Key getKey(int mode) { if (mEncryptionType == TYPE_ENCRYPTION_WITH_PRIVATE) { return mode == Cipher.ENCRYPT_MODE ? mPrivateKey : mPublicKey; } return mode == Cipher.ENCRYPT_MODE ? mPublicKey : mPrivateKey; } @Override public Cipher getCipher(int mode) { if (mode != Cipher.ENCRYPT_MODE && mode != Cipher.DECRYPT_MODE) return null; try { Cipher cipher = Cipher.getInstance(ALGORITHM + PADDING); cipher.init(mode, getKey(mode)); return cipher; } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvalidKeyException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } @Override public String getAlgorithm() { return ALGORITHM; } @Override protected int getBlockSize() { return RSA_BLOCK_SIZE; } @Override protected int getBufferSize() { return (mKeyLength / 8) - RSA_BLOCK_SIZE; } }
需要注意的是,這裡的buffer size 為key length/8,block size 是11。
另外,因為RSA 需要public key 和private key,所以gitCipher() 不再使用BlockEncryptionHelper 中的方法。
Activity 中設定button 進行點選:
private void testEncryptionRSA() { Button ersa = (Button) findViewById(R.id.encrypt_rsa); ersa.setOnClickListener(this); Button drsa = (Button) findViewById(R.id.decrypt_rsa); drsa.setOnClickListener(this); } private void rsaEncryption() { { mOperationTitle.setText(getString(R.string.encrypt_rsa)); String strSource = "hliuhiufhliuhsd;jfijso;goshgosjogijsgo;j"; mBeforeOperation.setText(getString(R.string.before_operation, strSource)); if (mRSAEncryption == null) { mRSAEncryption = new RSAEncryption(); mRSAEncryption.generateKeys(); } mStrEncrypted = mRSAEncryption.strEncryption(strSource); Log.d(TAG, "==== mStrEncrypted = " + mStrEncrypted); mAfterOperation.setText(getString(R.string.after_operation, mStrEncrypted)); } // if (mFileEncryption != null) { // Log.d(TAG, "==== test file, encryption with rsa ..."); // String filePath = "/storage/emulated/0/hehe.png"; // String destPath = "/storage/emulated/0/2.png"; // mFileEncryption.setAlgorithm(FileEncryption.ALG_MODE_RSA); // mFileEncryption.start(FileEncryption.MODE_ENCRYPT, filePath, destPath); // Log.d(TAG, "==== test file, encryption end"); // } } private void rsaDecryption() { { mOperationTitle.setText(getString(R.string.decrypt_rsa)); mBeforeOperation.setText(getString(R.string.before_operation, mStrEncrypted)); if (mRSAEncryption == null) { mRSAEncryption = new RSAEncryption(); mRSAEncryption.generateKeys(); } String strDecrypted = mRSAEncryption.strDecryption(mStrEncrypted); Log.d(TAG, "==== strDecrypted = " + strDecrypted); mAfterOperation.setText(getString(R.string.after_operation, strDecrypted)); } // if (mFileEncryption != null) { // Log.d(TAG, "==== test file, decryption with rsa ..."); // String filePath = "/storage/emulated/0/hehe.png"; // String destPath = "/storage/emulated/0/2.png"; // mFileEncryption.setAlgorithm(FileEncryption.ALG_MODE_RSA); // mFileEncryption.start(FileEncryption.MODE_DECRYPT, destPath, filePath); // Log.d(TAG, "==== test file, decryption end"); // } }
註釋掉的是對於檔案的加密、解密,同樣是實用的。
結果:
12-19 05:04:19.186 1958 1958 D TestEncryptionActivity: ==== mStrEncrypted = kPSmTWshnnFvHxOgxgp/qL7cJ2jHwx7sz+DE4cjrmskgeHOc1BKdBJGmKPTMN2JvY5NwI7Od5s/1
12-19 05:04:19.186 1958 1958 D TestEncryptionActivity: gNJX4Bzad/gvUgskpWklFOTHtfQL9hS1aG67fPhG8YXrbyOiHDYFSRxNdEFxRla4CkNRx+DDUWq7
12-19 05:04:19.186 1958 1958 D TestEncryptionActivity: /zDqAkA92myhgMUCLKk=
12-19 05:04:24.587 1958 1958 D TestEncryptionActivity: ==== strDecrypted = hliuhiufhliuhsd;jfijso;goshgosjogijsgo;j
12-19 05:04:32.139 1958 1958 D TestEncryptionActivity: ==== mStrEncrypted = PgZyrAPsJNIwa1sXSpeRFe5z8XsNHMJ0sPsNmLycdHKO4kZhiOWAvfXjMgaN2r6exhWLMbkzY+Kw
12-19 05:04:32.139 1958 1958 D TestEncryptionActivity: dGV8KHdVYWdy6GVUXGa85lPYkuEtGKyDXdAX8erXYhKdwGGKPcZtqFK074K0R7p1inFy2g24LEkl
12-19 05:04:32.139 1958 1958 D TestEncryptionActivity: RyMAZwuRCjgPiDJTqw4=
12-19 05:04:34.194 1958 1958 D TestEncryptionActivity: ==== strDecrypted = hliuhiufhliuhsd;jfijso;goshgosjogijsgo;j
12-19 05:04:35.797 1958 1958 D TestEncryptionActivity: ==== mStrEncrypted = EaFez+qztG8VP1WmgUaAdeQp7ZbuC0p+JwKiHYpo3VymgZ6fV4Yc4+Wfm64D4AQKPONzSVm7q8fc
12-19 05:04:35.797 1958 1958 D TestEncryptionActivity: fd4nnAfk+wqDYYyStvg+4D4LGvEXe6UZaKXw9leqfR9bLiSazbUgVzD60TwDE8Sgbx/igeoSX40G
12-19 05:04:35.797 1958 1958 D TestEncryptionActivity: 30MbOgVbjfQN3gRR86Q=
12-19 05:04:37.150 1958 1958 D TestEncryptionActivity: ==== strDecrypted = hliuhiufhliuhsd;jfijso;goshgosjogijsgo;j
每一次加密的結果都不一樣,這個是因為加密的key 是public key,所以填充都會隨機變化,導致了最後結果的不同。
如果加密的時候為private key,那麼加密後的值是相同的。