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
相关文章:
ECDH secp256k1 集成
在Android 原生api是不支持secp256k1算法的,所以要先集成以下库:implementation com.madgag.spongycastle:core:1.58.0.0compile com.madgag.spongycastle:prov:1.54.0.0compile com.madgag.spongycastle:pkix:1.54.0.0compile com.madgag.spongycastle:…...

工单模型的理解与应用
工单(任务单)模型的定义 工单模型是一种分派任务的方法,可以用来跟踪、评估和报告任务的完成情况。它通常用于针对特定目标的重复性任务或项目,以确保任务能够按时完成并符合期望的标准。 工单模型的基本流程为:提…...

Python年利率计算器【N日年化收益率】
现在有闲钱的人,按照聪明等级从低到高排序应该是钱买股票,一年利率约为-20%钱放银行活期,年利率约为0.3%钱放银行定期,一年利率约为1.5%钱放余额宝(支付宝)或零钱通(微信)࿰…...

3年测试拿8K,被校招来的实习生反超薪资,其实你在假装努力
最近朋友给我分享了一个他公司发生的事 大概的内容呢:公司一位工作3年的测试工资还没有新人高,对此怨气不小,她来公司辛辛苦苦三年,三年内迟到次数都不超过5次,每天都是按时上下班,工作也按量完成…...

因子分析计算权重
因子分析两类权重计算方法总结 案例背景 疫情爆发以来,越来越多的人为了避免线下与人接触,选择了线上购买生活必需品。网购虽然方便快捷,但是随着订单压力的增加,物流问题也随之出现,近期有很多卖家收到物流投诉的问题…...

国家调控油价预测案例+源码
项目git地址:https://github.com/Boris-2021/Oil-price-control-forecast 使用已知的历史数据:日期、汇率、布伦特、WTI、阿曼原油价格,预测下一个调价周期中的汽油、柴油零售限价的调价价格。 一. 需求 1.1 需求说明 使用已知的历史数据&a…...

Gephi快速入门
Gephi快速入门1. 导入文件(Import file)2. 布局(Layout)3. 排序(Ranking)4. 指标(Metrics)5. 标签(Label)6. 社区发现(Community detection&#…...

GitHub
什么是 Github?GitHub是一个面向开源及私有软件项目的托管平台,因为只支持Git作为唯一的版本库格式进行托管,故名GitHub。一、常用词Watch:观察。如果watch了一个项目,之后这个项目有更新,你会在第一时间收到该项目更…...
QT基础入门【调试篇】QT远程部署与调试嵌入式ARM开发板
目录 一、环境配置 1、根据开发板完成交叉编译链以及GDB的配置(因开发板而异)...

可观测性最佳实践|阿里云事件总线 EventBridge 最佳实践
本文介绍如何把阿里云事件总线 EventBridge 的内容接入观测云平台,通过观测云强大的统一汇聚能力轻松获取阿里云事件,实时追踪最新的数据信息。 背景信息 事件总线 EventBridge 是阿里云提供的一款无服务器事件总线服务,支持阿里云服务、自定…...
设计模式-行为型
设计模式-行为型 行为型设计模式主要用于软件运行时复杂的流程控制。包含:模板方法模式、策略模式、命令模式、职责链模式、状态模式、观察者模式、中介者模式、迭代器模式、访问者模式、备忘录模式和解释器模式 模板方法模式 在软件设计时,很多时候系…...

Salesforce大揭秘!SaaS鼻祖不为人知的那些事!
Salesforce的世界无疑是广阔的。自从创始人Marc Benioff于1999年创立公司以来,Salesforce一直在打破CRM领域的界限,改变销售、营销和技术的格局。 作为全球领先的B2B科技公司之一,Salesforce和硅谷里的其他企业一样,缔造着一个关…...

Oracle——物化视图
文章目录含义物化视图的语法物化视图的创建1、自动刷新的物化事务 ON COMMIT2、非自动刷新的物化视图 ON demand关于手动刷新物化视图的删除资料参考含义 什么是物化视图? 物化视图,通俗点说就是物理化的视图。 什么叫物理化? 将视图以表结构…...

ur3+robotiq 2f 140配置moveit
ur3robotiq 2f 140配置moveit 参考链接1 参考链接2 官方配置movit教程 搭建环境: ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 reasense: D435i 通过下面几篇博客配置好了ur3、力传感器、robotiq夹爪…...

LDO 芯片烫手,问题出在哪里?
设计失误的一个电路,该电路是数字电路的电源,为图方便对12V直接通过线性电源芯片降压到5V: 图1:线性电源降压12V转5V 几块电路板打样好后,测试均发现AMS1117-5.0芯片烫手,负载电流100mA多,也满…...

零日漏洞发展格局及防御策略
在过去的一年半中, 在野利用的零日漏洞数量持续飙升 ,这些软件制造商尚不知晓的漏洞正在被国家行为体黑客组织和勒索软件团伙滥用。 今年上半年,Google Project Zero统计了近20个零日漏洞,其中 大部分针对微软、苹果和谷歌构建的…...
RabbitMQ 可用磁盘空间报警
概要当磁盘可用空间低于设定的值(默认50M),将触发警报,并阻塞所有生产者。这目标是为了避免填满整个磁盘,这将导致所有节点上的写入操作失败,并可能导致RabbitMQ停止服务。如何工作为了减少磁盘被填满的风险…...

Web前端学习:二
二一:文字font-size样式 font-size:**px 控制文字大小,可精准控制大小 默认样式medium,中等的 large,大一号 x-large,再大一号 xx-large,再大一号 small,小一号 <!DOCTYPE html…...
【第一章 计算机网络体系结构,标准化工作相关组织,性能指标,分层结构,OSI参考模型】
第一章 计算机网络体系结构,标准化工作相关组织,性能指标,分层结构,OSI参考模型 1.计算机网络: (1)概念: ①计算机网络是将一个分散的、具有独立功能的计算机系统,通过通…...

SpringIOC源码解析
Spring深度学习(一)——IOC的设计理念Spring的核心思想——IOCSpring流程图DEMO编写Spring IoC容器的加载过程实例化化容器:AnnotationConfigApplicationContext实例化建BeanDefinition读取器: AnnotatedBeanDefinitionReaderBean…...

【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...