Javascript-javaecdh

Javascript-javaecdh,java,bouncycastle,public-key,secret-key,ecdh,Java,Bouncycastle,Public Key,Secret Key,Ecdh,在我的场景中,Alice和Bob就使用哪条曲线达成了一致 Alice生成公钥和私钥 Alice将公钥发送给Bob Bob根据收到的Alice公钥生成他的密钥并生成会话密钥(或密钥或共享密钥) 我的问题是Alice的公钥实际上是一个点,所以它是xy格式的 我需要将x,y坐标字节转换成一个ECPublicKey 这是我正在使用的源代码 // outerPublicKey is the raw bytes from x,y coordinates in hex format Key

在我的场景中,Alice和Bob就使用哪条曲线达成了一致

  • Alice生成公钥和私钥
  • Alice将公钥发送给Bob
  • Bob根据收到的Alice公钥生成他的密钥并生成会话密钥(或密钥或共享密钥)
我的问题是Alice的公钥实际上是一个点,所以它是xy格式的

我需要将x,y坐标字节转换成一个ECPublicKey

这是我正在使用的源代码

    // outerPublicKey is the raw bytes from x,y coordinates in hex format
    KeyFactory kf = KeyFactory.getInstance("EC");

    PublicKey remoteAlicePub = kf.generatePublic(new X509EncodedKeySpec(outerPublicKey));

    KeyPairGenerator bobKeyGen = KeyPairGenerator.getInstance("ECDH", "BC");
    bobKeyGen.initialize(new ECGenParameterSpec(properties.getCurveName()), new SecureRandom());

    KeyPair bobPair = bobKeyGen.generateKeyPair();
    ECPublicKey bobPub = (ECPublicKey)bobPair.getPublic();
    ECPrivateKey bobPvt = (ECPrivateKey)bobPair.getPrivate();

    byte[] bobPubEncoded = bobPub.getEncoded();
    byte[] bobPvtEncoded = bobPvt.getEncoded();

    KeyAgreement bobKeyAgree = KeyAgreement.getInstance("ECDH");
    bobKeyAgree.init(bobPvt);
    bobKeyAgree.doPhase(remoteAlicePub, true);

    return DatatypeConverter.printHexBinary(bobKeyAgree.generateSecret());
问题是:

    new X509EncodedKeySpec(outerPublicKey);
如何从点的xy坐标创建公钥? 因为
outerPublicey
是x,y坐标的原始字节数组,我应该使用哪种格式?

我用这种方式解决了(Java服务器端)

//获取一个类似以下的字符串04456CB4BA8EE9263311485BAA8562C27991F7FF22D59F3D8245B9A05661D159911B632A6F8A7A080D82F4CA77E4D12BB201B89C8EC93F61D5B4DD22DF42E4B82
映射结果=新的HashMap();
试一试{
//设置提供程序
addProvider(新的BouncyCastleProvider());
//从十六进制到ECPublicKey的转换
字节[]ecRawExternalPublicKey=this.toByte(externalRawPublicKey);
ECPublicKey ecExternalPublicKey=null;
KeyFactory externalKeyFactor=null;
ECNamedCurveParameterSpec ecExternalNamedCurveParameterSpec=ECNamedCurveTable.getParameterSpec(“secp256r1”);
ECCurve curve=ecExternalNamedCurveParameterSpec.getCurve();
EllipticCurve EllipticCurve=EC5Util.convertCurve(curve,ecExternalNamedCurveParameterSpec.getSeed());
java.security.spec.ECPoint ECPoint=ECPointUtil.decodePoint(ellipticCurve,ecRawExternalPublicKey);
java.security.spec.ECParameterSpec ECParameterSpec=EC5Util.convertSpec(ellipticCurve,ecExternalNamedCurveParameterSpec);
java.security.spec.ECPublicKeySpec externalPublicKeySpec=new java.security.spec.ECPublicKeySpec(ecPoint,ecParameterSpec);
externalKeyFactor=java.security.KeyFactory.getInstance(“EC”);
//这是externalPubicKey
ecExternalPublicKey=(ECPublicKey)externalKeyFactor.generatePublic(externalPublicKeySpec);
KeyPairGenerator keyGen=KeyPairGenerator.getInstance(“ECDH”、“BC”);
初始化(新的ECGenParameterSpec(“secp256r1”)、新的SecureRandom();
KeyPair=keyGen.generateKeyPair();
ECPublicKey pub=(ECPublicKey)pair.getPublic();
ECPrivateKey pvt=(ECPrivateKey)pair.getPrivate();
字节[]pubEncoded=pub.getEncoded();
字节[]pvtEncoded=pvt.getEncoded();
KeyAgreement keyAgree=KeyAgreement.getInstance(“ECDH”);
keyAgree.init(pvt);
keyAgree.doPhase(ecExternalPublicKey,true);
System.out.println(“sharedKey:+this.bytesToHex(keyAgree.generateScret()));
//内部公钥
返回“04”+pub.getW().getAffineX().toString(16)+pub.getW().getAffineY().toString(16)
}
捕获(例外e){
e、 printStackTrace();
返回null;
}
Javascript(客户端)

ecdhHandShake(){
让_this=this;
这个.keyGeneration()
.然后(k=>{
阿贾克斯({
url:“http://localhost:5050/test/ecdh/handshake",
标题:{
“内容类型”:“应用程序/json”
},
正文:{
公钥:this.buf2Hex(this.publickey)
},
方法:“POST”,
跨域:是的,
responseType:'json'
})
.订阅(
有效载荷=>{
const publicKey=_this.hex2Arr(payload.response.publicKey);
_this.serverPublicKey=_this.hex2Arr(payload.response.publicKey);
_this.importServerKey()
.然后(sharedSecret=>{
const sharedSecretHex=this.buf2Hex(sharedSecret);
log(“共享密钥:+sharedSecretHex”);
})
.catch(e=>{
控制台日志(e);
})
},
错误=>{
console.log(错误);
},
()=>console.log('done'))
)
;
})
.catch(e=>{
控制台日志(e);
})
;
}
keyGeneration(){
让_this=this;
返回window.crypto.minute.generateKey(
{
名称:“ECDH”,
namedCurve:“P-256”//曲线名称
},
是的,//{
_this.keys=key;
返回window.crypto.minute.exportKey(
“raw”//可以是“jwk”(公共或私有)、“raw”(仅限公共)、“spki”(仅限公共)或“pkcs8”(仅限私有)
_这是公用钥匙
)
。然后(rawPublicKey=>{
_this.publicKey=rawPublicKey;
返回公钥;
})
.catch(函数(err){
控制台错误(err);
})
;
})
.catch(函数(err){
控制台错误(err);
})
;
}
importServerKey(){
返回window.crypto.minute.importKey(
“生的”,
这个.serverPublicKey,
{
名称:‘ECDH’,
namedCurve:'P-256'
},
是的,
[]
)
。然后(aliceKeyImported=>{
返回window.crypto.minute.deriveBits(
{
名称:‘ECDH’,
namedCurve:'P-256',
公众:Alicekeye
},
这是私钥,
256)
})
.catch(e=>{
控制台日志(e);
})
}
hex2Arr(str){
如果(!str){
返回新的Uint8Array();
}
常数arr=[];
for(设i=0,len=str.length;i('00'+x.toString(16)).slice(-2))
.加入(“”)
}
(x,y)信息不足,
// arrive a string like this 04456cb4ba8ee9263311485baa8562c27991f7ff22d59f3d8245b9a05661d159911b632a6f8a7a080d82f4ca77e4d12bb201b89c8ec93f61d5b4dd22df42e1b482
Map<String, Object> result = new HashMap<>();
    try {

        // set provider
        Security.addProvider(new BouncyCastleProvider());

        // transform from hex to ECPublicKey
        byte[] ecRawExternalPublicKey = this.toByte(externalRawPublicKey);
        ECPublicKey ecExternalPublicKey = null;
        KeyFactory externalKeyFactor = null;

        ECNamedCurveParameterSpec ecExternalNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("secp256r1");
        ECCurve curve = ecExternalNamedCurveParameterSpec.getCurve();
        EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, ecExternalNamedCurveParameterSpec.getSeed());
        java.security.spec.ECPoint ecPoint = ECPointUtil.decodePoint(ellipticCurve, ecRawExternalPublicKey);
        java.security.spec.ECParameterSpec ecParameterSpec = EC5Util.convertSpec(ellipticCurve, ecExternalNamedCurveParameterSpec);
        java.security.spec.ECPublicKeySpec externalPublicKeySpec = new java.security.spec.ECPublicKeySpec(ecPoint, ecParameterSpec);

        externalKeyFactor = java.security.KeyFactory.getInstance("EC");
        // this is externalPubicKey
        ecExternalPublicKey = (ECPublicKey) externalKeyFactor.generatePublic(externalPublicKeySpec);

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ECDH", "BC");
        keyGen.initialize(new ECGenParameterSpec("secp256r1"), new SecureRandom());

        KeyPair pair = keyGen.generateKeyPair();
        ECPublicKey pub = (ECPublicKey)pair.getPublic();
        ECPrivateKey pvt = (ECPrivateKey)pair.getPrivate();

        byte[] pubEncoded = pub.getEncoded();
        byte[] pvtEncoded = pvt.getEncoded();

        KeyAgreement keyAgree = KeyAgreement.getInstance("ECDH");
        keyAgree.init(pvt);
        keyAgree.doPhase(ecExternalPublicKey, true);

        System.out.println("sharedKey: "+ this.bytesToHex( keyAgree.generateSecret() ));

        // internal public key
        return "04"+ pub.getW().getAffineX().toString(16) + pub.getW().getAffineY().toString(16)

    }
    catch (Exception e ){
        e.printStackTrace();
        return null;
    }
ecdhHandShake() {
    let _this = this;

    this.keyGeneration()
    .then( k => {
        ajax({
            url: "http://localhost:5050/test/ecdh/handshake",
            headers: {
                "Content-Type": "application/json"
            },
            body: {
                publickey: this.buf2Hex(this.publicKey)
            },
            method: 'POST',
            crossDomain: true,
            responseType: 'json'
        })
        .subscribe(
            payload => {
                const publicKey = _this.hex2Arr(payload.response.publicKey);
                _this.serverPublicKey = _this.hex2Arr(payload.response.publicKey);

                _this.importServerKey()
                .then(sharedSecret => {
                    const sharedSecretHex = this.buf2Hex(sharedSecret);
                    console.log("shared key: "+ sharedSecretHex);
                })
                .catch( e => {
                    console.log(e);
                })
            },
            error => {
                console.log(error);
            },
            () => console.log('done')
        )
        ;
    })
    .catch( e => {
        console.log(e);
    })
    ;
}


keyGeneration() {       

    let _this = this;
    return window.crypto.subtle.generateKey(
        {
            name: "ECDH",
            namedCurve: "P-256", // the curve name
        },
        true, // <== Here if you want it to be exportable !!
        ["deriveKey", "deriveBits"] // usage
    )
    .then(key => {
        _this.keys = key;
        return window.crypto.subtle.exportKey(
            "raw", //can be "jwk" (public or private), "raw" (public only), "spki" (public only), or "pkcs8" (private only)
            _this.keys.publicKey
        )
        .then(rawPublicKey => {
            _this.publicKey = rawPublicKey;
            return rawPublicKey;
        })
        .catch(function(err){
            console.error(err);
        })
        ;
    })
    .catch(function(err){
        console.error(err);
    })
    ;

}

importServerKey() {

    return window.crypto.subtle.importKey(
        'raw',
        this.serverPublicKey,
        {
            name: 'ECDH',
            namedCurve: 'P-256'
        },
        true,
        []
    )
    .then(aliceKeyImported => {
        return window.crypto.subtle.deriveBits(
            {
                name: 'ECDH',
                namedCurve: 'P-256',
                public: aliceKeyImported
            },
            this.keys.privateKey,
            256)
    })
    .catch( e => {
        console.log(e);
    })
}


hex2Arr( str ) {
    if (!str) {
        return new Uint8Array();
    }
    const arr = [];
    for (let i = 0, len = str.length; i < len; i+=2) {
        arr.push(parseInt(str.substr(i, 2), 16));
    }
    return new Uint8Array(arr);
}

buf2Hex( buf ) {
    return Array.from(new Uint8Array(buf))
        .map(x => ('00' + x.toString(16)).slice(-2))
        .join('')
}