Android中RSA加密

上次我们说了一个MD5加密,我们来复习一下。这是一种单向加密方式。我们只能让拦截我们数据的人不知道我们真实的内容是什么,但是我们不能反向解密。一般用于信息验证的场合。今天说的就是一个可以加密也可以解密的东东,那就是RSA加密。

RSA加密后的内容是一个byte数组,解密需要的内容也是byte数组。但加密后的byte数组如果你尝试转为字符串你会发现是乱码。所以我们传输或者保存的时候需要直接对byte数组进行传输处理,不要尝试转为字符串,否则会有意想不到的错误。

代码如下,大家参考。依赖包我已经上传到资源了。

加密工具类RSAUtil.java

public class RSAUtil {
    private static final String TAG = "RSAUtil";
    private static final String Algorithm = "RSA";

    public static KeyPair generateKeyPair() throws Exception {
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(Algorithm,
                    new org.bouncycastle.jce.provider.BouncyCastleProvider());
            // 这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会降低
            final int KEY_SIZE = 1024;
            keyPairGen.initialize(KEY_SIZE, new SecureRandom());
            KeyPair keyPair = keyPairGen.generateKeyPair();
            return keyPair;
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }

    //加密
    public 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());
        }
    }

    //解密
    public 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());
        }
    }
}

布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">
    <EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入文字"/>
    <Button
        android:id="@+id/bt_jiam"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="加密"/>
    <Button
        android:id="@+id/bt_jiem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="解密"/>

    <Button
        android:id="@+id/bt_scmyd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="生成密钥对"/>
</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private EditText et;
    private Button bt_jiam;
    private Button bt_jiem;
    private Button bt_scmyd;

    private KeyPair keyPair;//公钥私钥对
    private byte[] bytes;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et = findViewById(R.id.et);
        bt_jiam = findViewById(R.id.bt_jiam);
        bt_jiem = findViewById(R.id.bt_jiem);
        bt_scmyd = findViewById(R.id.bt_scmyd);
        bt_jiam.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String content = et.getText().toString();
                try {
                    bytes =  RSAUtil.encrypt(keyPair.getPublic(),content.getBytes());
                    et.setText("");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        bt_jiem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    bytes =  RSAUtil.decrypt(keyPair.getPrivate(),bytes);
                    et.setText(new String(bytes));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        bt_scmyd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    keyPair = RSAUtil.generateKeyPair();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

操作的时候我们要首先生成密钥对。接着就可以进行加解密操作。生成密钥对的操作可以放在服务端进行。然后将序列化的内容打包到我们本地端,并序列化成文件打包到apk中。

猜你喜欢

转载自blog.csdn.net/weixin_38322371/article/details/115063315