- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在用 Java 实现与第三方应用程序的通信。作为登录过程的一部分,第三方应用程序正在发送一个加密字符串,我必须对其进行解码并发回。我花了将近 2 天的时间在谷歌搜索和阅读帖子,但我找不到正确的方法来实现这一点。
我有一个测试用例,其中加密字符串为“c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY=”,使用密码“GAT”解密必须返回“101714994”。
我的文档说明了这一点:授权字符串使用以下设置加密:
这是如何解密授权字符串的 C# 示例:
/// <summary>
/// Decrypts a string.
/// </summary>
/// <param name="content">The string to decrypt.</param>
/// <param name="password">The password to use.</param>
/// <returns>The decrypted string.</returns>
private static string DecryptString(string content, string password) {
Rijndael aes;
byte[] retVal = null;
byte[] contentBytes;
byte[] passwordBytes;
byte[] ivBytes;
try {
//Get the content as byte[]
contentBytes = Convert.FromBase64String(content);
//Create the password and initial vector bytes
passwordBytes = new byte[32];
ivBytes = new byte[16];
Array.Copy(Encoding.Unicode.GetBytes(password), passwordBytes, Encoding.Unicode.GetBytes(password).Length);
Array.Copy(passwordBytes, ivBytes, 16);
//Create the cryptograpy
object aes = Rijndael.Create();
aes.Key = passwordBytes;
aes.IV = ivBytes;
aes.Padding = PaddingMode.PKCS7;
//Decrypt
retVal = aes.CreateDecryptor().TransformFinalBlock(contentBytes, 0, contentBytes.Length);
}
catch {
}
aes = null;
contentBytes = null;
passwordBytes = null;
ivBytes = null;
return Encoding.Unicode.GetString(retVal)
}
这是我解密字符串的 Java 程序:
private String decryptAuthorizationString(String authString, String password) {
try {
//Force the test string
authString = "c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY=";
//Force the test password
password = "GAT";
//Create the password and initial vector bytes
byte[] passwordBytes= new byte[32];
byte[] b= password.getBytes("UTF-8");
int len= b.length;
if (len > passwordBytes.length) len = passwordBytes.length;
System.arraycopy(b, 0, passwordBytes, 0, len);
byte[] ivBytes= new byte[16];
System.arraycopy(passwordBytes, 0, ivBytes, 0, 16);
//Get the authString as byte[]
byte[] authBytes = new BASE64Decoder().decodeBuffer(authString);
InputStream inputStream = new ByteArrayInputStream(authBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// If you have Bouncycastle library installed, you can use
// Rijndael/CBC/PKCS7PADDING directly.
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7PADDING", "BC");
// convertedSecureString and initVector must be byte[] with correct length
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(passwordBytes, "AES"), new IvParameterSpec(ivBytes));
CipherInputStream cryptoStream = new CipherInputStream(inputStream, cipher);
byte[] buffer = new byte[1024];
len = cryptoStream.read(buffer, 0, buffer.length);
while (len > 0) {
outputStream.write(buffer, 0, len);
len = cryptoStream.read(buffer, 0, buffer.length);
}
outputStream.flush();
cryptoStream.close();
String resStr = outputStream.toString("UTF-8");
return resStr; //<<--- resStr must be "101714994"
} catch (Throwable t) {
}
return null;
}
程序运行没有任何错误,但结果不是我想要的。任何帮助将不胜感激。
最佳答案
您不需要为此使用 BouncyCaSTLeProvider,因为 AES 已包含在 Java 中。但是 PKCS#7 填充是 incorrectly由 "PKCS5Padding"
指示,因此 "AES/CBC/PKCS7Padding"
不能在没有 Bouncy CaSTLe 的情况下指示。
.NET默认的Unicode
编码其实更兼容UTF-16LE。让 Microsoft 不遵守标准名称(尽管它们可能已经在它之前)。
Java JCE 并不像 C# 类那样真正围绕流构建,因此最好完全避免流。
我已经重写了您的示例代码,以展示如何在 Java 中正确编写代码(尽管您需要与 Java 7 兼容)。不要隐藏异常,将它们转化为 AssertError
或 RuntimeException
。
我使用的是 Bouncy CaSTLe Base 64 解码器,因为您和我都可以使用它(但除此之外它与 Bouncy 无关)。 Java 8 有一个 base 64 class包括。
所以事不宜迟:
import static java.nio.charset.StandardCharsets.UTF_16LE;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.util.encoders.Base64;
public class AuthenticationStringDecrypter {
private static final String AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5PADDING";
private static final int KEY_SIZE = 256;
public static void main(final String[] args) throws Exception {
System.out.println(decryptAuthorizationString(
"c1W2YO1vYQzu6czteEidrG0U4g5gT4h57vAlP7tdjcY=", "GAT"));
}
private static String decryptAuthorizationString(final String authString,
final String password) {
try {
// --- check if AES-256 is available
if (Cipher.getMaxAllowedKeyLength(AES_CBC_PKCS5PADDING) < KEY_SIZE) {
throw new IllegalStateException("Unlimited crypto files not present in this JRE");
}
// --- create cipher
final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING);
// --- create the key and initial vector bytes
final byte[] passwordEncoded = password.getBytes(UTF_16LE);
final byte[] keyData = Arrays.copyOf(passwordEncoded, KEY_SIZE
/ Byte.SIZE);
final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize());
// --- init cipher
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyData, "AES"),
new IvParameterSpec(ivBytes));
// --- decode & decrypt authentication string
final byte[] authBytes = Base64.decode(authString);
final byte[] decryptedData = cipher.doFinal(authBytes);
// WARNING: may still decrypt to wrong string if
// authString or password are incorrect -
// BadPaddingException may *not* be thrown
return new String(decryptedData, UTF_16LE);
} catch (BadPaddingException | IllegalBlockSizeException e) {
// failure to authenticate
return null;
} catch (final GeneralSecurityException e) {
throw new IllegalStateException(
"Algorithms or unlimited crypto files not available", e);
}
}
}
关于java - 解密 C# RIJNDAEL 编码的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25064529/
表架构 DROP TABLE bla; CREATE TABLE bla (id INTEGER, city INTEGER, year_ INTEGER, month_ INTEGER, val I
我需要拆分字符串/或从具有以下结构的字符串中获取更容易的子字符串。 字符串将来自 window.location.pathname 或 window.location.href,看起来像 text/n
每当将对象添加到数组中时,我都会尝试更新 TextView ,并在 TextView 中显示该文本,如下所示: "object 1" "object 2" 问题是,每次将新对象添加到数组时,它都会覆盖
我目前正在寻找使用 Java 读取网站可见文本并将其存储为纯文本字符串的方法。 换句话说,我想转换成这样: Hello stupid World进入“ Hello World ” 或者类似的东西 Un
我正在尝试以文本和 HTML 格式发送电子邮件,但无法正确发送正确的 header 。特别是,我想设置 Content-Type header ,但我找不到如何为 html 和文本部分单独设置它。 这
我尝试了上面的代码,但我无法绑定(bind)文本,我怎样才能将资源内部文本 bloc
我刚刚完成了 Space Shooter 教程,由于没有 GUIText 对象,所以我创建了 UI.Text 对象并进行了相应的编码。它在统一播放器中有效,但在构建 Web 应用程序后无效。我花了一段
我有这个代码: - (IBAction)setButtonPressed:(id)sender { NSUserDefaults *sharedDefaults = [[NSUserDefau
抱歉标题含糊不清,但我想不出我想在标题中做什么。无论如何,对于图像上的文本,我使用了 JLabel 文本并将其添加到图标中。 JLabel icon = new JLabel(new Imag
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我在将 Twitter 嵌入到我从 HTML 5 转换的 wordpress 运行网站时遇到问题。 我遇到的问题是推文不是我的自定义字体... 这是我无法使用任何 css 定位的 HTML 代码,我正
我正在尝试找到解决由于使用以下形式的代码而导致的冗余字符串连接问题的最佳方法: logger.debug("Entering loop, arg is: " + arg) // @1 在大多数情况下,
我写了这个测试 @Test public void removeRequestTextFromRouteError() throws Exception { String input = "F
我目前正在创建一个正则表达式来拆分所有匹配以下格式的字符串:&[文本],并且需要获取文本。字符串可能类似于:something &[text] &[text] everything &[text] 等
有没有办法将标题文本从一个词变形为另一个词,同时保留两个词中使用的字母?我看过的许多 css 文本动画大多是视觉的,很少有旋转整个单词的。 我想要做的是从一个词过渡,例如“BEACH”到“CHANGE
总结matplotlib绘图如何设置坐标轴刻度大小和刻度。 上代码: ?
我在容器 (1) 中创建了容器 (2)。你能帮忙如何向容器(1)添加文本吗?下面是我的代码 return Scaffold( body: Padding( padding: c
我似乎找不到任何人或任何人这样做过。我试图限制我们使用的图像数量,并想创建一个带有渐变作为其“颜色”的文本,并在其周围设置渐变轮廓/描边 到目前为止,我还没有看到任何将两者结合在一起的东西。 我可以自
我正在为视频游戏暗黑破坏神 2 使用 discord.py 构建一个不和谐机器人。其中一项功能要求机器人从暗黑破坏神 2 屏幕截图中提取项目的名称和属性。我目前正在为此使用 pytesseract,但
我很难弄清楚如何旋转 strip.text theme 中的属性来自 ggplot2 .我使用的是 R 版本 3.4.2 和 ggplot2 版本 2.2.1。 以下是 MWE 的数据。 > dput
我是一名优秀的程序员,十分优秀!