当前位置: 首页 > news >正文

ECDH secp256k1 集成

在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

http://www.lryc.cn/news/18985.html

相关文章:

  • 工单模型的理解与应用
  • Python年利率计算器【N日年化收益率】
  • 3年测试拿8K,被校招来的实习生反超薪资,其实你在假装努力
  • 因子分析计算权重
  • 国家调控油价预测案例+源码
  • Gephi快速入门
  • GitHub
  • QT基础入门【调试篇】QT远程部署与调试嵌入式ARM开发板
  • 可观测性最佳实践|阿里云事件总线 EventBridge 最佳实践
  • 设计模式-行为型
  • Salesforce大揭秘!SaaS鼻祖不为人知的那些事!
  • Oracle——物化视图
  • ur3+robotiq 2f 140配置moveit
  • LDO 芯片烫手,问题出在哪里?
  • 零日漏洞发展格局及防御策略
  • RabbitMQ 可用磁盘空间报警
  • Web前端学习:二
  • 【第一章 计算机网络体系结构,标准化工作相关组织,性能指标,分层结构,OSI参考模型】
  • SpringIOC源码解析
  • 【Jupyter Notebook的简单入门使用】
  • @Component@Import@Bean加载顺序解析
  • 二极管温度补偿电路工作原理分析
  • 【C语言】多线程之条件竞争
  • UE NavigationSystem的相关实现
  • Java 继承
  • Python学习笔记8:异常
  • python保留小数函数总结
  • 狐狸优化算法(Matlab代码实现)
  • 浏览器自动化框架沦为攻击者的工具
  • SQL必备知识(自用)