Created
November 22, 2016 14:07
-
-
Save pavlo/0a3089029f047e509a1e4c8a42f809e3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.foo; | |
import sun.security.ec.ECPrivateKeyImpl; | |
import sun.security.ec.ECPublicKeyImpl; | |
import javax.crypto.KeyAgreement; | |
import java.math.BigInteger; | |
import java.security.*; | |
import java.security.interfaces.ECPrivateKey; | |
import java.security.interfaces.ECPublicKey; | |
import java.security.spec.*; | |
import static javax.xml.bind.DatatypeConverter.printHexBinary; | |
import static javax.xml.bind.DatatypeConverter.parseHexBinary; | |
// iOS - https://github.com/ricmoo/GMEllipticCurveCrypto? | |
// C - https://github.com/esxgx/easy-ecc | |
// NodeJS - https://github.com/indutny/elliptic | |
// Java - http://connect2id.com/products/nimbus-jose-jwt | |
public class ECCStuff { | |
private static final String DS_PUBLIC_KEY_X509 = "3059301306072A8648CE3D020106082A8648CE3D030107034200049ECCEB1FB448414F9C9AFF4F5734005A2A63D568ED48725B024CD9B715ACCA6600FB9AF5635B67BB419EBCD635E71ED7079D341502C14DDF74C3AE4054E0CD70"; | |
private static final String DS_PRIVATE_KEY_PKCS8 = "3041020100301306072A8648CE3D020106082A8648CE3D030107042730250201010420CC309591D17EBF867DCB803E6A9561C30692A0971B108D75AA0D8ECC61D5CC7C"; | |
private static final String DS_PUBLIC_KEY_X = "71827489642506658763456034709171400250620549744728167720189312821359981415014"; | |
private static final String DS_PUBLIC_KEY_Y = "444548097847232459367223840555011063388349913266591690778394366523838877040"; | |
private static final String DS_PRIVATE_KEY = "92357662061556054328491863583938855342013559809943355423498537461705352793212"; | |
private static final String SDK_PUBLIC_KEY_X509 = "3059301306072A8648CE3D020106082A8648CE3D030107034200040B1C126D81DA304FB874F75EC78EFA849996FD9021B1F10CF1029E2368C4AA26DD0174E3D53ECF17E52ACD066048A88852CE356E835C9800F5320DC5AD92B66C"; | |
private static final String SDK_PRIVATE_KEY_PKCS8 = "3041020100301306072A8648CE3D020106082A8648CE3D03010704273025020101042036744775F4184AE94F2598D9FB918D5F841F8BF66DD54429C962728144BD45CF"; | |
private static final String SDK_PUBLIC_KEY_X = "5025040235973197239960723894005321281855226418603980498414503140147262171686"; | |
private static final String SDK_PUBLIC_KEY_Y = "99963713128908127595637622677267196565662543684710841894296137816645752239724"; | |
private static final String SDK_PRIVATE_KEY = "24630341287021252313437466753111713222299261312837557397825311892032817284559"; | |
// This stands for Content Encryption Key in JWA spec - is a product of key exchange, see exchange() method below | |
private static final String CEK = "3CE3782643528C8B553720252153B741C19590799B5A0E186EE26232ACDED5D8"; | |
public static void main(String[] args) throws Exception { | |
// ECCStuff.generateEcKeys(); | |
// ECCStuff.validatePublicKey(DS_PUBLIC_KEY_X509); | |
// System.out.println("----------------------------------------------"); | |
// ECCStuff.validatePrivateKey(DS_PRIVATE_KEY_PKCS8); | |
// | |
// System.out.println("----------------------------------------------"); | |
// System.out.println("----------------------------------------------"); | |
// ECCStuff.validatePublicKey(SDK_PUBLIC_KEY_X509); | |
// System.out.println("----------------------------------------------"); | |
// ECCStuff.validatePrivateKey(SDK_PRIVATE_KEY_PKCS8); | |
exchange(); | |
} | |
// partially based up on https://neilmadden.wordpress.com/2016/05/20/ephemeral-elliptic-curve-diffie-hellman-key-agreement-in-java/ | |
private static void exchange() throws Exception { | |
KeyFactory keyFactory = java.security.KeyFactory.getInstance("EC"); //ECDH | |
byte[] sdkPrivateKeyBytes = parseHexBinary(SDK_PRIVATE_KEY_PKCS8); | |
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(sdkPrivateKeyBytes); | |
ECPrivateKey skdPrivateKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec); | |
byte[] dsPublicKeyBytes = parseHexBinary(DS_PUBLIC_KEY_X509); | |
X509EncodedKeySpec dsPublicKeySpec = new X509EncodedKeySpec(dsPublicKeyBytes); | |
ECPublicKey dsPublicKey = (ECPublicKey) keyFactory.generatePublic(dsPublicKeySpec); | |
KeyAgreement ka = KeyAgreement.getInstance("ECDH"); | |
ka.init(skdPrivateKey); | |
ka.doPhase(dsPublicKey, /* the last phase in the agreement? */ true); | |
byte[] sharedSecret = ka.generateSecret(); | |
System.out.println("Shared secret: " + printHexBinary(sharedSecret)); | |
// TODO: | |
// The security considerations section of RFC 7748 advises to derive a key | |
// from the shared secret plus both public keys if we intend to use | |
// the key for authentication | |
// Designers using these curves should be aware that for each public | |
// key, there are several publicly computable public keys that are | |
// equivalent to it, i.e., they produce the same shared secrets. Thus | |
// using a public key as an identifier and knowledge of a shared secret | |
// as proof of ownership (without including the public keys in the key | |
// derivation) might lead to subtle vulnerabilities. | |
} | |
private static void generateEcKeys() throws Exception { | |
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", "SunEC"); | |
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256r1"); // I am not quite sure here but it looks like it | |
kpg.initialize(ecSpec); | |
KeyPair keyPair = kpg.genKeyPair(); | |
PrivateKey privateKey = keyPair.getPrivate(); | |
PublicKey publicKey = keyPair.getPublic(); | |
byte[] encodedPublicKey = publicKey.getEncoded(); // X.509 | |
byte[] encodedPrivateKey = privateKey.getEncoded(); // PKCS8 | |
// Display our public key | |
System.out.println("Encoded public key: " + printHexBinary(encodedPublicKey)); | |
System.out.println("Encoded private key: " + printHexBinary(encodedPrivateKey)); | |
System.out.println("Private Key as BigInteger: " + ((ECPrivateKeyImpl) privateKey).getS()); // an integer | |
BigInteger x = ((ECPublicKeyImpl) publicKey).getW().getAffineX(); | |
BigInteger y = ((ECPublicKeyImpl) publicKey).getW().getAffineY(); | |
System.out.println("Public Key X/Y: " + x + "/" + y); // x and y on the curve | |
} | |
// just to make sure we encode and decode the keys properly | |
private static void validatePublicKey(String keyString) throws Exception { | |
byte[] keyBytes = parseHexBinary(keyString); | |
X509EncodedKeySpec key = new X509EncodedKeySpec(keyBytes); | |
KeyFactory kf = java.security.KeyFactory.getInstance("EC"); //ECDH | |
ECPublicKey publicKey = (ECPublicKey) kf.generatePublic(key); | |
System.out.println("X: " + publicKey.getW().getAffineX()); | |
System.out.println("Y: " + publicKey.getW().getAffineY()); | |
} | |
private static void validatePrivateKey(String keyString) throws Exception { | |
byte[] keyBytes = parseHexBinary(keyString); | |
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); | |
KeyFactory kf = java.security.KeyFactory.getInstance("EC"); //ECDH | |
ECPrivateKey pk = (ECPrivateKey) kf.generatePrivate(keySpec); | |
System.out.println("S: " + pk.getS()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I have a public key generated from javascript, i send the (xy) hex rappresentation of that, but i have an error:
Why i get this error?