【问题标题】:Scalar multiplication on secp521r1 using Crypto++使用 Crypto++ 对 secp521r1 进行标量乘法
【发布时间】:2019-05-23 11:01:00
【问题描述】:

我正在为 C++ 中椭圆曲线中的标量乘法编写以下代码。当我不初始化点的值时,代码运行。但是当我这样做时,它给了我 nullptr 错误。

我试过下面的代码:

ECP r1;
ECPPoint basepoint = ECPPoint(2,3);
ECPPoint point;
ECPPoint s1= ecp.ScalarMultiply(basepoint, x1);

错误:

CryptoPP::ECP::GetField(...) returned nullptr.

【问题讨论】:

  • ECPPointScalarMultiply 是如何定义的?
  • @Riddick 找到:ECPPointECP::ScalarMultiply()
  • 代码在我没有初始化点的值时运行。 对我来说,它看起来是否ECPPoint point; 与其余行完全无关。如果初始化与无初始化有所不同,我会认为这是Undefined Behavior 的标志。在这种情况下,错误可能出现在任何未公开的代码中。
  • ecp 的初始化是否正确? x1 怎么样?除非您可以显示minimal reproducible example,否则很难得出任何结论
  • 我认为我们的 wiki 上没有曲线操作的好例子。我认为这是我们的一个文档错误。我们在Elliptic Curve Cryptography | Curve Operations 处向 wiki 添加了一个示例。

标签: c++ cryptography crypto++ elliptic-curve


【解决方案1】:

错误:CryptoPP::ECP::GetField(...) 返回 nullptr。

对于 Crypto++,您需要加载曲线。根据您发布的代码,它看起来并没有完成。加载曲线会加载曲线的域参数。在素数域上的曲线的情况下,域参数是 {a,b,p,G,n,h},其中 ab 是系数, p 模数,G 是基点,序为 Nn 是序数,n h 是辅因子。你可以在eccrypto.cpp看到他们。

对于secp521r1,最简单的方法可能是按照以下方式。 secp256r1 用于使输出更小,但您应该改用secp521r1

#include "integer.h"
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"

#include <iostream>
#include <iomanip>

int main(int argc, char* argv[])
{
    using namespace CryptoPP;
    typedef DL_GroupParameters_EC<ECP> GroupParameters;
    typedef DL_GroupParameters_EC<ECP>::Element Element;

    AutoSeededRandomPool prng;    
    GroupParameters group;
    group.Initialize(ASN1::secp256r1());

    // private key
    Integer x(prng, Integer::One(), group.GetMaxExponent());

    std::cout << "Private exponent:" << std::endl;
    std::cout << "  " << std::hex << x << std::endl;

    // public key
    Element y = group.ExponentiateBase(x);

    std::cout << "Public element:" << std::endl;
    std::cout << "  " << std::hex << y.x << std::endl;
    std::cout << "  " << std::hex << y.y << std::endl;

    // element addition
    Element u = group.GetCurve().Add(y, ECP::Point(2,3));

    std::cout << "Add:" << std::endl;
    std::cout << "  " << std::hex << u.x << std::endl;
    std::cout << "  " << std::hex << u.y << std::endl;

    // scalar multiplication
    Element v = group.GetCurve().ScalarMultiply(u, Integer::Two());

    std::cout << "Mult:" << std::endl;
    std::cout << "  " << std::hex << v.x << std::endl;
    std::cout << "  " << std::hex << v.y << std::endl;

    return 0;
}

g++ test.cxx ./libcryptopp.a -o test.exe编译代码。

运行代码产生:

$ ./test.exe
Private exponent:
  b48e35e8d60918f815857503b034681bc59db689dee0ffc35a140e365bb056dch
Public element:
  bb9c8daaace9712f368bc98cf004a4594a14f9c330e2db141906ec67f05ab8d8h
  e37e5e161aae15f54f20d67b665311717305932a1479427fe063d84c5be82a1dh
Add:
  f5055cd23f23f5721d8a5f6f87bd61206e972a97c19478200cb0b1f24af398ach
  107a532732098c4d051efc7f54d9bda78020a6e68f95e01a33700bab56a91f9ah
Mult:
  46628d3e4f43da4fd001c652682d33f608c34ce3cf6c13f45b9bd014cbb83ed4h
  3b58f98bd0d70196036b77f6fcca6fe206bdf3beda4b2b604d5cb8ae0327a57ch

DL_GroupParameters_EC&lt;ECP&gt; group 看起来不寻常,因为您使用的是较低级别的基本接口。根据您的示例代码,我认为这就是您想要的位置。

一般来说,关于 EC 齿轮的对象层次结构如下所示。它同时使用“是一个”或“有一个”关系。例如,签名者和解密者各自“拥有”一个私钥。私钥“是”组参数。

Encryptor
  +- Public key
       +- Group parameters
            +- Curve
                 +- Field

Decryptor
  +- Private key
       +- Group parameters
            +- Curve
                 +- Field

Verifier
  +- Public key
       +- Group parameters
            +- Curve
                 +- Field

Signer
  +- Private key
       +- Group parameters
            +- Curve
                 +- Field

例如,Signer 是协议,它在一个包中实现了您需要的所有内容。签名者下方是私钥,它执行乘法和求幂。私钥下方是字段和曲线。依此类推,直到你得到系数和模数。

话虽如此,您通常希望使用更高级别的对象之一。大多数人使用加密器、解密器、公钥和私钥。大多数人不需要再往下走,比如 GroupParameters 或 Curves 之类的对象。


您可能还对 Crypto++ wiki 中的 Crypto++ ManualElliptic Curve Cryptography 感兴趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2013-05-29
    • 1970-01-01
    • 2013-04-04
    相关资源
    最近更新 更多