1. 程式人生 > >Android 中資料加密 ---- RSA加密

Android 中資料加密 ---- RSA加密

前言:

對於RSA加密,在博文  RSA 加密 已經有了詳細說明,這邊博文將其用Android 實現。

 

更多的加密可以看:

資料加密 ---- 總篇

Android 中資料加密 ---- 異或加密

Android 中資料加密 ---- AES加密

Android 中資料加密 ---- DES加密

Android 中資料加密 ---- 3DES加密

Android 中資料加密 ---- MD5加密

Android 中資料加密 ---- SHA加密

 

例項:

實現的詳細程式碼同 AES 加密的例項

,這裡將抽象的幾個介面實現類RSAEncryption 貼出來:

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,那麼加密後的值是相同的。