0

首先,我不是 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 字符集下的字符串。

有许多常量,我一眼就知道其中一些来自哪里,而另一些则不是: ULong CRYPT_NEWKEYSET = 8 常量 ULong ERROR_MORE_DATA = 234

无论是在 1.5 中使用 BouncyCastle 之类的东西还是在 1.6 中使用用于 MS 的 Sun 加密接口来完成,我都不在乎,我们只是渴望看到这项工作,而且老实说我们都在头疼。


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

4

1 回答 1

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);
  }

}

注意:

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

我敢肯定你知道这一切,并且受到一些遗留应用程序的限制,但如果其他人看到这个答案,他们需要了解你被迫使用的 PowerBuilder“加密”库是没有能力实现的。


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

于 2009-03-18T18:10:39.803 回答