我有一个要求说明。
使用,计算共享密钥Z,静态统一模型,C(0e,2s,ECC CDH)密钥协商技术(在NIST特刊800-56Ar214中指定,除了将共享密钥归零的要求) :
基于SHA-256的单步密钥导出函数(KDF),如中所述 NIST特刊800-56Ar2;以及
椭圆曲线运算的P-256曲线
我已阅读并尝试实施我发现的here,但它不起作用。
此时我可以验证共享密钥是否正确,但我无法获得正确的密钥,也不能(不编辑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();
}
我很难过,并且会对我做错的任何帮助表示感谢。感谢
答案 0 :(得分:2)
解决方案是我编写单步KDF代码而不是使用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();
}