需要一个例子 - 使用 Microsoft Crypto API 在 Java 中解密字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/658826/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Need an example - decrypting string in Java using Microsoft Crypto API
提问by erickson
First and foremost, I am not a Java programmer. I'm looking for an example solution to this problem because the Java developer I have does not have much experience working with encryption. Everything we've found online pertains to encrypting web pages and dealing with the MS keystore. We just want to work with a single string from PowerBuilder (PB) and be able to decrypt it in Java. The restriction here is the MS library. Due to certain limitations, we are stuck with using this method of encrypting so it's up to the Java side to handle what's being thrown at it.
首先,我不是 Java 程序员。我正在寻找这个问题的示例解决方案,因为我的 Java 开发人员在加密方面没有太多经验。我们在网上找到的所有内容都与加密网页和处理 MS 密钥库有关。我们只想使用来自 PowerBuilder (PB) 的单个字符串并能够用 Java 对其进行解密。这里的限制是 MS 库。由于某些限制,我们一直坚持使用这种加密方法,因此由 Java 端来处理抛出的内容。
What I have is a PB version 10.2 program that needs to call this Java utility and pass it a username & password. We are trying to encrypt the password as a command line friendly string as that is how PB will make the call to the Java app.
我有一个 PB 版本 10.2 程序,它需要调用这个 Java 实用程序并向它传递用户名和密码。我们正在尝试将密码加密为命令行友好字符串,因为这就是 PB 调用 Java 应用程序的方式。
In PB I'm using the following object: http://www.topwizprogramming.com/freecode_crypto.html
在 PB 我使用以下对象:http: //www.topwizprogramming.com/freecode_crypto.html
What the code is doing, is wrapping the Microsoft cryptographic API found in advapi32.dll. The functions it uses are:
代码正在做的是包装在 advapi32.dll 中找到的 Microsoft 加密 API。它使用的功能是:
CryptAcquireContext http://msdn.microsoft.com/en-us/library/aa379886(VS.85).aspx
CryptAcquireContext http://msdn.microsoft.com/en-us/library/aa379886(VS.85).aspx
CryptCreateHash http://msdn.microsoft.com/en-us/library/aa379908(VS.85).aspx
CryptCreateHash http://msdn.microsoft.com/en-us/library/aa379908(VS.85).aspx
CryptHashData http://msdn.microsoft.com/en-us/library/aa380202(VS.85).aspx
CryptHashData http://msdn.microsoft.com/en-us/library/aa380202(VS.85).aspx
CryptDeriveKey http://msdn.microsoft.com/en-us/library/aa379916(VS.85).aspx
CryptDeriveKey http://msdn.microsoft.com/en-us/library/aa379916(VS.85).aspx
CryptEncrypt http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx
CryptEncrypt http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx
It's using the Microsoft Strong Cryptographic Provider and PROV_RSA_FULL. The code takes the data to be encrypted, converts it to a BLOB which is then passed to the encryption functions. There, it acuires a context, creates a hash object from the context, hashes the password, gets a session key from the hash, then calls encrypt/decrypt. Last thing is it takes the BLOB returned and converts it to a string under the ANSI character set.
它使用 Microsoft Strong Cryptographic Provider 和 PROV_RSA_FULL。该代码获取要加密的数据,将其转换为 BLOB,然后将其传递给加密函数。在那里,它获取一个上下文,从上下文创建一个散列对象,对密码进行散列,从散列中获取会话密钥,然后调用加密/解密。最后一件事是它获取返回的 BLOB 并将其转换为 ANSI 字符集下的字符串。
There are a number of constants which at a glance I understand where some come from, others not so much: Constant String KEY_CONTAINER = "MyKeyContainer" Constant ULong PROV_RSA_FULL = 1 Constant ULong CALG_MD5 = 32771 Constant ULong CALG_RC4 = 26625 Constant ULong ENCRYPT_ALGORITHM = CALG_RC4 Constant ULong CRYPT_NEWKEYSET = 8 Constant ULong ERROR_MORE_DATA = 234
有许多常量乍一看我明白一些来自哪里,其他人则不太清楚: Constant String KEY_CONTAINER = "MyKeyContainer" Constant ULong PROV_RSA_FULL = 1 Constant ULong CALG_MD5 = 32771 Constant ULong CALG_RC4 = 26625 Constant ULong ENCRYPT_ALGORITHM = CALG ULong CRYPT_NEWKEYSET = 8 常量 ULong ERROR_MORE_DATA = 234
Whether this is done in 1.5 using something like BouncyCastle or 1.6 with the Sun crypto interface for MS I don't care, we're just dying to see this work and are honestly over our heads.
无论这是使用 BouncyCastle 之类的东西在 1.5 中完成,还是在 1.6 中使用用于 MS 的 Sun 加密接口完成,我都不在乎,我们只是迫不及待地想看到这项工作,而且老实说,我们已经不知所措了。
Hey i need to crypt a string and store it a file and then I need to read the file again and decrypt the same string back. But i dont want to crypt the whole file. Once I have got the required crypted value stored in the file ,i need to convert that alone to the original string. Can you please help me out with the sample code.
嘿,我需要加密一个字符串并将其存储为一个文件,然后我需要再次读取该文件并将相同的字符串解密回来。但我不想加密整个文件。一旦我将所需的加密值存储在文件中,我需要将其单独转换为原始字符串。你能帮我解决示例代码吗?
回答by erickson
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class Decrypt
{
public static void main(String... argv)
throws Exception
{
byte[] password = "password".getBytes("UTF-8");
byte[] ciphertext = { -68, -112, 66, 78, 85, 50, 22, -63,
16, 24, -45, 4, -116, -14, 88, 34,
-85, 116, 105, 59, 45, -126 };
byte[] plaintext = decrypt(password, ciphertext);
System.out.println(new String(plaintext, "UTF-8"));
}
public static byte[] decrypt(byte[] password, byte[] ciphertext)
throws GeneralSecurityException
{
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] hash = digest.digest(password);
Cipher rc4 = Cipher.getInstance("RC4");
rc4.init(Cipher.DECRYPT_MODE, new SecretKeySpec(hash, "RC4"));
return rc4.doFinal(ciphertext);
}
}
N.B.:
注意:
This "encryption" is horrible. RC4 is a key stream cipher. Never use the same keystream cipher key for more than one message!Using the same password in this way for multiple messages makes it trivial to recover the plain text and the key given multiple cipher texts. Given the weakness in MD5, they can probably recover the password too. These flaws are enough to compromise a good stream cipher, but RC4, like MD5, has its own vulnerabilities and is not recommended for new applications.
这种“加密”是可怕的。RC4 是一种密钥流密码。切勿对多个消息使用相同的密钥流密码!以这种方式对多条消息使用相同的密码使得恢复纯文本和给定多个密文的密钥变得微不足道。鉴于 MD5 的弱点,他们可能也可以恢复密码。这些缺陷足以危及一个好的流密码,但 RC4 与 MD5 一样,也有其自身的漏洞,不推荐用于新应用程序。
I'm sure that you knew all that, and are constrained by some legacy application, but if other people see this answer, they need to understand that the PowerBuilder "crypto" library you are compelled to use is incompetently implemented.
我确信您知道所有这些,并且受到一些遗留应用程序的限制,但是如果其他人看到这个答案,他们需要了解您被迫使用的 PowerBuilder“加密”库是不称职地实现的。
Since cipher input and output is always "binary", a text encoding is commonly used, such as Base-64 or Base-85 when the cipher text has to pass through a text-oriented channel (like the command line). If possible, can you Base-64 encode the cipher text before invoking the Java utility? That would insulate you from any character encoding issues.
由于密码输入和输出始终是“二进制”的,因此当密文必须通过面向文本的通道(如命令行)时,通常使用文本编码,例如 Base-64 或 Base-85。如果可能,您能否在调用 Java 实用程序之前对密文进行 Base-64 编码?这将使您免受任何字符编码问题的影响。

