Android传递IV参数加密/解密文本
Android Passing IV parameters Encryption /Decryption text
我希望你能帮助我关联我的代码。
我正在尝试将参数 IV 传递给加密/解密
加密函数:
我尝试连接文本;四
encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT) + ";" + (Base64.encodeToString(encryptionIv, Base64.DEFAULT)));
我认为效果很好,如图所示。
public void encryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] src= initialText.getBytes("UTF-8");
byte[] iv = inCipher.getIV();
assert iv.length == 12;
byte[] cipherText = inCipher.doFinal(src);
assert cipherText.length == src.length + 16;
byte[] message = new byte[12 + src.length + 16];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(src);
cipherOutputStream.close();
byte [] vals = outputStream.toByteArray();
encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
[![在此处输入图片描述][1]][1]
你能帮我举个例子让解密工作正常吗?
感谢您的帮助
更新:您好,我正在尝试通过 IV 作为示例:
我的代码在这里:
public void encryptString(String alias) {
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text' widget", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(initialText.getBytes("UTF-8"));
cipherOutputStream.close();
byte [] vals = outputStream.toByteArray();
encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
[![在此处输入图片描述][2]][2]
NEW 更新:
加密密码
public void encryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] src= initialText.getBytes("UTF-8");
byte[] iv = inCipher.getIV();
assert iv.length == 12;
byte[] cipherText = inCipher.doFinal(src);
assert cipherText.length == src.length + 16;
byte[] message = new byte[12 + src.length + 16];
System.arraycopy(iv, 0, message, 0, 12);
System.arraycopy(cipherText, 0, message, 12, cipherText.length);
//ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//CipherOutputStream cipherOutputStream = new CipherOutputStream(
// outputStream, inCipher);
//cipherOutputStream.write(message);
//cipherOutputStream.close();
//byte [] vals = outputStream.toByteArray();
encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
解密代码:(无效)
public void decryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String cipherText = encryptedText.getText().toString();
byte[] src = cipherText.getBytes();
byte[] message = new byte[12 + src.length + 16];
Cipher output = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
output.init(Cipher.DECRYPT_MODE, secretKey, params);
// output.doFinal(message, 12, message.length - 12);
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
decryptedText.setText(finalText);
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
你能帮我解决图片中显示的错误吗?
[![在此处输入图片描述][3]][3]
<<---更新的解决方案-->
加密函数:
public void encryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] src= initialText.getBytes("UTF-8");
byte[] iv = inCipher.getIV();
assert iv.length == 12;
byte[] cipherText = inCipher.doFinal(src);
assert cipherText.length == src.length + 16;
byte[] message = new byte[12 + src.length + 16];
System.arraycopy(iv, 0, message, 0, 12);
System.arraycopy(cipherText, 0, message, 12, cipherText.length);
encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
解密函数:
public void decryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String cipherText = encryptedText.getText().toString();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] nonceCiphertextTag = Base64.decode(cipherText, Base64.DEFAULT);
GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
String finalText = new String(decrypted, 0, decrypted.length, "UTF-8");
decryptedText.setText(finalText);
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
非常感谢@Topaco 的帮助
最新发布的加密代码中,将nonce、密文和tag拼接并进行Base64编码,以下称为nonceCiphertextTagB64
.
解密时
nonceCiphertextTagB64
必须先Base64解码为nonceCiphertextTag
,
- 随机数必须封装在
GCMParameterSpec
实例中;随机数是 nonceCiphertextTag
、 的前 12 个字节
- 必须创建
AES/GCM/NoPadding
的密码实例,使用密钥和处于解密模式的 GCMParameterSpec
实例进行初始化,
- 密文与标签的拼接被解密;密文和tag的拼接就是nonce之后的数据
在以下示例实现中,对于重现,使用了 32 字节的密钥 01234567890123456789012345678901
(而不是来自密钥库的密钥)。密文是使用相同的密钥和明文使用发布的加密代码创建的 The quick brown fox jumps over the lazy dog:
...
String nonceCiphertextTagB64 =
"UpyxMnzPrw+zJGANL4wBbaC+UX5KnMKYwhR0u2iF/GDCcU38YKWlvJp1zJ+mrN0POP7lz9y+eweH\n" +
"vIxAH4R4U3At8T0fVe0=";
SecretKeySpec secretKey = new SecretKeySpec("01234567890123456789012345678901".getBytes(StandardCharsets.UTF_8),"AES");
byte[] nonceCiphertextTag = Base64.decode(nonceCiphertextTagB64, Base64.DEFAULT);
GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
System.out.println(new String(decrypted, StandardCharsets.UTF_8)); // The quick brown fox jumps over the lazy dog
...
输出为:
The quick brown fox jumps over the lazy dog
我希望你能帮助我关联我的代码。
我正在尝试将参数 IV 传递给加密/解密
加密函数:
我尝试连接文本;四
encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT) + ";" + (Base64.encodeToString(encryptionIv, Base64.DEFAULT)));
我认为效果很好,如图所示。
public void encryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] src= initialText.getBytes("UTF-8");
byte[] iv = inCipher.getIV();
assert iv.length == 12;
byte[] cipherText = inCipher.doFinal(src);
assert cipherText.length == src.length + 16;
byte[] message = new byte[12 + src.length + 16];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(src);
cipherOutputStream.close();
byte [] vals = outputStream.toByteArray();
encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
[![在此处输入图片描述][1]][1] 你能帮我举个例子让解密工作正常吗?
感谢您的帮助
更新:您好,我正在尝试通过 IV 作为示例:
我的代码在这里:
public void encryptString(String alias) {
try {
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text' widget", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
inCipher.init(Cipher.ENCRYPT_MODE, publicKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, inCipher);
cipherOutputStream.write(initialText.getBytes("UTF-8"));
cipherOutputStream.close();
byte [] vals = outputStream.toByteArray();
encryptedText.setText(Base64.encodeToString(vals, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
[![在此处输入图片描述][2]][2]
NEW 更新:
加密密码
public void encryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] src= initialText.getBytes("UTF-8");
byte[] iv = inCipher.getIV();
assert iv.length == 12;
byte[] cipherText = inCipher.doFinal(src);
assert cipherText.length == src.length + 16;
byte[] message = new byte[12 + src.length + 16];
System.arraycopy(iv, 0, message, 0, 12);
System.arraycopy(cipherText, 0, message, 12, cipherText.length);
//ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//CipherOutputStream cipherOutputStream = new CipherOutputStream(
// outputStream, inCipher);
//cipherOutputStream.write(message);
//cipherOutputStream.close();
//byte [] vals = outputStream.toByteArray();
encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
解密代码:(无效)
public void decryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String cipherText = encryptedText.getText().toString();
byte[] src = cipherText.getBytes();
byte[] message = new byte[12 + src.length + 16];
Cipher output = Cipher.getInstance("AES/GCM/NoPadding");
GCMParameterSpec params = new GCMParameterSpec(128, message, 0, 12);
output.init(Cipher.DECRYPT_MODE, secretKey, params);
// output.doFinal(message, 12, message.length - 12);
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipherText, Base64.DEFAULT)), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
String finalText = new String(bytes, 0, bytes.length, "UTF-8");
decryptedText.setText(finalText);
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
你能帮我解决图片中显示的错误吗?
[![在此处输入图片描述][3]][3]
<<---更新的解决方案-->
加密函数:
public void encryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String initialText = startText.getText().toString();
if(initialText.isEmpty()) {
Toast.makeText(this, "Enter text in the 'Initial Text'", Toast.LENGTH_LONG).show();
return;
}
Cipher inCipher = Cipher.getInstance("AES/GCM/NoPadding");
inCipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] src= initialText.getBytes("UTF-8");
byte[] iv = inCipher.getIV();
assert iv.length == 12;
byte[] cipherText = inCipher.doFinal(src);
assert cipherText.length == src.length + 16;
byte[] message = new byte[12 + src.length + 16];
System.arraycopy(iv, 0, message, 0, 12);
System.arraycopy(cipherText, 0, message, 12, cipherText.length);
encryptedText.setText(Base64.encodeToString(message, Base64.DEFAULT));
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
解密函数:
public void decryptString(String alias) {
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
SecretKey secretKey = (SecretKey) keyStore.getKey(alias, null);
String cipherText = encryptedText.getText().toString();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
byte[] nonceCiphertextTag = Base64.decode(cipherText, Base64.DEFAULT);
GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
String finalText = new String(decrypted, 0, decrypted.length, "UTF-8");
decryptedText.setText(finalText);
} catch (Exception e) {
Toast.makeText(this, "Exception " + e.getMessage() + " occurred", Toast.LENGTH_LONG).show();
Log.e(TAG, Log.getStackTraceString(e));
}
}
非常感谢@Topaco 的帮助
最新发布的加密代码中,将nonce、密文和tag拼接并进行Base64编码,以下称为nonceCiphertextTagB64
.
解密时
nonceCiphertextTagB64
必须先Base64解码为nonceCiphertextTag
,- 随机数必须封装在
GCMParameterSpec
实例中;随机数是nonceCiphertextTag
、 的前 12 个字节
- 必须创建
AES/GCM/NoPadding
的密码实例,使用密钥和处于解密模式的GCMParameterSpec
实例进行初始化, - 密文与标签的拼接被解密;密文和tag的拼接就是nonce之后的数据
在以下示例实现中,对于重现,使用了 32 字节的密钥 01234567890123456789012345678901
(而不是来自密钥库的密钥)。密文是使用相同的密钥和明文使用发布的加密代码创建的 The quick brown fox jumps over the lazy dog:
...
String nonceCiphertextTagB64 =
"UpyxMnzPrw+zJGANL4wBbaC+UX5KnMKYwhR0u2iF/GDCcU38YKWlvJp1zJ+mrN0POP7lz9y+eweH\n" +
"vIxAH4R4U3At8T0fVe0=";
SecretKeySpec secretKey = new SecretKeySpec("01234567890123456789012345678901".getBytes(StandardCharsets.UTF_8),"AES");
byte[] nonceCiphertextTag = Base64.decode(nonceCiphertextTagB64, Base64.DEFAULT);
GCMParameterSpec params = new GCMParameterSpec(128, nonceCiphertextTag, 0, 12);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
byte[] decrypted = cipher.doFinal(nonceCiphertextTag, 12, nonceCiphertextTag.length - 12);
System.out.println(new String(decrypted, StandardCharsets.UTF_8)); // The quick brown fox jumps over the lazy dog
...
输出为:
The quick brown fox jumps over the lazy dog