3

I have this code in node.js, it create Key using Crypto. Can i create same key using Java?

diffieHellmanConfig': {
      'group': 'modp14',
      'encoding': 'base64'
    }


 const clientDHInstance = crypto.getDiffieHellman(config.userCardCrypto.diffieHellmanConfig.group);
 clientDHInstance.generateKeys();

 const clientPublicKey = clientDHInstance.getPublicKey(config.userCardCrypto.diffieHellmanConfig.encoding);

I try to use

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
keyGen.initialize(2048);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();
byte[] encoded = publicKey.getEncoded();
String s = Base64.getEncoder().encodeToString(encoded);
System.out.println(s);

But key is wrong

Node key is t2EBMu8wCShfu8Dm45i9nNQ+TXyG5Oz1/izjTwRD0dchUK2400R9cP+NjLlOqjLstXnTbG5/aa0WaCoP187J90piiebGOjZUlF/Bu/xkkrYncQHAJ403J8+R2V5eHYCSQXbS6CSO7x+eEhNz8QTMgwkOR9w1R3gvbibaqL7qyQARPFak6+VIKFLUakSzMvdAIjLNPu2dva1QdJixid+EYiZE/DxA7lqpje74I7wynZj7kmUZXtiIWu46suf5CaVONtjEVZilvErJNpVlPX5TXoMVNrWkl9g5Aa6moXg4K0M6Gc4taumnDr9gh4PEuw+/QVauEld27/5TQlfAlalvzg==

Java key is MIICKTCCARsGCSqGSIb3DQEDATCCAQwCggEBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMoYIXwykF5GLjbOO+OedywYDoYDmyeDouwHoo+1xV3wb0xSyd4ry/aVWBcYOZVJfOqVauUV0iYYmPoFEBVyjlqKrKpo//////////8CAQICAgQAA4IBBgACggEBAI+NYSvMh0bfh1ptt62vHEHENz6ZAYvnnrwmRhQRdYMBZiqu60AvJ4F6qL99EfesxvH3n8YaC+cG7bKAqkw74rRHJXkMF5xOy/kpTVvmQGAPjvTi5o4BJtHLOBgiwFKy7CYFKFksCJzkqNdAuPri/mfMm6GNG5MBYtQIurWkgOnnrVl3Nra2CSVUixQ5zCANOSnnNYNFPanr01bI6KZXsiRZRqfA4oYxBPySy4Sp1dx2IvSQe8EjNWTicTQQj/HP7hl1yf3uiYlM4h3dMbmfqv6Y10hW8kvoD88/mh09pdz+HxxDz+mVSMe+3+N7VIYUEGRHhrAvjbXmwh5zyCMIJiI=

  • what's the problem with the key? When you say 'same' key, you mean the same size right? Or you actually want to generate the same key instance? i.e. literally the same key bytes... when you make a call to genKeyPair() or generateKeys() you will of course by definition get different key material. – Woodstock Mar 06 '20 at 13:02
  • @Woodstock Java key is bigger than node, also when i try to send it to server i got response {"code":500,"message":"Supplied key is too large"} – Michael Sych Mar 06 '20 at 13:09
  • Can you supply two example keys, one from node and one from Java so I can take a look at the formats pls? – Woodstock Mar 06 '20 at 13:12
  • @Woodstock update question – Michael Sych Mar 06 '20 at 13:23
  • Ok, think I figured it, will write up answer – Woodstock Mar 06 '20 at 13:28

1 Answers1

3

In your example keys, the DH keys created by node are the expected 2048 bits in size, however, the Java DH keys are pushing into ~4k bits.

So I think there is something wrong with the way you are initialising the DH keys on Java.

Looking at your code, I don't think it's appropriate to provide an integer literal to specify the size of the DH cyclic group.

Instead try instantiating your Java DH keys like this:

  final DHParameterSpec keySpec=new DHParameterSpec(DH_MODULUS,DH_BASE);
  final KeyPair keyPair;
  try {
    KeyPairGenerator keyGen=KeyPairGenerator.getInstance("DH");
    keyGen.initialize(keySpec);
    keyPair=keyGen.generateKeyPair();
    PrivateKey privateKey = keyPair.getPrivate();
    PublicKey publicKey = keyPair.getPublic();
    byte[] encoded = publicKey.getEncoded();
    String s = Base64.getEncoder().encodeToString(encoded);
    System.out.println(s);
  }

You need to create a DHParameterSpec object in Java providing a modulus and base, similar to the values provided in node.

Example:

public DHParameterSpec modp14() {
  final BigInteger p =
      new BigInteger(
          "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
              + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
              + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
              + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
              + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
              + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
              + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
              + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
              + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
              + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
              + "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
          16);
  final BigInteger g = new BigInteger("2");
  return new DHParameterSpec(p, g);
}

Pls see here for specification on prime group.

Community
  • 1
  • 1
Woodstock
  • 22,184
  • 15
  • 80
  • 118
  • Thank you, but how can I find values provided in node – Michael Sych Mar 06 '20 at 13:41
  • @MichaelSych the prime used by node is actually always ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff and the base is 2. – Woodstock Mar 06 '20 at 13:53
  • If you use my code above the keys will be compatible every time. @MichaelSych – Woodstock Mar 06 '20 at 13:53
  • I use your code with DHParameterSpec modp14(), what i need to do after keyAgreement.init(keyPair.getPrivate()); to get key as String in Base64)) Sorry i'm first time work with crypto) @Woodstock – Michael Sych Mar 06 '20 at 14:01
  • 1
    I updated my code to reflect your original intent @MichaelSych, pls mark question as answered if this works for you. – Woodstock Mar 06 '20 at 14:07
  • I copied your solution, with final DHParameterSpec keySpec = modp14(); but still get the wrong key(( something like that MIICKDCCARsGCSqGSIb3DQEDATCCAQwCggEBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7ORbPcIAfLihY78FmNpINhxV05ppFj+o/STPX4NlXSPco62WHGLzViCFUrue1SkHcJaWbWcMNU5KvJgE8XRsCMoYIXwykF5GLjbOO+OedywYDoYDmyeDouwHoo+1xV3wb0xSyd4ry/aVWBcYOZVJfOqVauUV0iYYmPoFEBVyjlqKrKpo//////////8CAQICAgQAA4IBBQACggEANkYj2zS2SlVRztRcMIkl1a7x..... @Woodstock – Michael Sych Mar 06 '20 at 14:20
  • I think you need to check that your comparing the correct keys... pub to pub and private to private... – Woodstock Mar 06 '20 at 14:30
  • And why first part of key is always same? MIICKTCCARsGCSqGSIb3DQEDATCCAQwCggEBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJRSgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL @Woodstock – Michael Sych Mar 06 '20 at 14:42
  • 2
    The Java key _is_ 2048 bits (and public), but is in **X.509 SubjectPublicKeyInfo format**, as specified in the javadoc for Key, which contains the parameters (p and g) as well as the actual key (y) plus some overhead, making the representation 557 bytes total. At least for now Java does use group 14 parameters for size=2048, but this is not guaranteed and specifying them yourself is indeed better. @MichaelSych: the initial part that is 'always the same' is the outer TLV and X.509 AlgorithmId containing the OID and parameters, which _should_ be the same. – dave_thompson_085 Mar 06 '20 at 16:10
  • @dave_thompson_085 THANK you! i just change 2048 to 512 and all works!! – Michael Sych Mar 06 '20 at 16:16
  • 1
    @MichaelSych+ if you want only the y value use `((DHPublicKey)publicKey).getY().toByteArray()` and if necessary trim (or in rare cases pad) the result to 256 bytes. And convert to base64 since you want that. – dave_thompson_085 Mar 06 '20 at 16:18
  • @MichaelSych: specifying `keygen.init(512)` will not give you a group-14 key. It will give you a key in some smaller group that is easily breakable, provides no security at all, and will not be interoperable with any competently designed system or program. Search 'logjam' for _many_ examples. – dave_thompson_085 Mar 06 '20 at 16:19
  • @dave_thompson_085 i need it only for back end autotests so don't care about security of key)) – Michael Sych Mar 06 '20 at 16:22