【发布时间】:2014-08-12 12:49:48
【问题描述】:
我正在尝试使用带有公钥的 RSA 算法加密文件(我使用给定的模数和指数构建)。
我的代码在 Android 4.3 上运行良好,我得到了我需要的一切。但我试图让它适用于其他 Android 版本,如(2.3.3),但没有办法。它抱怨“对于 RSA 密码而言输入太大”。 如果我已经很好地理解了这个理论,那么分组密码的大小是相对于 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;
}
}
任何建议或建议都将受到欢迎。 非常感谢。
【问题讨论】:
-
不是直接在主题上,但我建议发布您认为可能会发出错误的一小部分代码
-
好吧,在 Android 2.3.3 中,它第一次抱怨尝试执行 cipher.doFinal(buffer),因为“显然”缓冲区对于该密码来说太大了(输入数据也是对于 RSA 密码来说很大)。但这对我来说毫无意义,因为在 Android 4.3 中它可以完美运行。我想知道是否还有其他东西。
-
他们是否可能使用不同版本的安全提供程序 BC?
-
我建议您阅读developer.com/ws/android/… 并尝试那里的实现,这对于所有 API 级别都应该是正确的。
-
@IVlad 那个写了应该被枪杀和龙骨牵引的白痴,然后再次射击以确保。
标签: java android algorithm encryption rsa