在Android 原生api是不支持secp256k1算法的,所以要先集成以下库:

implementation 'com.madgag.spongycastle:core:1.58.0.0'compile 'com.madgag.spongycastle:prov:1.54.0.0'compile 'com.madgag.spongycastle:pkix:1.54.0.0'compile 'com.madgag.spongycastle:pg:1.54.0.0'

然后在使用前需要添加一行代码

static {Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);}

1 获取公钥与私钥 :

private void nnnn() {X9ECParameters ecp = SECNamedCurves.getByName("secp256k1");ECDomainParameters domainParams = new ECDomainParameters(ecp.getCurve(),ecp.getG(),ecp.getN(),ecp.getH(),ecp.getSeed());// Generate a private key and a public keyAsymmetricCipherKeyPair keyPair;ECKeyGenerationParameters keyGenParams = new ECKeyGenerationParameters(domainParams, new SecureRandom());ECKeyPairGenerator generator = new ECKeyPairGenerator();generator.init(keyGenParams);keyPair = generator.generateKeyPair();ECPrivateKeyParameters privateKey = (ECPrivateKeyParameters) keyPair.getPrivate();ECPublicKeyParameters publicKey = (ECPublicKeyParameters) keyPair.getPublic();byte[] privateKeyBytes = privateKey.getD().toByteArray();// First print our generated private key and public keyLog.e("mlt",".......Private key:..........."+ECDH.toHex(privateKeyBytes));Log.e("mlt","........Public key:..........."+ECDH.toHex(publicKey.getQ().getEncoded(true)));
// Then calculate the public key only using domainParams.getG() and private keyECPoint Q = domainParams.getG().multiply(new BigInteger(privateKeyBytes));Log.e("mlt",".......Calculated public key:...." +"......."+ECDH.toHex(Q.getEncoded(true)));// The calculated public key and generated public key should always matchif (!ECDH.toHex(publicKey.getQ().getEncoded(true)).equals(ECDH.toHex(Q.getEncoded(true)))) {Log.e("mlt",".......ERROR: Public keys do not match!:...........");} else {Log.e("mlt",".......Congratulations, public keys match:...........");}}

字符转byte[]

 public static String toHex(byte[] data) {StringBuilder sb = new StringBuilder();for (byte b: data) {sb.append(String.format("%02x", b&0xff));}return sb.toString();}

先看下密钥对:

//56477ec67d3e3426db2646a9f873cb6c90753bcfc51ea1fc8b0b982dffcd8791       Private key

//0384bb60ab084f42a6093839eec228d9b3f4641ff80b6fe96a1ad55ec12ade9a8f     Public key

3 生成共享密钥

public static String generateAgreedKey(PrivateKey privateKey, PublicKey publicKey) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "SC");keyAgreement.init(privateKey);keyAgreement.doPhase(publicKey, true);byte[] sharedKeyBytes = keyAgreement.generateSecret();
//        return Base64.encodeToString(sharedKeyBytes, Base64.DEFAULT).replaceAll("\n", "");return toHex(sharedKeyBytes);}

4 因为生成对是16进制 key需要转publickey 和privatekey 还需另外方法

public static ECPublicKey keyToPublick(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {// transform from hex to ECPublicKeybyte[] ecRawExternalPublicKey = hexStringToByteArray(key);ECPublicKey ecExternalPublicKey = null;KeyFactory externalKeyFactor = null;ECNamedCurveParameterSpec ecExternalNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("secp256k1");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 externalPubicKeyecExternalPublicKey = (ECPublicKey) externalKeyFactor.generatePublic(externalPublicKeySpec);return ecExternalPublicKey;}public static ECPrivateKey keyToPrivate(String key) throws NoSuchAlgorithmException, InvalidKeySpecException {// transform from hex to ECPublicKeybyte[] ecRawExternalPublicKey = hexStringToByteArray(key);ECPrivateKey ecPrivateKey = null;KeyFactory externalKeyFactor = null;ECNamedCurveParameterSpec ecExternalNamedCurveParameterSpec = ECNamedCurveTable.getParameterSpec("secp256k1");ECCurve curve = ecExternalNamedCurveParameterSpec.getCurve();EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, ecExternalNamedCurveParameterSpec.getSeed());java.security.spec.ECParameterSpec ecParameterSpec = EC5Util.convertSpec(ellipticCurve, ecExternalNamedCurveParameterSpec);java.security.spec.ECPrivateKeySpec externalPublicKeySpec = new java.security.spec.ECPrivateKeySpec(new BigInteger(ecRawExternalPublicKey), ecParameterSpec);externalKeyFactor = java.security.KeyFactory.getInstance("EC");// this is externalPubicKeyecPrivateKey = (ECPrivateKey) externalKeyFactor.generatePrivate(externalPublicKeySpec);return ecPrivateKey;}

string key 转 byte[]

 public static byte[] hexStringToByteArray(String s) {int len = s.length();byte[] data = new byte[len / 2];for (int i = 0; i < len; i += 2) {data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)+ Character.digit(s.charAt(i + 1), 16));}return data;}

5 调用方法生成共享密钥

Log.e("mlt","...........aaa....."+ECDH.generateAgreedKey(globalData.getPrivateKey(), ECDH.keyToPublick(ss)));//随时生成私钥可以用这个

Log.e("mlt","...........aaa....."+ECDH.generateAgreedKey(ECDH.keyToPrivate(prsss), ECDH.keyToPublick(ss)));//把本地私钥保存本地

 public static String generateAgreedKey(PrivateKey privateKey, PublicKey publicKey) throws NoSuchProviderException, NoSuchAlgorithmException, InvalidKeyException {KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "SC");keyAgreement.init(privateKey);keyAgreement.doPhase(publicKey, true);byte[] sharedKeyBytes = keyAgreement.generateSecret();
//        return Base64.encodeToString(sharedKeyBytes, Base64.DEFAULT).replaceAll("\n", "");return toHex(sharedKeyBytes);}

基本就可以了,下面说几个问题,本来stringkey是用下面这两个方法,结果会出现问题

public static PublicKey stringToPublicKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException {byte[] keyBytes = Base64.decode(key.getBytes("utf-8"), Base64.DEFAULT);X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("ECDH", "SC");return keyFactory.generatePublic(spec);}
public static PrivateKey stringToPrivateKey(String key) throws UnsupportedEncodingException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {byte[] keyBytes = Base64.decode(key.getBytes("utf-8"), Base64.DEFAULT);PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("ECDH", "SC");return keyFactory.generatePrivate(spec);}

这个两个不成功所以采用上面的方法实现

参考代码:

// arrive a string like this 04456cb4ba8ee9263311485baa8562c27991f7ff22d59f3d8245b9a05661d159911b632a6f8a7a080d82f4ca77e4d12bb201b89c8ec93f61d5b4dd22df42e1b482
Map<String, Object> result = new HashMap<>();try {// set providerSecurity.addProvider(new BouncyCastleProvider());// transform from hex to ECPublicKeybyte[] 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 externalPubicKeyecExternalPublicKey = (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 keyreturn"04"+ pub.getW().getAffineX().toString(16) + pub.getW().getAffineY().toString(16)}catch (Exception e ){e.printStackTrace();return null;}

https://www.codenong.com/51861056/

https://www.lmlphp.com/user/151226/article/item/3360735/

https://cloud.tencent.com/developer/ask/sof/275206

http://www.17bigdata.com/study/programming/bcalg/bcalg-secp256k1.html

https://blog.csdn.net/weixin_29192211/article/details/114853972

// generate bogus keypair(!) with named-curve paramsKeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");ECGenParameterSpec gps = new ECGenParameterSpec ("secp256r1"); // NIST P-256kpg.initialize(gps);KeyPair apair = kpg.generateKeyPair();ECPublicKey apub = (ECPublicKey)apair.getPublic();ECParameterSpec aspec = apub.getParams();// could serialize aspec for later use (in compatible JRE)//// for test only reuse bogus pubkey, for real substitute valuesECPoint apoint = apub.getW();BigInteger x = apoint.getAffineX(), y = apoint.getAffineY();// construct point plus params to pubkeyECPoint bpoint = new ECPoint (x,y);ECPublicKeySpec bpubs = new ECPublicKeySpec (bpoint, aspec);KeyFactory kfa = KeyFactory.getInstance ("EC");ECPublicKey bpub = (ECPublicKey) kfa.generatePublic(bpubs);//// for test sign with original key, verify with reconstructed keySignature sig = Signature.getInstance ("SHA256withECDSA");byte [] data = "test".getBytes();sig.initSign(apair.getPrivate());sig.update (data);byte[] dsig = sig.sign();sig.initVerify(bpub);sig.update(data);System.out.println (sig.verify(dsig));

https://blog.csdn.net/weixin_39583751/article/details/116008623

ECDH secp256k1 集成相关推荐

  1. secp256k1的结构——ECDH密钥交换

    2021SC@SDUSC secp256k1的结构--ECDH密钥交换 ECDH地址 共享密钥ECDH 在加密通信过程中可以使用Diffie Hellman密钥交换来进行密钥分发,经过密钥交换之后相当 ...

  2. netty集成ssl完整参考指南(含完整源码)

    虽然我们在内部rpc通信中使用的是基于认证和报文头加密的方式实现安全性,但是有些时候仍然需要使用SSL加密,可能是因为对接的三方系统需要,也可能是由于open的考虑.中午特地测了下netty下集成ss ...

  3. java ecdh算法_椭圆曲线ECC ECDH原理 javacard实现

    椭圆曲线原理: 椭圆曲线的图像并不是椭圆形,椭圆曲线源自于求椭圆弧长的椭圆积分的反函数. 定义: 椭圆曲线可用下列方程来表示,其中a,b,c,d为系数. E: y2 =ax3 + bx2 +cx +d ...

  4. ECDH算法与mbedTLS

    ECDH密钥协商算法基于椭圆曲线密码系统(ECC),使用较短的密钥长度可提供与RSA或DH算法同等的安全等级,密钥长度位160 ~ 256比特的椭圆曲线算法与密钥长度位1024 ~ 3072比特的非E ...

  5. ECDH and ECDSA(ECC椭圆曲线算法3)

    这是ECC系列的第三篇. 专栏:https://blog.csdn.net/mrpre/category_6952288.html 在之前的文章中,我们看到了什么是椭圆曲线,并且我们为了做一些数学运算 ...

  6. 3椭圆曲线密码学:ECDH和ECDSA

    原文链接:Elliptic Curve Cryptography: ECDH and ECDSA 这篇文章是ECC系列的第三篇. 在之前的文章中,我们已经知道了椭圆曲线是什么,并且为了对椭圆曲线上的点 ...

  7. 极狐GitLab 和 ArgoCD 的集成实践

    极狐GitLab ArgoCD 和 GitOps 概述 ArgoCD 是一款开源且主要针对 Kubernetes 来做 GitOps 的持续交付工具.现在是 CNCF 的孵化项目.其整体架构图如下: ...

  8. 物联网安全系列 - 非对称加密算法 ECDH

    非对称加密算法 - ECDH 背景    之前的章节讲到了对称加密算法AES,发送方和接收方需要使用相同的密钥进行通讯,但是发送方怎么将密钥安全的发送给接收方?这是一个问题. 密钥分配问题    对称 ...

  9. ECDSA和ECDH原理

    2021SC@SDUSC ECDSA和ECDH原理 secp256k1的参数 ECDSA椭圆曲线数字签名算法 公钥生成 签名 签名验证 k 公钥恢复 ECDH椭圆曲线Diffie–Hellman秘钥交 ...

最新文章

  1. [武道资料]《菲律宾短棍-单棍》(Edgar Sulite Lameco Escrima Single Stick)
  2. laravel5.0升级到5.1
  3. Android开发各类常见错误解决方案
  4. 【转】Python 简介
  5. 在EXT中向弹窗传值或者对象
  6. iWiscloud智慧家居控制中心
  7. C++四种cast操作符
  8. undefined reference to `std::cout'等错误
  9. java输出的文本内容不对_java 字符串写入文件后再读出不一样? 有什么解决办法吗?...
  10. oracle DataGuard停机和启动顺序
  11. 5e的训练模式全是英文_四块GPU即可训练BigGAN:「官方版」PyTorch实现出炉
  12. 将lena图片进行简单处理
  13. pacpng文件格式说明
  14. 35岁的程序员:第12章,林菲菲
  15. QQ拼音截取屏幕局部放大问题解决
  16. “好好说话,别伤人。”
  17. C# 9 新功能“源代码生成器”,你用了吗?
  18. android googleplay 支付接入
  19. wap网站服务器要求,使您的WEB服务器支持WAP数据发送
  20. .scss和.css的区别,css - SCSS和Sass有什么区别?

热门文章

  1. win10家庭版如何开启本地组策略
  2. git各种异常问题整理
  3. 七参数对不同坐标系统的转换
  4. 计算机网络(3)--应用层协议--HTTP与HTTPS
  5. qq邮箱android版官方,QQ邮箱下载_腾讯QQ邮箱客户端下载【安卓版】-太平洋下载中心...
  6. Office 365 API平台概览
  7. Eagle设计师必备利器管理工具
  8. Web前端-aria2:AriaNg
  9. 树莓派3B+不能连接5G的Wi-Fi热点
  10. NYOJ - 597