Java 生成 DH public 密钥大小与文档中的样本大小不同

Java generate DH public key size is not the same size as sample that documentation have

我的一份文件说

Generate the private and public keys using the Diffie-Hellman parameters (‘p’ and ‘g’). The result is ‘Pub_key’and ‘Priv_key’ (1024-bit/128 bytes).

其中 P 和 G 通过以下给出:

Diffie-Hellman-Parameters: (1024 bit) Prime (p): e5:16:e4:3e:54:57:b2:f6:6f:6c:a3:67:b3:35:ea: d8:31:99:39:fa:4d:f6:c1:b7:f8:6e:73:e9:22:a6: d1:93:93:25:5e:41:90:96:66:81:74:e3:5c:81:8a: 66:11:7f:79:9e:86:66:c8:05:0e:e4:36:f9:80:13: 51:60:6c:55:d4:5f:ab:a0:3f:39:e2:92:3b:a9:26: a9:cd:75:d4:bd:bc:a9:de:78:b6:2a:9b:84:7a:78: 1c:69:2c:06:3e:aa:cb:43:a3:96:f0:1d:12:1d:04: 27:55:d0:b7:c0:b2:df:a8:b4:98:a5:7e:4d:90:c3: 0c:a0:49:a7:ac:2b:7f:73

generator (g): 5 (0x5)

文档提供的关于 public 键的示例数据如下:

85:f0:4d:d0:03:45:64:2a:d1:2b:65:bd:1a:7c:38:72:8b:ff:0b:8e:28:1d:db: 6a:c4:f2:73:9e:82:a0:21:45:da:ab:f2:3d:17:3c:93:39:13:b1:f8:44:05:97: 10:e9:12:55:91:56:9d:e4:27:ea:e1:d2:69:ac:cb:fa:33:05:06:9d:eb:76:22: d1:da:3a:d9:82:0d:11:bd:24:fd:cc:e5:38:1d:2d:f9:9b:da:31:43:94:73:8d: fc:be:21:0e:ae:24:7b:13:03:e7:92:97:ff:74:6c:d9:19:e1:89:f6:a5:77:6e: 6e:cc:24:c8:90:0d:e0:f3:8f:15:90:72:de

但是,当我尝试自己使用 Java 使用参数生成 DH public 密钥时,我得到如下内容:

30:82:01:24:30:81:99:06:09:2A:86:48:86:F7:0D:01:03:01:30:81:8B:02:81:81:00:E5:16:E4:3E:54:57:B2:F6:6F:6C:A3:67:B3:35:EA:D8:31:99:39:FA:4D:F6:C1:B7:F8:6E:73:E9:22:A6:D1:93:93:25:5E:41:90:96:66:81:74:E3:5C:81:8A:66:11:7F:79:9E:86:66:C8:05:0E:E4:36:F9:80:13:51:60:6C:55:D4:5F:AB:A0:3F:39:E2:92:3B:A9:26:A9:CD:75:D4:BD:BC:A9:DE:78:B6:2A:9B:84:7A:78:1C:69:2C:06:3E:AA:CB:43:A3:96:F0:1D:12:1D:04:27:55:D0:B7:C0:B2:DF:A8:B4:98:A5:7E:4D:90:C3:0C:A0:49:A7:AC:2B:7F:73:02:01:05:02:02:02:00:03:81:85:00:02:81:81:00:A9:AF:1C:F3:45:77:8C:BA:BC:32:59:52:7B:EA:90:80:74:9A:1D:A7:01:D4:C4:10:74:4C:6E:E9:35:36:49:6D:0D:03:F5:2D:EC:FA:C5:CE:CD:C9:23:D3:F5:2F:C2:E0:3E:54:3C:A1:20:6B:ED:CC:6C:1F:52:26:7D:CD:E7:0D:14:F8:34:B0:36:B7:F9:FD:AC:97:4C:C0:7D:50:7E:DC:E0:D4:62:52:27:7B:FE:0B:16:62:34:81:2A:E1:8B:6A:54:EE:55:6D:C3:D0:F4:89:A1:E8:11:F0:67:3E:17:AB:BF:C3:6C:B7:37:51:29:36:45:BA:26:BF:CB:90:AE:A7

如您所见,它更长了...

这是我的编码部分

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;

public class DHKeyAgreement {

  // The 1024 bit Diffie-Hellman modulus values used by SKIP
  private static final byte skip1024ModulusBytes[] = {(byte) 0xe5, (byte) 0x16, (byte) 0xe4,
      (byte) 0x3e, (byte) 0x54, (byte) 0x57, (byte) 0xb2, (byte) 0xf6, (byte) 0x6f, (byte) 0x6c,
      (byte) 0xa3, (byte) 0x67, (byte) 0xb3, (byte) 0x35, (byte) 0xea, (byte) 0xd8, (byte) 0x31,
      (byte) 0x99, (byte) 0x39, (byte) 0xfa, (byte) 0x4d, (byte) 0xf6, (byte) 0xc1, (byte) 0xb7,
      (byte) 0xf8, (byte) 0x6e, (byte) 0x73, (byte) 0xe9, (byte) 0x22, (byte) 0xa6, (byte) 0xd1,
      (byte) 0x93, (byte) 0x93, (byte) 0x25, (byte) 0x5e, (byte) 0x41, (byte) 0x90, (byte) 0x96,
      (byte) 0x66, (byte) 0x81, (byte) 0x74, (byte) 0xe3, (byte) 0x5c, (byte) 0x81, (byte) 0x8a,
      (byte) 0x66, (byte) 0x11, (byte) 0x7f, (byte) 0x79, (byte) 0x9e, (byte) 0x86, (byte) 0x66,
      (byte) 0xc8, (byte) 0x05, (byte) 0x0e, (byte) 0xe4, (byte) 0x36, (byte) 0xf9, (byte) 0x80,
      (byte) 0x13, (byte) 0x51, (byte) 0x60, (byte) 0x6c, (byte) 0x55, (byte) 0xd4, (byte) 0x5f,
      (byte) 0xab, (byte) 0xa0, (byte) 0x3f, (byte) 0x39, (byte) 0xe2, (byte) 0x92, (byte) 0x3b,
      (byte) 0xa9, (byte) 0x26, (byte) 0xa9, (byte) 0xcd, (byte) 0x75, (byte) 0xd4, (byte) 0xbd,
      (byte) 0xbc, (byte) 0xa9, (byte) 0xde, (byte) 0x78, (byte) 0xb6, (byte) 0x2a, (byte) 0x9b,
      (byte) 0x84, (byte) 0x7a, (byte) 0x78, (byte) 0x1c, (byte) 0x69, (byte) 0x2c, (byte) 0x06,
      (byte) 0x3e, (byte) 0xaa, (byte) 0xcb, (byte) 0x43, (byte) 0xa3, (byte) 0x96, (byte) 0xf0,
      (byte) 0x1d, (byte) 0x12, (byte) 0x1d, (byte) 0x04, (byte) 0x27, (byte) 0x55, (byte) 0xd0,
      (byte) 0xb7, (byte) 0xc0, (byte) 0xb2, (byte) 0xdf, (byte) 0xa8, (byte) 0xb4, (byte) 0x98,
      (byte) 0xa5, (byte) 0x7e, (byte) 0x4d, (byte) 0x90, (byte) 0xc3, (byte) 0x0c, (byte) 0xa0,
      (byte) 0x49, (byte) 0xa7, (byte) 0xac, (byte) 0x2b, (byte) 0x7f, (byte) 0x73};


  // The SKIP 1024 bit modulus
  private static final BigInteger skip1024Modulus = new BigInteger(1, skip1024ModulusBytes);

  // The base used with the SKIP 1024 bit modulus
  private static final BigInteger skip1024Base = BigInteger.valueOf(5);

  public static void main(String[] args) throws Exception {
    DHParameterSpec dhSkipParamSpec;
    dhSkipParamSpec = new DHParameterSpec(skip1024Modulus, skip1024Base);
    System.out.println("ALICE: Generate DH keypair ...");
    KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
    aliceKpairGen.initialize(dhSkipParamSpec);
    KeyPair aliceKpair = aliceKpairGen.generateKeyPair();
    System.out.println("ALICE: Initialization ...");
    KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
    aliceKeyAgree.init(aliceKpair.getPrivate());

    // Alice encodes her public key, and sends it over to Bob.
    byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();
    byte[] alicePrivKeyEnc = aliceKpair.getPrivate().getEncoded();


    System.out.println("ALICE public key: " + toHexString(alicePubKeyEnc));
    System.out.println("Alice private key: " + toHexString(alicePrivKeyEnc));

  }

  /*
   * Converts a byte to hex digit and writes to the supplied buffer
   */
  private static void byte2hex(byte b, StringBuffer buf) {
    char[] hexChars =
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    int high = ((b & 0xf0) >> 4);
    int low = (b & 0x0f);
    buf.append(hexChars[high]);
    buf.append(hexChars[low]);
  }

  /*
   * Converts a byte array to hex string
   */
  private static String toHexString(byte[] block) {
    StringBuffer buf = new StringBuffer();

    int len = block.length;

    for (int i = 0; i < len; i++) {
      byte2hex(block[i], buf);
      if (i < len - 1) {
        buf.append(":");
      }
    }
    return buf.toString();
  }
}

是我理解错了还是文档有误?

您看到的作为 aliceKpair.getPublic().getEncoded() 结果的最终十六进制字符串是 ASN.1 DER 编码字符串。您拥有的 public 密钥(已删除 :)的十六进制字符串是

3082012430819906092A864886F70D01030130818B02818100E516E43E5457B2F66F6CA367B335EAD8319939FA4DF6C1B7F86E73E922A6D19393255E419096668174E35C818A66117F799E8666C8050EE436F9801351606C55D45FABA03F39E2923BA926A9CD75D4BDBCA9DE78B62A9B847A781C692C063EAACB43A396F01D121D042755D0B7C0B2DFA8B498A57E4D90C30CA049A7AC2B7F73020105020202000381850002818100A9AF1CF345778CBABC3259527BEA9080749A1DA701D4C410744C6EE93536496D0D03F52DECFAC5CECDC923D3F52FC2E03E543CA1206BEDCC6C1F52267DCDE70D14F834B036B7F9FDAC974CC07D507EDCE0D46252277BFE0B166234812AE18B6A54EE556DC3D0F489A1E811F0673E17ABBFC36CB73751293645BA26BFCB90AEA7

遵循以下格式。 ASN.1 格式用于以独立于平台的方式序列化和反序列化数据结构。

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
    OBJECT IDENTIFIER 1.2.840.113549.1.3.1 dhKeyAgreement (PKCS #3)
    SEQUENCE (3 elem)
      INTEGER (1024 bit) 160872061717711572653317052595503399048868038241656045229773297825253…
      INTEGER 5
      INTEGER 512
  BIT STRING (1 elem)
    INTEGER (1024 bit) 119156181916892940910396680345482295722468357006826527903397802475513…

3 元素序列包含素数 (p) 作为结构的第一个元素,生成器 (g) 作为第二个元素。 IN JDK 每个 PublicKey 类型(EC/DH/RSA 等等)包含相应的 getEncoded() 实现,它创建一个 ASN.1 编码的 DER 字符串。 Here's such an implementation 从 JDK 到 DHPublicKeyDHPrivateKey.

会有类似的实现

在您的情况下,中的素数是 1024 位,这就是您要查找的值,您感兴趣的 public 键值是 1024 位 BIT STRING 值。

您提供的示例 public 密钥是 256 个字符的十六进制编码,即 128 字节数组,即 1024 位值。这是编码的 public 密钥结构中 3 元素序列的第一个值。