问题描述:项目需要使用secp256k1类型的椭圆曲线进行加解密,客户端是用java实现的,而后台是用golang。问题在于java有secp256k1的标准库,可以生成密钥和加密,通过x509序列化之后传给golang后台,但是golang没有该标准库,无法进行验证。

解决方案(两种)

  • 对照java的标准库用golang自行实现可用的椭圆曲线(待定)
  • java实现验证,编成jar包,利用golang中的os/exec包调用jar,得到结果

准备: java和golang的运行环境
java代码(验证):

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.sun.org.apache.xerces.internal.impl.dv.util.HexBin;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;


/**
 * Created by bqh on 2017/4/8.
 * <p>
 * E-mail:M201672845@hust.edu.cn
 */
public class Verify {
    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException,
            InvalidAlgorithmParameterException,InvalidKeyException,SignatureException {
        if (args.length != 3) {
            System.out.println("args length invalid");
        }

        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decode(args[0]));
        KeyFactory fact = KeyFactory.getInstance("ECDSA", "BC");
        PublicKey publicKey = fact.generatePublic(x509EncodedKeySpec);

        Signature signature = Signature.getInstance("SHA1withECDSA");
        signature.initVerify(publicKey);
        signature.update(args[1].getBytes());
        boolean flag = signature.verify(HexBin.decode(args[2]));
        System.out.println(flag);
    }
}

用idea生成一个jar文件Verify.jar,能在命令行中成功运行

java -jar Verify.jar 参数1 参数2 参数3

即可认定jar可用(我遇到报错Invalid signature file digest for Manifest main attributes,这是由于jar签名不合法,用winrar打开该jar,删除.SF文件即可)

golang调用代码:

package main

import (
    "fmt"
    "os/exec"
)

const (
    sigScript  string = "3046022100E4C617A5626E408938EEAC33D7BC0ACD645D8FF0B9A29FE55EC3F9BAB01A07C9022100D0F9E8A545E997F3E431C5E3DADA0EC5F53ACE6A7E9598FD6F3B85BE055D3E10"
    unsignedTx string = "bqh"
    pubScr     string = "MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEnpwnu94soZ/z9QdfTEwJAY+Qhz34pLsNFZA/OgmhekTIBBdJyxpHs4GaId3wWrq11OyqmJlu2qCLDtZcGFBjdA=="
    priScr     string = "MIGNAgEAMBAGByqGSM49AgEGBSuBBAAKBHYwdAIBAQQg49U3dRtNk+WZ6E1BJKIM8oHP2zm766HFTF9jjP1RM9qgBwYFK4EEAAqhRANCAASwYY8XyIPfiNnfkC25axj/Lw6Eq64hVaz34PKquSwiujCk3tB21VivJwrUJkXhkCmAxYsYhF6izcNLpOAvDrPO"
)

func main() {
    cmd := exec.Command("java", "-jar", "Verify.jar", pubScr, unsignedTx, sigScript)
    out, err := cmd.Output()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Print(string(out))
}

成功返回true!
这种方法看起来不太安全,下一步计划用golang实现secp256k1类型的椭圆曲线。

参考资料:

  • 建议尝试的GoJVM(未使用) https://github.com/abneptis/GoJVM
  • 依赖包:bcpkix-jdk15on-156.jar、bcprov-ext-jdk15on-156.jar、core-1.54.0.0.jar