使用之前在 ECIES 中生成的私钥

2023-12-02

我想使用 ECIES 加密/解密数据,我为此使用 cryptopp 。

AutoSeededRandomPool prng;

//get private key generated
ECIES<ECP>::Decryptor d0(prng, ASN1::secp256r1());
PrintPrivateKey(d0.GetKey());

//get public key 
ECIES<ECP>::Encryptor e0(d0);
PrintPublicKey(e0.GetKey());

//encrypt the message
string em0; // encrypted message
StringSource ss1 (message, true, new PK_EncryptorFilter(prng, e0, new StringSink(em0) ) );

//decrypt the message   
string dm0; // decrypted message
StringSource ss2 (em0, true, new PK_DecryptorFilter(prng, d1, new StringSink(dm0) ) );

其他一切都很好,但我想使用已经生成的“私钥”而不是随机生成的“私钥”来执行上述相同的操作,与上面的情况不同。我怎样才能做到这一点?

我尝试过以下代码,但它只是崩溃了

AutoSeededRandomPool prng;

std::string  privatekeyString="02C200102C180F9E6A4E7A2F58B5BE86BC179478";

CryptoPP::HexDecoder decoder;
decoder.Put((byte*)privatekeyString.data(), privatekeyString.size());
decoder.MessageEnd();

ECIES<ECP> ::Decryptor d0;
d0.AccessKey().AccessGroupParameters().Initialize(ASN1::secp128r1());

崩溃点

//load private key  
d0.AccessKey().Load(decoder);
PrintPrivateKey(d0.GetKey());

//get public key    
ECIES<ECP>::Encryptor e0(d0);
PrintPublicKey(e0.GetKey());

string em0; // encrypted message
StringSource ss1(message, true, new PK_EncryptorFilter(prng, e0, new StringSink(em0) ) );
cout<<"encrypted msg: "<<em0<<"  and its length: "<<em0.length()<<endl;

string dm0; // decrypted message
StringSource ss2 (em0, true, new PK_DecryptorFilter(prng, d0, new StringSink(dm0) ) );
cout <<"decrypted msg: "<< dm0<<"  and its length: "<<dm0.length() <<   endl;

Edit 2

为了回应 @jww 回答,我设法使用私钥将消息解码为:

  try
  {
    AutoSeededRandomPool prng;

    std::string exponent="AsIAECwYD55qTnovWLW+hrwXlHg=";
    StringSource ss(exponent, true /*pumpAll*/, new CryptoPP::HexDecoder);


    Integer x;
    x.Decode(ss, ss.MaxRetrievable(), Integer::UNSIGNED);
    // cout << "Exponent: " << std::hex << x << endl;

    ECIES<ECP>::Decryptor decryptor;
    decryptor.AccessKey().Initialize(ASN1::secp128r1(), x);

    bool valid = decryptor.AccessKey().Validate(prng, 3);
    if(!valid)
    {
        cout<<"Exponent is not valid for P-128"<<endl;
        return;
    }
      //  throw  Exception(CryptoPP::Exception::OTHER_ERROR, "Exponent is not valid for P-256");

    // Or: decryptor.AccessKey().ThrowIfInvalid(prng, 3);

    cout << "Exponent is valid for P-128" << endl;

    PrintPrivateKey(decryptor.GetKey());


    //get public key
    ECIES<ECP>::Encryptor encryptor(decryptor);
    PrintPublicKey(encryptor.GetKey());



    string em0; // encrypted message
    StringSource ss1(message, true, new PK_EncryptorFilter(prng, encryptor, new StringSink(em0) ) );
    cout<<"encrypted msg: "<<em0<<"  and its length: "<<em0.length()<<endl;

    string dm0; // decrypted message
    StringSource ss2 (em0, true, new PK_DecryptorFilter(prng, decryptor, new StringSink(dm0) ) );
    cout <<"decrypted msg: "<< dm0<<"  and its length: "<<dm0.length() << endl;

}
catch(const CryptoPP::Exception& ex)
{
    std::cerr << ex.what() << endl;
}

但是当我尝试使用公钥加密消息时出现错误

CryptoPP::CryptoMaterial::InvalidMaterial:CryptoMaterial:此对象包含无效值

这是我的代码:

std::string     public_point="AsIAEFjzIcX+Kvhe8AmLoGUc8aYAEAwf5ecREGZ2u4RLxQuav/A=";
StringSource ss(public_point, true, new CryptoPP::HexDecoder);

ECIES<ECP>::Encryptor encryptor;
    encryptor.AccessKey().AccessGroupParameters().Initialize(ASN1::secp128r1());

ECP::Point point;
encryptor.GetKey().GetGroupParameters().GetCurve().DecodePoint(point, ss, ss.MaxRetrievable());
cout << "X: " << std::hex << point.x << endl;
cout << "Y: " << std::hex << point.y << endl;

encryptor.AccessKey().SetPublicElement(point);


encryptor.AccessKey().ThrowIfInvalid(prng, 3);

PrintPublicKey(encryptor.GetKey());



string em0; // encrypted message
StringSource ss1(message, true, new PK_EncryptorFilter(prng, encryptor, new StringSink(em0) ) );
cout<<"encrypted msg: "<<em0<<"  and its length: "<<em0.length()<<endl;

我遇到的问题是您似乎不知道自己拥有什么,并且您使用的某些参数与其他参数一起使用时是错误的。所以这几乎是在黑暗中刺伤。


首先,您应该将磁盘操作包装在try/catch。 I/O 总是会导致问题,因此一定要捕获与 I/O 相关的异常iostream东西。您还应该捕获与密钥加载相关的 Crypto++ 异常。这将在没有信息的情况下处理“崩溃”。

所以你的代码可能看起来像这样:

try
{
    // Read key from disk, load it into Crypto++ object
}
catch(const Exception& ex)
{
    cerr << "Caught Crypto++ exception " << ex.what() << endl;
}
catch(const std::runtime_error& ex)
{
    cerr << "Caught C++ runtime error " << ex.what() << endl;
}

其次,这看起来像一个私有指数,而不是私钥:

std::string  privatekeyString="02C200102C180F9E6A4E7A2F58B5BE86BC179478";

而且它太大了,无法进入P-128。也许你应该这样做:

try
{
    AutoSeededRandomPool prng;

    std::string exponent="02C200102C180F9E6A4E7A2F58B5BE86BC179478";
    StringSource ss(exponent, true /*pumpAll*/, new HexDecoder);

    Integer x;
    x.Decode(ss, ss.MaxRetrievable(), Integer::UNSIGNED);        
    // cout << "Exponent: " << std::hex << x << endl;

    ECIES<ECP>::Decryptor decryptor;
    decryptor.AccessKey().Initialize(ASN1::secp256r1(), x);

    bool valid = decryptor.AccessKey().Validate(prng, 3);
    if(!valid)
        throw  Exception(Exception::OTHER_ERROR, "Exponent is not valid for P-256");

    // Or: decryptor.AccessKey().ThrowIfInvalid(prng, 3);

    cout << "Exponent is valid for P-256" << endl;        
}
catch(const Exception& ex)
{
    cerr << ex.what() << endl;
}

或者,您可以:

ECIES<ECP>::Decryptor decryptor;
decryptor.AccessKey().AccessGroupParameters().Initialize(ASN1::secp256r1());
decryptor.AccessKey().SetPrivateExponent(x);

如果将以下内容添加到上面的程序中:

// Encode key, use OID versus domain paramters
string encoded;
HexEncoder encoder(new StringSink(encoded));

decryptor.AccessKey().AccessGroupParameters().SetEncodeAsOID(true);
decryptor.GetKey().Save(encoder);

cout << "Private key: " << encoded << endl;

您将获得以下私钥:

$ ./ecies-test.exe
Exponent: 2c200102c180f9e6a4e7a2f58b5be86bc179478h
Private key: 3041020100301306072A8648CE3D020106082A8648CE3D030107042730250201010
42000000000000000000000000002C200102C180F9E6A4E7A2F58B5BE86BC179478

正如你所看到的,关键是is not "02C200102C180F9E6A4E7A2F58B5BE86BC179478".

12 个前导 0 对我来说看起来很可疑。尽管指数有效,但您应该验证指数和字段。我能找到的最接近的拟合是曲线secp160r2(当然,像这样的曲线secp192k1 and secp224k1也工作)。

上面的私钥是十六进制编码的ecies.priv.der如下所示。


第三,由于领先,这可能是压缩形式的公共点02.

std::string  privatekeyString="02C200102C180F9E6A4E7A2F58B5BE86BC179478";

如果是这种情况,那么你应该能够做到这一点,但我无法让它解码该点(请参阅最小化密钥大小以实现持久性在维基百科上)。x and y运算后均为0;也许问题出在该领域:

std::string public_point="02C200102C180F9E6A4E7A2F58B5BE86BC179478";
StringSource ss(public_point, true, new HexDecoder);

ECIES<ECP>::Encryptor encryptor;
encryptor.AccessKey().AccessGroupParameters().Initialize(ASN1::secp128r1());

ECP::Point point;
encryptor.GetKey().GetGroupParameters().GetCurve().DecodePoint(point, ss, ss.MaxRetrievable());
cout << "X: " << std::hex << point.x << endl;
cout << "Y: " << std::hex << point.y << endl;

encryptor.AccessKey().SetPublicElement(point);
encryptor.AccessKey().ThrowIfInvalid(prng, 3);

第四,您可能应该保存整个密钥,而不仅仅是指数。这是一个适合您的程序,向您展示如何保存和加载密钥。它还向您展示了如何单行执行加密和解密。

/////////////////////////////////////////////////
// Part one - generate keys

ECIES<ECP>::Decryptor decryptor(prng, ASN1::secp256r1());
ECIES<ECP>::Encryptor encryptor(decryptor);

/////////////////////////////////////////////////
// Part two - save keys

FileSink fs1("ecies.priv.der", true /*binary*/);
decryptor.AccessKey().AccessGroupParameters().SetEncodeAsOID(true);
decryptor.GetKey().Save(fs1);

FileSink fs2("ecies.pub.der", true /*binary*/);
encryptor.AccessKey().AccessGroupParameters().SetEncodeAsOID(true);
encryptor.GetKey().Save(fs2);

/////////////////////////////////////////////////
// Part three - encrypt/decrypt

string message, encrypted, recovered;

if(argc >= 2 && argv[1] != NULL)
    message = argv[1];
else
    message = "Attack at dawn!";

StringSource ss1 (message,   true /*pumpAll*/, new PK_EncryptorFilter(prng, encryptor, new StringSink(encrypted)));
StringSource ss2 (encrypted, true /*pumpAll*/, new FileSink("ecies.encrypted.bin", true /*binary*/));
StringSource ss3 (encrypted, true /*pumpAll*/, new PK_DecryptorFilter(prng, decryptor, new StringSink(recovered)));

cout << recovered << endl;

这是上面测试程序中私钥的样子。请注意,它已将字段编码到结构中,因此您不必猜测它(P-256 versus P-128 versus P-521).

$ dumpasn1 ecies.priv.der 
  0  65: SEQUENCE {
  2   1:   INTEGER 0
  5  19:   SEQUENCE {
  7   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 16   8:     OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
       :     }
 26  39:   OCTET STRING, encapsulates {
 28  37:     SEQUENCE {
 30   1:       INTEGER 1
 33  32:       OCTET STRING
       :         00 00 00 00 00 00 00 00 00 00 00 00 02 C2 00 10
       :         2C 18 0F 9E 6A 4E 7A 2F 58 B5 BE 86 BC 17 94 78
       :       }
       :     }
       :   }

和公钥:

$ dumpasn1 ecies.pub.der 
  0  89: SEQUENCE {
  2  19:   SEQUENCE {
  4   7:     OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
 13   8:     OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
       :     }
 23  66:   BIT STRING
       :     04 08 9B D2 1C 3A DC 08 8B 1F F1 D0 F4 97 A0 87
       :     FE 4F 78 EA E2 B8 30 B8 E7 06 37 68 27 4C 71 CD
       :     63 C3 E2 90 66 64 2B 1C F6 79 00 36 AF 72 4C 61
       :     69 FA E9 06 00 9A 15 32 0B 85 B5 88 B2 C5 88 46
       :     5E
       :   }

Crypto++ 在 ECIES 上有一个 wiki 页面。看椭圆曲线综合加密方案。他们还有 Bouncy Castle 互操作解决方法。


您还可以对密钥进行 PEM 编码,但您需要一个补丁才能完成此操作,因为它不是库的一部分。对于补丁,请参见PEM Pack在 Crypto++ wiki 上。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用之前在 ECIES 中生成的私钥 的相关文章

  • boost::asio + std::future - 关闭套接字后访问冲突

    我正在编写一个简单的 TCP 客户端来发送和接收单行文本 异步操作由 std future 处理 以便于超时阻塞查询 不幸的是 我的测试应用程序在破坏服务器对象时因访问冲突而崩溃 这是我的代码 TCP客户端 hpp ifndef TCPCL
  • 为什么相同的代码在同一台计算机上的执行时间可能不同?

    我是 C 编程新手 我编写了代码并希望获得它的运行时 这就是我所做的 每次运行代码时 我都会得到不同的运行时值 这样对吗 或者我的代码有问题吗 int main int argc char argv time t start end sta
  • 使用 Unity 在构造函数中使用属性依赖注入

    好的 我在基类中定义了一个依赖属性 我尝试在其派生类的构造函数内部使用它 但这不起作用 该属性显示为 null Unity 在使用 container Resolve 解析实例后解析依赖属性 我的另一种选择是将 IUnityContaine
  • 使用Physics.Raycast 和Physics2D.Raycast 检测对象上的点击

    我的场景中有一个空的游戏对象 带有 2D 组件盒碰撞器 我将脚本附加到该游戏对象 void OnMouseDown Debug Log clic 但是当我点击我的游戏对象时 没有任何效果 你有什么想法 如何检测我的盒子碰撞器上的点击 使用光
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 如何在 C# 中从 UNIX 纪元时间转换并考虑夏令时?

    我有一个从 unix 纪元时间转换为 NET DateTime 值的函数 public static DateTime FromUnixEpochTime double unixTime DateTime d new DateTime 19
  • 推导指南中的引用和值之间的差异

    考虑类型A template
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 如何将 #ifdef DEBUG 添加到 Xcode?

    我的项目中有一些代码永远不应该在发布版本中使用 但在测试时很有用 我想做这样的事情 ifdef DEBUG Run my debugging only code endif 在 Xcode 4 中哪里添加 DEBUG 设置 我尝试将其放入
  • 在 Unity 进程和另一个 C# 进程之间进行本地 IPC 的最快方法 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我希望每秒大约 30 次从 C 应用程序向我的 Unity 应用程序传送大量数据 由于 Unity 不支持映射内存和管道 我考虑了 t
  • 如何在 C# 中定义文本框数组?

    您好 当我在 Windows 申请表上创建文本框时 我无法将其命名为 box 0 box 1 等 我这样做的目的是因为我想循环使用它们 其实我发现TextBox array firstTextBox secondTextBox 也有效
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 如何在 Linq 中获得左外连接?

    我的数据库中有两个表 如下所示 顾客 C ID city 1 Dhaka 2 New york 3 London 个人信息 P ID C ID Field value 1 1 First Name Nasir 2 1 Last Name U
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • 在客户端系统中安装后桌面应用程序无法打开

    我目前正在使用 Visual Studio 2017 和 4 6 1 net 框架 我为桌面应用程序创建了安装文件 安装程序在我的系统中完美安装并运行 问题是安装程序在其他计算机上成功安装 但应用程序无法打开 edit 在客户端系统中下载了

随机推荐

  • R:使用 IFELSE 替代方案创建数据框的最快方法

    我有一个类似的问题 这个问题在这个线程上 使用 R 将矩阵中 但就我而言 假设我有更大的数据集和可变阈值 我需要使用同一数据帧第一列上的值创建一个数据帧 其中包含从条件中检索的每个值 每条线的这些值都不同 这是数据框的示例 SNP A1 A
  • C# 将密钥发送到其他应用程序到特定文本字段

    我需要使用 C 将密钥发送到其他应用程序到其他应用程序中的特定文本字段 那可能吗 如果是 有人可以给我示例代码吗 SendKeys只将击键组合发送到活动窗口 因此 如果您的 C 应用程序调用SendKeys在正确的时间运行 当用户将其他应用
  • Javascript 中的 String 是原始类型还是对象?

    Javascript 中的 String 是原始类型还是对象 消息人士称 Undefined Null Boolean Number 和 String 都是 Javascript 中的原始类型 但它说 String 也是一个对象 我很困惑
  • Java:扩展类加载器从 Java 13 中的哪里获取类?

    我能找到的所有文档都提到了 jre lib ext 文件夹 但我的 JRE 13 安装中不存在该文件夹 我猜想在 Java 8 我可以在 jre lib ext 中看到 jar 和 Java 13 之间的某个地方 它们移动了 但我无法确定它
  • 批量替换文本文件中的文本(Linux/OSX 命令行)

    我有数百个文件 需要更改其部分文本 例如 我想将 http 的每个实例替换为 rtmp 这些文件具有 txt 扩展名 并且分布在多个文件夹和子文件夹中 我基本上正在寻找一种遍历每个文件夹 子文件夹和每个文件的方法 脚本 如果它在该文件中发现
  • 终止空闲的 mysql 连接

    我看到很多连接处于打开状态并且长时间处于空闲状态 例如 5 分钟 是否有任何解决方案可以在不重新启动 mysql 服务的情况下从服务器终止 关闭它 我正在维护旧版 PHP 系统 无法关闭为执行查询而建立的连接 我是否应该将 my cnf 文
  • UIImageView 动画RepeatCount 奇怪的行为

    所以我有这段代码可以无限次地对一组图像进行动画处理 但是一旦我尝试限制它的动画处理次数 它就不起作用了 甚至没有显示图像 有效的代码 animatedMap animationImages NSArray arrayWithObjects
  • 如何为图标内的文本着色

    我想问是否有一种方法可以为我将鼠标悬停在下面链接的图标上添加颜色 例如 如果我将鼠标悬停在文本上 如何才能仅将文本的颜色设置为 红色 我认为你必须结合照片编辑器来完成它 但我真的不知道如何做 感谢帮助 这是我尝试过的代码 section a
  • Mysql - 更新表中列具有空值的第一行

    我有一个包含 API 密钥列表的数据库 我需要将电子邮件和姓名与这些关联起来 我希望我的查询更新第一行中电子邮件为空的姓名和电子邮件 id key name email 1 3046GUGYi7ab NULL NULL 2 TXQzL33H
  • 在没有工具栏的新进程中启动 Internet Explorer 7

    我需要在 IE 中运行一个 Web 应用程序 因此它至少看起来与独立应用程序类似 我还需要能够在单独的会话中同时运行此 Web 应用程序的多个实例 为了实现这种外观 我希望始终在新进程中启动 Internet Explorer 7 而无需从
  • 使用 GCC 扩展 ASM 将内联 Intel ASM 转换为 AT&T ASM

    我花了 2 天的时间来研究 AT T 内联汇编 但是在转换这个汇编时遇到了一些问题 static char vendername 50 0 asm mov eax 0 cpuid mov dword ptr vendername ebx m
  • 如何使用 List 填充 DropDownList

    我有一个下拉列表 我需要用收集到的项目填充它List
  • 使用 SBT,如何指定除当前目录之外的备用项目根目录来运行主类?

    通常 SBT 会在以下位置查找构建文件 build sbt and project Build scala 是否可以指定备用项目根目录 以便我可以构建不在当前工作目录中的项目 我本质上正在寻找相当于mvn f path to pom xml
  • 无法修改 c:\windows 目录中的 .ini 文件

    我正在编写一个 C Windows 应用程序来更新旧应用程序的 ini 文件 我没有旧应用程序的源代码 因此无法对其进行修改 旧版应用程序将设置存储在 C Windows 的 INI 文件中 该位置无法更改 为了修改 INI 设置 我一直在
  • 减少mongodb中的值

    我正在创建一个购物应用程序 每个用户都有钱包 结构如下 userName Gandalf the Grey wallet 100 orderHistory 假设该用户购买了价值 50 件的商品 有没有更好的方法而不是用 findOne 获取
  • g++ 9 概念支持包括 ubuntu 18.04 上的

    我正在使用 g std c 2a fconcepts 来处理 g 的概念 但出现 include Concepts 标头错误 没有这样的文件或目录 有人可以帮我调试这个吗 这是我从 cppreference 复制的代码 include
  • 如何在嵌入式 React 应用程序的页面之间路由?

    背景 我正在尝试在嵌入式 Shopify 应用程序中创建一些链接 我明白我不能使用简单的 a 标签 因为 Shopify 嵌入式应用程序呈现为 iframe 我在本教程中取得了一些进展 但我陷入了困境 https theunlikelyde
  • Rails:在早期开发阶段改变迁移

    在 Rails 应用程序开发的早期阶段 我更喜欢直接修改迁移文件以将新列 字段 添加到我的表 模型 中 而不是堆积迁移来更改字段和 或进行较小的更改 这在 Rails 中可能吗 我运行以下命令来解决这个问题 将其保存在脚本中 然后就可以开始
  • Java时区:为什么需要Offset

    我的要求是这样的 我在数据库和时区中保存以毫秒为单位的时间 例如 以毫秒为单位的时间是1223123123232长时区是Asia Calcutta 我必须将其转换为Africa Asmara时区 long l 1223123123232l
  • 使用之前在 ECIES 中生成的私钥

    我想使用 ECIES 加密 解密数据 我为此使用 cryptopp AutoSeededRandomPool prng get private key generated ECIES