前言:
对于RSA加密,在博文 RSA 加密 已经有了详细说明,这边博文将其用Android 实现。
更多的加密可以看:
实例:
实现的详细代码同 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,那么加密后的值是相同的。