我有一个要求,其中指出。
使用静态统一模型 C(0e, 2s, ECC CDH) key 协议(protocol)技术(如 NIST 特别出版物 800-56Ar214 中指定,除了将共享 secret 归零的要求外)来计算共享 secret Z :
基于 SHA-256 的单步 key 派生函数 (KDF),如 NIST 特别出版物 800-56Ar2;和
椭圆曲线运算的 P-256 曲线
我已经阅读并尝试实现我发现的内容 here但它不起作用。
此时,我可以验证共享 secret 是否正确,但我无法获得正确的 key ,也无法(在不编辑 Bouncy CaSTLe 源代码的情况下)计算如何将 OtherInfo 引入计算中。我找啊找……
代码很简单
private static Byte[] getSingleStepKDF_SHA256( Byte[] OtherInfo,
Byte[] PrivateKey,
Byte[] PublicKey,
Int32 DesiredKeyBitLength
)
{
BigInteger bi = null;
X9ECParameters curve = null;
ECDomainParameters ecParam = null;
ECPrivateKeyParameters privKey = null;
ECPublicKeyParameters pubKey = null;
ECDHWithKdfBasicAgreement agree = null;
ECPoint point = null;
ECDHKekGenerator ecGen = null;
/***********************************************************************
*
* I currently do not know how to include OtherInfo into the
* calculation. I have tried actually modifying ECDHKekGenerator by
* overloading CalculateAgreement to accept OtherInfo. This had no
* affect on the resulting key. I have tried using KdfParameters but
* ECDHWithKdfBasicAgreement raises an exception when I do that.
*
* The shared seceret is always correct.
*
************************************************************************/
curve = NistNamedCurves.GetByName( "P-256" );
ecParam = new ECDomainParameters( curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed() );
privKey = new ECPrivateKeyParameters( new BigInteger( PrivateKey ), ecParam );
point = ecParam.Curve.DecodePoint( PublicKey );
pubKey = new ECPublicKeyParameters( point, ecParam );
ecGen = new ECDHKekGenerator( DigestUtilities.GetDigest( "SHA256" ) );
agree = new ECDHWithKdfBasicAgreement( NistObjectIdentifiers.IdAes256Cbc.ToString(), ecGen );
agree.Init( privKey );
// The shared secret is calculated in this method as well as the key
bi = agree.CalculateAgreement( pubKey );
return bi.ToByteArrayUnsigned().Take( ( int )( DesiredKeyBitLength / 8 ) ).ToArray();
}
我很困惑,希望能对我做错的事情提供帮助。谢谢
最佳答案
解决方案是我编写单步 KDF 代码,除了生成共享 key 之外不使用 Bouncy CaSTLe。希望这可以帮助其他努力实现这一目标的人
/// <summary>
/// Gets the single step KDF using Hash SHA256.
/// NIST SP800 56Ar2 Section 5.8.1.1
/// </summary>
/// <param name="OtherInfo">The other information.</param>
/// <param name="PrivateKey">The private key.</param>
/// <param name="PublicKey">The public key.</param>
/// <param name="DesiredKeyBitLength">Length of the desired key bit.</param>
/// <returns>Byte[].</returns>
private static Byte[] getSingleStepKDF_SHA256( Byte[] OtherInfo,
Byte[] PrivateKey,
Byte[] PublicKey,
Int32 DesiredKeyBitLength
)
{
ByteAccumulator ba = null;
Byte[] data = null;
Byte[] secret = null;
int keyDataLenInBits = 0;
int keyLenInBytes = 0;
uint reps = 0;
uint cntr = 0;
secret = getSharedSecret( PrivateKey, PublicKey );
if( secret != null )
{
#region Single-Step KDF
keyDataLenInBits = DesiredKeyBitLength;
keyLenInBytes = ( int )( DesiredKeyBitLength / 8 );
reps = ( uint )( keyDataLenInBits / 128 ); // Our hash length is 128 bytes
if( reps > ( UInt32.MaxValue - 1 ) )
new Exception( "reps too large" );
cntr = 1;
if( ( 4 + ( secret.Length * 8 ) + ( OtherInfo.Length * 8 ) ) > 256 )
new Exception( "data is too large" );
ba = new ByteAccumulator();
ba.IsBigEndian = true;
data = General.CatArray<Byte>( BitConverter.GetBytes( cntr ).Reverse().ToArray(),
secret,
OtherInfo );
for( int i = 1; i <= reps; i++ )
{
ba.AddBlock( SecureHashAlgorithm.GetSha256_BouncyCastle( data ), 32 );
// Increment counter modulo 2^32
cntr = ( uint )( cntr++ % 32 );
data = General.CatArray<Byte>( BitConverter.GetBytes( cntr ).Reverse().ToArray(),
secret,
OtherInfo );
}
return ba.ToArray().Take( keyLenInBytes ).ToArray();
#endregion Single-Step KDF
}
else
return null;
}
/// <summary>
/// Gets the shared secret.
/// </summary>
/// <param name="PrivateKeyIn">The private key in.</param>
/// <param name="PublicKeyIn">The public key in.</param>
/// <returns>Byte[].</returns>
private static Byte[] getSharedSecret( Byte[] PrivateKeyIn, Byte[] PublicKeyIn )
{
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
X9ECParameters curve = null;
ECDomainParameters ecParam = null;
ECPrivateKeyParameters privKey = null;
ECPublicKeyParameters pubKey = null;
ECPoint point = null;
curve = NistNamedCurves.GetByName( "P-256" );
ecParam = new ECDomainParameters( curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed() );
privKey = new ECPrivateKeyParameters( new BigInteger( PrivateKeyIn ), ecParam );
point = ecParam.Curve.DecodePoint( PublicKeyIn );
pubKey = new ECPublicKeyParameters( point, ecParam );
agreement.Init( privKey );
BigInteger secret = agreement.CalculateAgreement( pubKey );
return secret.ToByteArrayUnsigned();
}
关于c# - ECDH 与充气城堡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39648807/