Nodejs和C#使用ECDH算法交换秘钥

转载于:https://bkssl.com/document/nodejs-csharp-ecdh.html

nodejs的ECDH算法在进行computeSecret的时候不会自动进行HASH运算,但C#的ECDH算法必须指定HASH算法。

两边算法必须使用相同的椭圆曲线和Hash算法,例如下面用例都是用的SHA256。
双方交换公钥,计算得到共享秘钥:SharedSecret。

用例使用readline去交换公钥,实际一般运行在其他协议中,像SSH2等。
单纯秘钥交换并不安全,需要增加其他手段保证不被中间人监听、修改,例如ssh2使用serverhostkey对秘钥交换的数据进行签名。

nodejs测试代码

import readline from 'readline';

import crypto  from 'crypto';

function computeHash(data, alg){
    const hashAlg = crypto.createHash(alg || 'SHA256');
    hashAlg.update(data);
    return hashAlg.digest();
}

const reader = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const ecdh = crypto.createECDH('prime256v1');

const e = ecdh.generateKeys();

console.log("Local Public Key:" + e.toString('base64'));

reader.question('Please Input Remote PublicKey:', key => {
    console.log("Remote Public Key:" + key);
    let sharedSecret = ecdh.computeSecret(Buffer.from(key, 'base64'));

    //计算共享秘钥,需要先HASH运算,以兼容C#
    sharedSecret = computeHash(sharedSecret);
    console.log("Shared Secret: " + sharedSecret.toString('base64'));
})


// 控制台输出
// Local Public Key:BGLb5Sddo8N5sd1/+a7vhwb66QFMqAJtNFvEISecSzrBP3DjEr3R6vHeefI100yVDCnPQLNmgv56ampL+tNBc2c=
// Please Input Remote PublicKey:BASkBjbrTNysfXrcqyCOWuVgWVRF8a3VTufPLl99PFdY4+oj2d2kImu1OoZLMMoRKwul02gP27dWRoMCGicHjuQ=
// Remote Public Key:BASkBjbrTNysfXrcqyCOWuVgWVRF8a3VTufPLl99PFdY4+oj2d2kImu1OoZLMMoRKwul02gP27dWRoMCGicHjuQ=
// Shared Secret: EvhnVuNRa3dBqIFDyfSQfYmRF4/fPgJHDRZG5xB6HnA=

C#测试代码
 

var ecdh = ECDiffieHellmanHelper.New();
byte[] localPublicKey = ECDiffieHellmanHelper.CreateKeyExchange(ecdh);

Console.WriteLine("Local Public Key: {0}", localPublicKey.ToBase64String());


Console.WriteLine("Please Input Remote Public Key:");
string remotePublicKey = Console.ReadLine();

Console.WriteLine("Remote Public Key: {0}", remotePublicKey);

byte[] sharedSecret = ECDiffieHellmanHelper.DecryptKeyExchange(ecdh, remotePublicKey.AsBase64String());

Console.WriteLine("Shared Secret: {0}", sharedSecret.ToBase64String());

// 控制台输出
// Local Public Key: BASkBjbrTNysfXrcqyCOWuVgWVRF8a3VTufPLl99PFdY4+oj2d2kImu1OoZLMMoRKwul02gP27dWRoMCGicHjuQ=
// Please Input Remote Public Key:
// BGLb5Sddo8N5sd1/+a7vhwb66QFMqAJtNFvEISecSzrBP3DjEr3R6vHeefI100yVDCnPQLNmgv56ampL+tNBc2c=
// Remote Public Key: BGLb5Sddo8N5sd1/+a7vhwb66QFMqAJtNFvEISecSzrBP3DjEr3R6vHeefI100yVDCnPQLNmgv56ampL+tNBc2c=
// Shared Secret: EvhnVuNRa3dBqIFDyfSQfYmRF4/fPgJHDRZG5xB6HnA=

C#的ECDiffieHellmanHelper类实现

internal class ECPublicKey : ECDiffieHellmanPublicKey
{
    private readonly ECParameters parameters;

    public ECPublicKey(ECParameters parameters)
    {
        this.parameters = parameters;
    }

    public override ECParameters ExportParameters() => parameters;

    public override ECParameters ExportExplicitParameters() => parameters;

}

public class ECDiffieHellmanHelper
{
    //可以选择其他的曲线
    private static readonly ECCurve curve = ECCurve.NamedCurves.nistP256;


    public static ECDiffieHellman New(ECCurve curve) => ECDiffieHellman.Create(curve);
    public static ECDiffieHellman New() => ECDiffieHellman.Create(curve);
    public static byte[] CreateKeyExchange(ECDiffieHellman ecdh)
    {
        var args = ecdh.PublicKey.ExportParameters();

        int blockSize = args.Q.X.Length;
        byte[] buffer = new byte[blockSize * 2 + 1];
        buffer[0] = 0x4;
        args.Q.X.CopyTo(buffer, 1);
        args.Q.Y.CopyTo(buffer, blockSize + 1);

        return buffer;
    }

    public static byte[] DecryptKeyExchange(ECDiffieHellman ecdh, byte[] serverPublicKey)
    {
        ReadOnlySpan<byte> bytes = new(serverPublicKey);

        int length = (serverPublicKey.Length - 1) / 2;

        ECPublicKey thirdPublicKey = new (new ECParameters
        {
            Curve = curve,
            D = null,
            Q = new ECPoint
            {
                X = bytes.Slice(1, length).ToArray(),
                Y = bytes.Slice(1 + length, length).ToArray(),
            }
        });

        return ecdh.DeriveKeyFromHash(thirdPublicKey, HashAlgorithmName.SHA256);
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/893159.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Matlab|用于平抑可再生能源功率波动的储能电站建模及评价

目录 主要内容 模型研究 1.目标函数 2.约束条件 部分代码 结果一览 1.储能平抑风电功率 2.储能平抑风电和光伏功率 下载链接 主要内容 程序参考文献《用于平抑可再生能源功率波动的储能电站建模及评价》&#xff0c;针对风电和光伏分布式能源出力波动的问…

题目:连续子序列

解题思路&#xff1a; 首先&#xff0c;不能使用暴力枚举&#xff0c;时间为O(n2)&#xff0c;超时。以下为正确做法&#xff1a; 假设找到一段区间&#xff08;其和>m&#xff09;&#xff0c;如上图黄色部分&#xff0c;那么该区间加上i后面的元素形成的新区间和都>m&a…

opencv学习:CascadeClassifier和detectMultiScale算法进行人脸识别

CascadeClassifier CascadeClassifier 是 OpenCV 提供的一个用于对象检测的类&#xff0c;它基于Haar特征和AdaBoost算法。它能够识别图像中的特定对象&#xff0c;比如人脸、眼睛、微笑等。CascadeClassifier 需要一个预训练的XML分类器文件&#xff0c;该文件包含了用于检测…

CodeActAgent :Executable Code Actions Elicit Better LLM Agents解读

论文地址 https://arxiv.org/pdf/2402.01030.pdf 项目地址 https://github.com/svjack/CodeActAgent-Gradio/blob/main/README.md 代码智能体的优势 选择代码智能体有以下几个关键原因&#xff0c;它们相较于使用类似JSON的字典输出具有显著优势&#xff1a; 1. 代码的高…

Spring Boot 应用开发:入门与实战

Spring Boot 应用开发&#xff1a;入门与实战 引言 Spring Boot 是 Spring 框架的一个子项目&#xff0c;旨在简化 Spring 应用的配置和开发。它通过自动配置和嵌入式服务器&#xff0c;极大地简化了 Java 企业级应用的开发。本文将详细介绍 Spring Boot 的核心概念&#xff…

【SPIE独立出版】第四届计算机、信息工程与电子材料国际学术会议 (CTIEEM 2024,2024年11月15-17日 )

第四届计算机、信息工程与电子材料国际学术会议 (CTIEEM 2024) The 4th International Conference on Computer Technology, Information Engineering and Electron Materials 会议官网&#xff1a;www.ctieem.org The 4th International Conference on Computer Technology,…

【bug】paddleocr draw_ocr_box_txt ValueError: incorrect coordinate type

【bug】paddleocr draw_ocr_box_txt ValueError: incorrect coordinate type 环境 python 3.10.15pillow 10.4.0 paddleocr 2.8.1错误详情 错误文本 Traceback (most recent call last):....draw_left.polygon(box, fillcolor)ValueError: inco…

浏览器内置文字转语音,播报功能Web Speech API - SpeechSynthesisUtterance

SpeechSynthesisUtterance: 让网页说话的艺术 在现代Web开发中&#xff0c;让网页具有语音功能可以极大提升用户体验&#xff0c;特别是对于视障用户或需要多任务处理的场景。SpeechSynthesisUtterance 是 Web Speech API 中的一个接口&#xff0c;它允许开发者创建一个语音合…

穷举vs暴搜vs深搜vs回溯vs剪枝(一)

文章目录 全排列子集找出所有子集的异或总和再求和全排列 II电话号码的字母组合 全排列 题目&#xff1a;全排列 思路 通过深度优先搜索的方式&#xff0c;不断枚举每个数在当前位置的可能性&#xff0c;然后回溯到上一个状态&#xff0c;直到枚举完所有可能性得到正确的结果 r…

SDK5(note上)

以下代码实现菜单窗口和快捷键的ctrlo打开的操作 #include <windows.h> #include<tchar.h> #include <stdio.h> #include <strsafe.h> #include <string> #define IDM_OPEN 102 /*鼠标消息 * 键盘消息 * Onkeydown * Onkeyup * //键盘扫描码 * …

力扣hot100--二叉树

目录 二叉树 1. 94. 二叉树的中序遍历 2. 98. 验证二叉搜索树 3. 101. 对称二叉树 4.102. 二叉树的层序遍历 5. 104. 二叉树的最大深度 6. 105. 从前序与中序遍历序列构造二叉树 7. 114. 二叉树展开为链表 8. 226. 翻转二叉树 9. 236. 二叉树的最近公共祖先 二叉树 …

操作符详解(C 语言)

目录 一、操作符的分类二、算数操作符1. 除法操作符2. 取余操作符 三、位移操作符1. 进制2. 原码、反码和补码3. 左移操作符&#xff08;<<&#xff09;和右移操作符&#xff08;>>&#xff09; 四、位操作符1. 按位与 &2. 按位或 |3. 按位异或 ^4. 按位取反 ~…

大衍数列——考研408考试科目之数据算法——未来之窗学习通

一、大衍数列 中国古代文献中&#xff0c;曾记载过“大衍数列”, 主要用于解释中国传统文化中的太极衍生原理。 它的前几项是&#xff1a;0、2、4、8、12、18、24、32、40、50 … 其规律是&#xff1a;对偶数项&#xff0c;是序号平方再除2&#xff0c;奇数项&#xff0c;是…

有源滤波器(三)

这个连接方法很可以&#xff0c;正好解决了最近没有转接器的问题&#xff1a;

javaweb-xml映射文件编写sql语句

可以使用注解的方式&#xff0c;也可以使用xml映射的方式&#xff0c;一般简单sql语句使用注解&#xff0c;复杂的使用xml映射。

【PhpSpreadsheet】ThinkPHP5+PhpSpreadsheet实现批量导出数据

目录 前言 一、安装 二、API使用 三、完整实例 四、效果图 前言 为什么使用PhpSpreadsheet&#xff1f; 由于PHPExcel不再维护&#xff0c;所以建议使用PhpSpreadsheet来导出exlcel&#xff0c;但是PhpSpreadsheet由于是个新的类库&#xff0c;所以只支持PHP7.1及以上的版…

【文心智能体 | AI大师工坊】如何使用智能体插件,完成一款购物类智能体的开发,来体验一下我的智能体『科技君Tom』

目录 1.1、智能体运行效果1.2、创作灵感来源智能体平台拥有个人化且人性化的大致框架&#xff0c;可以让小白也能搭建出一个智能体其次是拥有丰富的插件&#xff0c;可以更加快速的得到自己想要的效果~ 1.3、如何制作智能体常见问题与解决方案关于人设与回复逻辑插件使用模型的…

【黑马redis高级篇】持久化

//来源[01,05]分布式缓存 除了黑马&#xff0c;还参考了别的。 目录 1.单点redis问题及解决方案2.为什么需要持久化&#xff1f;3.Redis持久化有哪些方式呢&#xff1f;为什么我们需要重点学RDB和AOF&#xff1f;4.RDB4.1 定义4.2 触发方式4.2.1手动触发save4.2.2被动触发bgsa…

文件IO(Linux文件IO,目录操作函数)

前言 本文介绍Linux系统下自带的文件IO的函数。 Linux文件IO相关函数 open函数 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode)…

2024ideaUI切换和svn与git的切换

2024的UI实在很不舒服&#xff0c;隐藏了很多按键&#xff1b; 第一步&#xff1a; 视图 -》 外观 -》 工具栏选出来&#xff1b; 结果出来&#xff1a; 运行的按键和设置的按钮 第二步 点击设置的按钮&#xff0c;选择最后一个&#xff0c;重启就行 结果 舒服&#xff01; s…