使用带有BouncyCastle的iSeries加密API

时间:2014-11-10 09:56:56

标签: c# bouncycastle ibm-midrange

我正在尝试加密C#客户端和iSeries服务器之间的通信,但遇到了一些问题。我正在尝试使用Diffie Hellman创建共享密钥,但共享密钥不匹配。

我在C#中使用Bouncy Castle,在iSeries上使用QC3 * API。步骤是:

  1. C#客户端生成DH参数,并将其与客户端公钥一起发送到服务器。
  2. C服务程序解码参数并调用QC3GENDK以创建服务器公钥。
  3. 服务器使用客户端公钥调用QC3CALDS以生成共享密钥。
  4. 将服务器公钥发送回客户端。
  5. 使用客户私钥初始化Bouncy Castle基本DH协议
  6. 客户端使用从步骤1中的参数和服务器公钥生成的DHPublicKeyParameters调用CalculateAgreement。
  7. 数据来回发送的方式是转换为HEX字符串并在每一侧进行解码。 EBCDIC和ASCII之间的转换发生在iSeries上的服务程序中。例如,客户端公钥转换如下:

    1. 将公钥(如BigInteger)转换为无符号字节数组,例如256 - > {1,0}
    2. 将字节数组转换为HEX字符串,例如{1,0} - > “0100”)
    3. 将HEX字符串发送到iSeries。
    4. 通过以下(RPG)代码将HEX字符串转换为长度为64的字符数组:

      cvtch( %Addr (@clientKey ): %Addr(data4): 128);
      eval @clientKey = %Subst( @clientKey: 1: 64);
      

      其中:

      data4 - HEX字符串

      @clientKey - 64A接收器变量

    5. ,服务器密钥通过以下方式转换为Hex:

      1. 转换为服务器上的十六进制字符串

        cvthc ( %Addr( @serverKeyHex ): %Addr(@serverKey): 128);
        eval @serverKeyHex = %Subst(@serverKeyHex: 1: 128);
        

        其中:

        @serverKey是64A serverKey

        @serverKeyHex是128A接收器变量

      2. 将HEX字符串发送到C#客户端

      3. 通过

        将HEX字符串解释为BigInteger

        var serverKey = new BigInteger(serverHex,16);

      4. 因此,共享密钥不匹配,但我不知道这是否与我如何解释密钥或发送它们有关。感谢您的任何建议。

        编辑: 举一个具体的例子:

        在RPG调试器中我可以看到: RPG debugger

        对于其十六进制为的客户公钥:4F58E1463B66CAAC1BDD35C518A6B76E52E0464E635050B50C87329CFC4C154B8EA07B12AF0E0B9754D5331235805CF59ABE1BB500B4906BD03BCF6C7861E2E8

        EDIT2(更多信息): 可以在此要点中看到iSeries上的API调用(在C中): https://gist.github.com/ximenean/a0a9193b776f301997bb

1 个答案:

答案 0 :(得分:2)

我不知道C#端发生了什么转换,但RPG / MI端正在从字符串转换为字符串。取一个EBCDIC字符串'ABCD'这是一个完全有效的4字节二进制数,以及一个完全有效的4字节字符。在EBCDIC CCSID 37(美国英语)中,该字符串具有代码点x'C1C2C3C4'。

CVTCH将生成以下字符串:'C1C2C3C4'即,它需要一个4个字符的字符串并将其“转换”为8个字符的字符串。在CCSID 37中,即x'C3F1C3F2C3F3C3F4'。如果你把这个字符串发送到一个用ASCII解释它的客户端,它将被完全不同地解释,因为ASCII的代码点x'C1C2C3C4'是ASCII字符串'ÁÂÃÄ'

您可能希望在从IBM端发送之前将其转换为ASCII。 'C1C2C3C4'将变为'41424344'等等。