我正在尝试使用带有公钥的RSA算法加密文件(我使用给定的模数和指数构建)。
我的代码适用于Android 4.3,我得到了我所需要的一切。但我试图让它适用于其他Android版本(2.3.3)并且没有办法。它抱怨输入对于RSA密码而言太大了#34; 如果我已经很好地理解了这个理论,那么分组密码大小是相对于publicKey.size()的,所以如果这个从一个版本的Android改为另一个版本,我应该得到相同的结果,不应该这样吗? ?
这是我的代码: 包com.example.rsa_ex;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.RSAPublicKeySpec;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
public class MainActivity extends Activity
{
private byte[] mKeyModulus = {...};
private byte[] mKeyExponent = {...};
private String tag = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String token = "";
try
{
token = readTokenFromFile("token.base64");
}
catch (IOException e)
{
Log.d(tag, "Failed to open property file");
}
byte[] encodedBytes = Base64.encode(token.getBytes(), 0);
Log.d(tag, "Encrypt Token"+ onEncrypt(encodedBytes));
}
public String readTokenFromFile(String fileName) throws IOException
{
String token = "empty";
try
{
AssetManager assetManager = getAssets();
InputStream iS = assetManager.open(fileName);
byte[] buffer = new byte[iS.available()];
iS.read(buffer);
ByteArrayOutputStream oS = new ByteArrayOutputStream();
oS.write(buffer);
token = oS.toString();
oS.close();
iS.close();
Log.d(tag, "token ==> "+token);
}
catch (IOException e)
{
Log.d(tag, "Failed to open property file");
}
return token;
} // readTokenFromFile end
public String onEncrypt(byte[] token)
{
Log.d(tag,"onEncrypt entry");
String encryptedTranspherable = "";//null;
// get the publicKey
try
{
BigInteger m = new BigInteger(mKeyModulus);
BigInteger e = new BigInteger(mKeyExponent);
KeyFactory fact = KeyFactory.getInstance("RSA");
Key pubKey = fact.generatePublic(new RSAPublicKeySpec(m, e));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] encrypted = blockCipher(token,cipher);
encryptedTranspherable = Base64.encodeToString(encrypted, Base64.DEFAULT);
}
catch (Exception e)
{
throw new RuntimeException("serialisation error got issue here !! ==>"+ e.getMessage(), e);
}
return encryptedTranspherable;
}// onEncrypt end
private byte[] blockCipher(byte[] bytes,Cipher cipher) throws IllegalBlockSizeException, BadPaddingException
{
Log.d(tag,"ISecurityProvider blockCipher entry");
Log.d(tag,"ISecurityProvider byteArray =>"+ Arrays.toString(bytes));
byte[] scrambled = new byte[0];
// toReturn will hold the total result
byte[] toReturn = new byte[0];
int length = 256;
// another buffer. this one will hold the bytes that have to be modified in this step
byte[] buffer = new byte[Math.min(bytes.length, length)];//(bytes.length > length ? length : bytes.length)];
for (int i=0; i< bytes.length; i++)
{
// if we filled our buffer array we have our block ready for de- or encryption
if ((i > 0) && (i % length == 0))
{
Log.d(tag,"ISecurityProvider blockCipher processing block i ="+i);
scrambled = cipher.doFinal(buffer);
toReturn = append(toReturn,scrambled);
// here we calculate the length of the next buffer required
int newlength = length;
// if newlength would be longer than remaining bytes in the bytes array we shorten it.
if (i + length > bytes.length)
{
newlength = bytes.length - i;
}
// clean the buffer array
buffer = new byte[newlength];
}
// copy byte into our buffer.
buffer[i%length] = bytes[i];
}
// this step is needed if we had a trailing buffer. should only happen when encrypting.
// example: we encrypt 110 bytes. 100 bytes per run means we "forgot" the last 10 bytes. they are in the buffer array
scrambled = cipher.doFinal(buffer);
// final step before we can return the modified data.
toReturn = append(toReturn,scrambled);
return toReturn;
}
private byte[] append(byte[] prefix, byte[] suffix)
{
byte[] toReturn = new byte[prefix.length + suffix.length];
int prefixSize = prefix.length;
int suffixSize = suffix.length;
for (int i=0; i< prefixSize; i++)
{
toReturn[i] = prefix[i];
}
for (int i=0; i< suffixSize; i++)
{
toReturn[i+prefixSize] = suffix[i];
}
return toReturn;
}
}
任何建议或建议都非常欢迎。 非常感谢。
答案 0 :(得分:3)
从Android 4.2增强功能:
Cryptography - 修改SecureRandom和Cipher.RSA的默认实现以使用OpenSSL。使用OpenSSL 1.0.1为TLSv1.1和TLSv1.2添加了SSL套接字支持
这意味着他们正在使用其他提供程序,可能还有另一个默认 RSA填充机制。您应始终提供完整的算法字符串,而不是依赖提供程序默认值,例如尝试"RSA/ECB/OAEPWithSHA1AndMGF1Padding"
申请新申请,"RSA/ECB/PKCS1Padding"
申请与旧图书馆兼容。
请注意,您通常不使用RSA直接加密文件。通常使用随机数据密钥使用例如加密文件。 AES,一种对称密码。然后使用RSA公钥加密该AES密钥,并使用密文发送结果。这样,您可以加密(几乎)任意数量的字节。这称为hybrid cryptography。