使用 public 密钥坐标与 Crypto++ 的 ECDH class
Using public key coordinate with Crypto++'s ECDH class
我正在使用 crypto++ 进行 ECDH 密钥协议
ECDH.Agree(key, privateKey, outherpublicKey);
鉴于 public 键我只有 X 和 Y 坐标。如何从这个值生成 public 键?
ECDH.Agree(key,privateKey, getPublicKey(X,Y))
提前致谢
Given that for public key I have only X and Y coordinates. How to generate publicKey from this values?
ECDH.Agree(key,privateKey, getPublicKey(X,Y))
{x,y}
是曲线上的一个点,但是直接用它来操作从来都不是一件容易的事。
这就是我们真正想要做的,但它不起作用。问题是 ECDH::Domain
只是域参数。 public 点和私有指数位于顶部。
OID curve = ASN1::secp256r1();
DL_GroupParameters_EC<ECP> params(curve);
Integer x("...");
Integer y("...");
ECP::Point q(x, y);
DL_PublicKey_EC<ECP> pubKey;
pubKey.Initialize(params, q);
ECDH < ECP >::Domain theirs(pubKey);
更复杂的是,ECDH 协议生成的密钥是临时的或短暂的。它们不应该被持久化;相反,它们应该使用一次并丢弃。所以 Crypto++ 并不容易持久化它们(比如,提供 DEREncode
)。
分析
要使用{x,y}
坐标,我们需要弄清楚图书馆是如何使用它的。临时 public 和私钥是在第 1380 行附近的 pubkey.h
中创建的。它们的代码如下:
void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey)
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, PrivateKeyLength());
}
void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey)
{
const DL_GroupParameters<T> ¶ms = GetAbstractGroupParameters();
Integer x(privateKey, PrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
上面的兴趣线是params.EncodeElement(true, y, publicKey)
。要了解那里发生了什么,我们需要查看第 70 行附近的 eccrypto.h
,并注意 reversible
是 true
:
void EncodeElement(bool reversible, const Element &element, byte *encoded)
{
if (reversible)
GetCurve().EncodePoint(encoded, element, m_compress);
else
element.x.Encode(encoded, GetEncodedElementSize(false));
}
params.EncodeElement
呼叫 ECP::EncodePoint
。要查看它的作用,我们可以检查第 120 行附近的 ecp.cpp
。该例程写入一个未压缩的点,但在 public 元素的最大大小上阻塞 x
和 y
,这应该是字段大小或子组顺序。
void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed)
{
if (P.identity)
NullStore().TransferTo(bt, EncodedPointSize(compressed));
else if (compressed)
{
bt.Put(2 + P.y.GetBit(0));
P.x.Encode(bt, GetField().MaxElementByteLength());
}
else
{
unsigned int len = GetField().MaxElementByteLength();
bt.Put(4); // uncompressed
P.x.Encode(bt, len);
P.y.Encode(bt, len);
}
}
不用太担心 BufferedTransformation
。有多种方法可以将 byte[]
变成一个,它发生在上面显示的代码之前。如果跟踪代码,您将看到它通过 ArraySource
:
进行了转换
byte myArray[PublicEphemeralKeyLength()];
ArraySource as(myArray, COUNTOF(myArray));
上面,as
是一个 BufferedTransformation
,它包装了你传递给函数的 byte[]
。
最后一个悬而未决的问题是字段元素的最大大小。这似乎是模数大小减一,以字节为单位:
$ grep -I -A 1 MaxElementByteLength modarith.h
unsigned int MaxElementByteLength() const
{return (m_modulus-1).ByteCount();}
协议
根据以上信息,您应该执行以下操作。您需要在 ECP::Point q(x,y)
中提供 x
和 y
的值。它们只是 Crypto++ 整数。
OID curve = ASN1::secp256r1();
DL_GroupParameters_EC<ECP> params(curve);
size_t size = params.GetEncodedElementSize(true);
vector<byte> othersPublicKey(size);
ECP::Point q(x,y);
params.EncodeElement(true, q, &othersPublicKey[0]);
那你可以拨打:
ecdh.Agree(key, myPrivateKey, &othersPublicKey[0]);
请注意:params.GetEncodedElementSize(true)
应等于 PublicEphemeralKeyLength()
。如果它们不相等,则说明有问题。
如果您需要修改压缩,那么您可以:
params.SetPointCompression(true);
我会将其添加到 Crypto++ 的 Elliptic Curve Diffie-Hellman wiki 页面,这样其他人就不必再四处寻找了。
我正在使用 crypto++ 进行 ECDH 密钥协议
ECDH.Agree(key, privateKey, outherpublicKey);
鉴于 public 键我只有 X 和 Y 坐标。如何从这个值生成 public 键?
ECDH.Agree(key,privateKey, getPublicKey(X,Y))
提前致谢
Given that for public key I have only X and Y coordinates. How to generate publicKey from this values?
ECDH.Agree(key,privateKey, getPublicKey(X,Y))
{x,y}
是曲线上的一个点,但是直接用它来操作从来都不是一件容易的事。
这就是我们真正想要做的,但它不起作用。问题是 ECDH::Domain
只是域参数。 public 点和私有指数位于顶部。
OID curve = ASN1::secp256r1();
DL_GroupParameters_EC<ECP> params(curve);
Integer x("...");
Integer y("...");
ECP::Point q(x, y);
DL_PublicKey_EC<ECP> pubKey;
pubKey.Initialize(params, q);
ECDH < ECP >::Domain theirs(pubKey);
更复杂的是,ECDH 协议生成的密钥是临时的或短暂的。它们不应该被持久化;相反,它们应该使用一次并丢弃。所以 Crypto++ 并不容易持久化它们(比如,提供 DEREncode
)。
分析
要使用{x,y}
坐标,我们需要弄清楚图书馆是如何使用它的。临时 public 和私钥是在第 1380 行附近的 pubkey.h
中创建的。它们的代码如下:
void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey)
{
Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
x.Encode(privateKey, PrivateKeyLength());
}
void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey)
{
const DL_GroupParameters<T> ¶ms = GetAbstractGroupParameters();
Integer x(privateKey, PrivateKeyLength());
Element y = params.ExponentiateBase(x);
params.EncodeElement(true, y, publicKey);
}
上面的兴趣线是params.EncodeElement(true, y, publicKey)
。要了解那里发生了什么,我们需要查看第 70 行附近的 eccrypto.h
,并注意 reversible
是 true
:
void EncodeElement(bool reversible, const Element &element, byte *encoded)
{
if (reversible)
GetCurve().EncodePoint(encoded, element, m_compress);
else
element.x.Encode(encoded, GetEncodedElementSize(false));
}
params.EncodeElement
呼叫 ECP::EncodePoint
。要查看它的作用,我们可以检查第 120 行附近的 ecp.cpp
。该例程写入一个未压缩的点,但在 public 元素的最大大小上阻塞 x
和 y
,这应该是字段大小或子组顺序。
void ECP::EncodePoint(BufferedTransformation &bt, const Point &P, bool compressed)
{
if (P.identity)
NullStore().TransferTo(bt, EncodedPointSize(compressed));
else if (compressed)
{
bt.Put(2 + P.y.GetBit(0));
P.x.Encode(bt, GetField().MaxElementByteLength());
}
else
{
unsigned int len = GetField().MaxElementByteLength();
bt.Put(4); // uncompressed
P.x.Encode(bt, len);
P.y.Encode(bt, len);
}
}
不用太担心 BufferedTransformation
。有多种方法可以将 byte[]
变成一个,它发生在上面显示的代码之前。如果跟踪代码,您将看到它通过 ArraySource
:
byte myArray[PublicEphemeralKeyLength()];
ArraySource as(myArray, COUNTOF(myArray));
上面,as
是一个 BufferedTransformation
,它包装了你传递给函数的 byte[]
。
最后一个悬而未决的问题是字段元素的最大大小。这似乎是模数大小减一,以字节为单位:
$ grep -I -A 1 MaxElementByteLength modarith.h
unsigned int MaxElementByteLength() const
{return (m_modulus-1).ByteCount();}
协议
根据以上信息,您应该执行以下操作。您需要在 ECP::Point q(x,y)
中提供 x
和 y
的值。它们只是 Crypto++ 整数。
OID curve = ASN1::secp256r1();
DL_GroupParameters_EC<ECP> params(curve);
size_t size = params.GetEncodedElementSize(true);
vector<byte> othersPublicKey(size);
ECP::Point q(x,y);
params.EncodeElement(true, q, &othersPublicKey[0]);
那你可以拨打:
ecdh.Agree(key, myPrivateKey, &othersPublicKey[0]);
请注意:params.GetEncodedElementSize(true)
应等于 PublicEphemeralKeyLength()
。如果它们不相等,则说明有问题。
如果您需要修改压缩,那么您可以:
params.SetPointCompression(true);
我会将其添加到 Crypto++ 的 Elliptic Curve Diffie-Hellman wiki 页面,这样其他人就不必再四处寻找了。