需要一个示例 - 使用Microsoft Crypto API在Java中解密字符串

时间:2009-03-18 15:40:19

标签: java encryption cryptography mscapi

首先,我不是Java程序员。我正在寻找这个问题的示例解决方案,因为我所拥有的Java开发人员在使用加密方面没有多少经验。我们在网上找到的所有内容都与加密网页和处理MS密钥库有关。我们只想使用PowerBuilder(PB)中的单个字符串,并能够用Java解密它。这里的限制是MS库。由于某些限制,我们不得不使用这种加密方法,因此可以由Java端来处理被抛出的内容。

我所拥有的是一个PB版本10.2程序,需要调用此Java实用程序并将其传递给用户名&密码。我们正在尝试将密码加密为命令行友好字符串,因为PB将调用Java应用程序。

在PB中我使用以下对象: http://www.topwizprogramming.com/freecode_crypto.html

代码正在做什么,包装在advapi32.dll中找到的Microsoft加密API。它使用的功能是:

CryptAcquireContext http://msdn.microsoft.com/en-us/library/aa379886(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

CryptDeriveKey http://msdn.microsoft.com/en-us/library/aa379916(VS.85).aspx

CryptEncrypt http://msdn.microsoft.com/en-us/library/aa379924(VS.85).aspx

它使用的是Microsoft Strong Cryptographic Provider和PROV_RSA_FULL。代码将数据加密,将其转换为BLOB,然后传递给加密函数。在那里,它执行上下文,从上下文创建哈希对象,哈希密码,从哈希获取会话密钥,然后调用加密/解密。最后一件事是返回BLOB并将其转换为ANSI字符集下的字符串。

有许多常数,我一眼就知道有些来自哪里,有些则不是这样: 常量字符串KEY_CONTAINER =“MyKeyContainer” 常量ULong PROV_RSA_FULL = 1 常数ULong CALG_MD5 = 32771 常数ULong CALG_RC4 = 26625 常量ULong ENCRYPT_ALGORITHM = CALG_RC4 常量ULONG CRYPT_NEWKEYSET = 8 常数ULong ERROR_MORE_DATA = 234

无论是使用BouncyCastle还是1.6使用像MS的Sun加密接口这样的东西,我都不在乎,我们只是渴望看到这项工作而且老实说是我们的头脑。


嘿我需要加密字符串并将其存储为文件,然后我需要再次读取该文件并解密相同的字符串。 但我不想加密整个文件。一旦我将所需的加密值存储在文件中,我就需要将其单独转换为原始字符串。 你能帮我解决一下示例代码。

1 个答案:

答案 0 :(得分:4)

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:

这种“加密”太可怕了。 RC4是密钥流密码。 永远不要对多条消息使用相同的密钥流密钥!以这种方式对多条消息使用相同的密码使得恢复纯文本和给定多个密文的密钥变得微不足道。鉴于MD5的弱点,他们也可以恢复密码。这些缺陷足以破坏良好的流密码,但RC5与MD5一样,有自己的漏洞,不建议用于新的应用程序。

我确信你知道这一切,并受到一些遗留应用程序的限制,但如果其他人看到这个答案,他们需要了解你被迫使用的PowerBuilder“加密”库是无法实现的。< / p>


由于密码输入和输出始终是“二进制”,因此当密文必须通过面向文本的通道(如命令行)时,通常会使用文本编码,例如Base-64或Base-85。如果可能,您可以在调用Java实用程序之前对Base-64编码密文吗?这样可以使您免于任何字符编码问题。