title: Derive Shared Secret From ECDH with existing foreign public key
body: <p>Im converting a method from nodeSJ to Java, but im having trouble getting it to work. Im stuck trying to calculate a derived shared secret. </p>
  
  <p>Hoping someone can catch what im doing wrong porting over the nodeJS to Java. </p>
  
  <p>NodeJS code:</p>
  
  <pre><code> //the public_key param here is from a different device. 
   sign: function(public_key)
      {
          //dummy values 
          var PRE_SALT_VALUE = 'f0f0f0f0f0';
          var POST_SALT_VALUE = '0101010101';
  
          const crypto = require('crypto');
          var sha512 = crypto.createHash("sha512");
  
          var EC = require('elliptic').ec;
          var ec = new EC('p256');
  
          // Generate keys
          var key1 = ec.genKeyPair(); //key1 is gen before pub key
          var key2 = ec.keyFromPublic(public_key, 'hex') //pub key gen from saved cert
  
          var derived_secret = key1.derive(key2.getPublic()); 
          var derived_secret = Buffer.from(derived_secret.toString(16), 'hex')
  
          var public_key_client = key1.getPublic('hex') 
  
          var pre_salt = Buffer.from(PRE_SALT_VALUE, 'hex')
          var post_salt = Buffer.from(POST_SALT_VALUE, 'hex')
  
          derived_secret = Buffer.from(pre_salt.toString('hex')+derived_secret.toString('hex')+post_salt.toString('hex'), 'hex') // finalyze shared secret 
          // Hash shared secret
          var sha = sha512.update(derived_secret);
          derived_secret = sha.digest();
  
          return {
              public_key: public_key_client.toString('hex').slice(2), //anyone know why we drop the first byte here?
              secret: derived_secret.toString('hex')  
          }
      }
  </code></pre>
  
  <p>In progress Java Code:</p>
  
  <pre><code>        //load cert from pem string (passed in from file), foreign cert
          ByteArrayInputStream input = new ByteArrayInputStream(pem);
          CertificateFactory cf = CertificateFactory.getInstance("X.509");
          Certificate cert = cf.generateCertificate(input);
          X509Certificate x509Cert = (X509Certificate) cert;
  
          // get pub key from cert
          PublicKey publicKeyForSignature = x509Cert.getPublicKey();
  
          // Generate ephemeral ECDH keypair KEY1
          KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
          kpg.initialize(256);
          KeyPair kp1 = kpg.generateKeyPair();
          byte[] ourPk = kp1.getPublic().getEncoded(); //use this later
  
          //load KEY2 from others public key
          KeyFactory kf = KeyFactory.getInstance("EC");
          X509EncodedKeySpec pkSpec = new X509EncodedKeySpec(publicKeyForSignature.getEncoded());
          PublicKey otherPublicKey = kf.generatePublic(pkSpec);
  
          // Perform key agreement
          KeyAgreement ka = KeyAgreement.getInstance("ECDH");
          ka.init(kp1.getPrivate());
          ka.doPhase(otherPublicKey, true);
  
          // Read shared secret
          byte[] sharedSecret = ka.generateSecret();
  
          // Derive a key from the shared secret and both salt keys
          MessageDigest hash = MessageDigest.getInstance("SHA-512");
          hash.update(Util.PRE_SALT_VALUE);
          hash.update(sharedSecret);
          hash.update(Util.POST_SALT_VALUE);
  
          byte[] derivedKey = hash.digest();
  
          ... etc, derivedKey = secret returned in JS method, ourPk = public_key returned in JS method. 
  </code></pre>
  
  <p>One thing i notice is that the public/private keys generated from nodejs vs java are different sizes? 65 bytes in node an 91 bytes in java. No idea why that would happen. </p>
  
  <p>What stands out as wrong here? </p>
  
  <p>Thanx</p>
  
  <p>Edit:</p>
  
  <p>So basically, I just need to know how to do this in Java</p>
  
  <pre><code> var EC = require('elliptic').ec;
   var ec = new EC('p256');
   // Generate keys
   var key1 = ec.genKeyPair();
   var key2 = ec.keyFromPublic(public_key, 'hex') //pub key from foreign device     
   var derived_secret = key1.derive(key2.getPublic());  
  </code></pre>