init commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class DHAgreement
|
||||
{
|
||||
private DHPrivateKeyParameters key;
|
||||
|
||||
private DHParameters dhParams;
|
||||
|
||||
private BigInteger privateValue;
|
||||
|
||||
private SecureRandom random;
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
AsymmetricKeyParameter asymmetricKeyParameter;
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
ParametersWithRandom parametersWithRandom = (ParametersWithRandom)parameters;
|
||||
random = parametersWithRandom.Random;
|
||||
asymmetricKeyParameter = (AsymmetricKeyParameter)parametersWithRandom.Parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
random = new SecureRandom();
|
||||
asymmetricKeyParameter = (AsymmetricKeyParameter)parameters;
|
||||
}
|
||||
if (!(asymmetricKeyParameter is DHPrivateKeyParameters))
|
||||
{
|
||||
throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
|
||||
}
|
||||
key = (DHPrivateKeyParameters)asymmetricKeyParameter;
|
||||
dhParams = key.Parameters;
|
||||
}
|
||||
|
||||
public BigInteger CalculateMessage()
|
||||
{
|
||||
DHKeyPairGenerator dHKeyPairGenerator = new DHKeyPairGenerator();
|
||||
dHKeyPairGenerator.Init(new DHKeyGenerationParameters(random, dhParams));
|
||||
AsymmetricCipherKeyPair asymmetricCipherKeyPair = dHKeyPairGenerator.GenerateKeyPair();
|
||||
privateValue = ((DHPrivateKeyParameters)asymmetricCipherKeyPair.Private).X;
|
||||
return ((DHPublicKeyParameters)asymmetricCipherKeyPair.Public).Y;
|
||||
}
|
||||
|
||||
public BigInteger CalculateAgreement(DHPublicKeyParameters pub, BigInteger message)
|
||||
{
|
||||
if (pub == null)
|
||||
{
|
||||
throw new ArgumentNullException("pub");
|
||||
}
|
||||
if (message == null)
|
||||
{
|
||||
throw new ArgumentNullException("message");
|
||||
}
|
||||
if (!pub.Parameters.Equals(dhParams))
|
||||
{
|
||||
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
|
||||
}
|
||||
BigInteger p = dhParams.P;
|
||||
BigInteger y = pub.Y;
|
||||
if (y == null || y.CompareTo(BigInteger.One) <= 0 || y.CompareTo(p.Subtract(BigInteger.One)) >= 0)
|
||||
{
|
||||
throw new ArgumentException("Diffie-Hellman public key is weak");
|
||||
}
|
||||
BigInteger bigInteger = y.ModPow(privateValue, p);
|
||||
if (bigInteger.Equals(BigInteger.One))
|
||||
{
|
||||
throw new InvalidOperationException("Shared key can't be 1");
|
||||
}
|
||||
return message.ModPow(key.X, p).Multiply(bigInteger).Mod(p);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class DHBasicAgreement : IBasicAgreement
|
||||
{
|
||||
private DHPrivateKeyParameters key;
|
||||
|
||||
private DHParameters dhParams;
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom)parameters).Parameters;
|
||||
}
|
||||
if (!(parameters is DHPrivateKeyParameters))
|
||||
{
|
||||
throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
|
||||
}
|
||||
key = (DHPrivateKeyParameters)parameters;
|
||||
dhParams = key.Parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (key.Parameters.P.BitLength + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(ICipherParameters pubKey)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new InvalidOperationException("Agreement algorithm not initialised");
|
||||
}
|
||||
DHPublicKeyParameters dHPublicKeyParameters = (DHPublicKeyParameters)pubKey;
|
||||
if (!dHPublicKeyParameters.Parameters.Equals(dhParams))
|
||||
{
|
||||
throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
|
||||
}
|
||||
BigInteger p = dhParams.P;
|
||||
BigInteger y = dHPublicKeyParameters.Y;
|
||||
if (y == null || y.CompareTo(BigInteger.One) <= 0 || y.CompareTo(p.Subtract(BigInteger.One)) >= 0)
|
||||
{
|
||||
throw new ArgumentException("Diffie-Hellman public key is weak");
|
||||
}
|
||||
BigInteger bigInteger = y.ModPow(key.X, p);
|
||||
if (bigInteger.Equals(BigInteger.One))
|
||||
{
|
||||
throw new InvalidOperationException("Shared key can't be 1");
|
||||
}
|
||||
return bigInteger;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities.Encoders;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class DHStandardGroups
|
||||
{
|
||||
private static readonly string rfc2409_768_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc2409_768_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc2409_768 = FromPG(rfc2409_768_p, rfc2409_768_g);
|
||||
|
||||
private static readonly string rfc2409_1024_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc2409_1024_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc2409_1024 = FromPG(rfc2409_1024_p, rfc2409_1024_g);
|
||||
|
||||
private static readonly string rfc3526_1536_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc3526_1536_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc3526_1536 = FromPG(rfc3526_1536_p, rfc3526_1536_g);
|
||||
|
||||
private static readonly string rfc3526_2048_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc3526_2048_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc3526_2048 = FromPG(rfc3526_2048_p, rfc3526_2048_g);
|
||||
|
||||
private static readonly string rfc3526_3072_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc3526_3072_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc3526_3072 = FromPG(rfc3526_3072_p, rfc3526_3072_g);
|
||||
|
||||
private static readonly string rfc3526_4096_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc3526_4096_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc3526_4096 = FromPG(rfc3526_4096_p, rfc3526_4096_g);
|
||||
|
||||
private static readonly string rfc3526_6144_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc3526_6144_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc3526_6144 = FromPG(rfc3526_6144_p, rfc3526_6144_g);
|
||||
|
||||
private static readonly string rfc3526_8192_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF";
|
||||
|
||||
private static readonly string rfc3526_8192_g = "02";
|
||||
|
||||
public static readonly DHParameters rfc3526_8192 = FromPG(rfc3526_8192_p, rfc3526_8192_g);
|
||||
|
||||
public static readonly DHParameters rfc4306_768 = rfc2409_768;
|
||||
|
||||
public static readonly DHParameters rfc4306_1024 = rfc2409_1024;
|
||||
|
||||
private static readonly string rfc5114_1024_160_p = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371";
|
||||
|
||||
private static readonly string rfc5114_1024_160_g = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507FD6406CFF14266D31266FEA1E5C41564B777E690F5504F213160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28AD662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24855E6EEB22B3B2E5";
|
||||
|
||||
private static readonly string rfc5114_1024_160_q = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353";
|
||||
|
||||
[Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")]
|
||||
public static readonly DHParameters rfc5114_1024_160 = FromPGQ(rfc5114_1024_160_p, rfc5114_1024_160_g, rfc5114_1024_160_q);
|
||||
|
||||
private static readonly string rfc5114_2048_224_p = "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC2129037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708B3BF8A317091883681286130BC8985DB1602E714415D9330278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486DCDF93ACC44328387315D75E198C641A480CD86A1B9E587E8BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71CF9DE5384E71B81C0AC4DFFE0C10E64F";
|
||||
|
||||
private static readonly string rfc5114_2048_224_g = "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFAAB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7C17669101999024AF4D027275AC1348BB8A762D0521BC98AE247150422EA1ED409939D54DA7460CDB5F6C6B250717CBEF180EB34118E98D119529A45D6F834566E3025E316A330EFBB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC017981BC087F2A7065B384B890D3191F2BFA";
|
||||
|
||||
private static readonly string rfc5114_2048_224_q = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB";
|
||||
|
||||
[Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")]
|
||||
public static readonly DHParameters rfc5114_2048_224 = FromPGQ(rfc5114_2048_224_p, rfc5114_2048_224_g, rfc5114_2048_224_q);
|
||||
|
||||
private static readonly string rfc5114_2048_256_p = "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597";
|
||||
|
||||
private static readonly string rfc5114_2048_256_g = "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659";
|
||||
|
||||
private static readonly string rfc5114_2048_256_q = "8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3";
|
||||
|
||||
[Obsolete("Existence of a 'hidden SNFS' backdoor cannot be ruled out.")]
|
||||
public static readonly DHParameters rfc5114_2048_256 = FromPGQ(rfc5114_2048_256_p, rfc5114_2048_256_g, rfc5114_2048_256_q);
|
||||
|
||||
public static readonly DHParameters rfc5996_768 = rfc4306_768;
|
||||
|
||||
public static readonly DHParameters rfc5996_1024 = rfc4306_1024;
|
||||
|
||||
private static readonly string rfc7919_ffdhe2048_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B423861285C97FFFFFFFFFFFFFFFF";
|
||||
|
||||
public static readonly DHParameters rfc7919_ffdhe2048 = Rfc7919Parameters(rfc7919_ffdhe2048_p, 225);
|
||||
|
||||
private static readonly string rfc7919_ffdhe3072_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B66C62E37FFFFFFFFFFFFFFFF";
|
||||
|
||||
public static readonly DHParameters rfc7919_ffdhe3072 = Rfc7919Parameters(rfc7919_ffdhe3072_p, 275);
|
||||
|
||||
private static readonly string rfc7919_ffdhe4096_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E655F6AFFFFFFFFFFFFFFFF";
|
||||
|
||||
public static readonly DHParameters rfc7919_ffdhe4096 = Rfc7919Parameters(rfc7919_ffdhe4096_p, 325);
|
||||
|
||||
private static readonly string rfc7919_ffdhe6144_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CD0E40E65FFFFFFFFFFFFFFFF";
|
||||
|
||||
public static readonly DHParameters rfc7919_ffdhe6144 = Rfc7919Parameters(rfc7919_ffdhe6144_p, 375);
|
||||
|
||||
private static readonly string rfc7919_ffdhe8192_p = "FFFFFFFFFFFFFFFFADF85458A2BB4A9AAFDC5620273D3CF1D8B9C583CE2D3695A9E13641146433FBCC939DCE249B3EF97D2FE363630C75D8F681B202AEC4617AD3DF1ED5D5FD65612433F51F5F066ED0856365553DED1AF3B557135E7F57C935984F0C70E0E68B77E2A689DAF3EFE8721DF158A136ADE73530ACCA4F483A797ABC0AB182B324FB61D108A94BB2C8E3FBB96ADAB760D7F4681D4F42A3DE394DF4AE56EDE76372BB190B07A7C8EE0A6D709E02FCE1CDF7E2ECC03404CD28342F619172FE9CE98583FF8E4F1232EEF28183C3FE3B1B4C6FAD733BB5FCBC2EC22005C58EF1837D1683B2C6F34A26C1B2EFFA886B4238611FCFDCDE355B3B6519035BBC34F4DEF99C023861B46FC9D6E6C9077AD91D2691F7F7EE598CB0FAC186D91CAEFE130985139270B4130C93BC437944F4FD4452E2D74DD364F2E21E71F54BFF5CAE82AB9C9DF69EE86D2BC522363A0DABC521979B0DEADA1DBF9A42D5C4484E0ABCD06BFA53DDEF3C1B20EE3FD59D7C25E41D2B669E1EF16E6F52C3164DF4FB7930E9E4E58857B6AC7D5F42D69F6D187763CF1D5503400487F55BA57E31CC7A7135C886EFB4318AED6A1E012D9E6832A907600A918130C46DC778F971AD0038092999A333CB8B7A1A1DB93D7140003C2A4ECEA9F98D0ACC0A8291CDCEC97DCF8EC9B55A7F88A46B4DB5A851F44182E1C68A007E5E0DD9020BFD64B645036C7A4E677D2C38532A3A23BA4442CAF53EA63BB454329B7624C8917BDD64B1C0FD4CB38E8C334C701C3ACDAD0657FCCFEC719B1F5C3E4E46041F388147FB4CFDB477A52471F7A9A96910B855322EDB6340D8A00EF092350511E30ABEC1FFF9E3A26E7FB29F8C183023C3587E38DA0077D9B4763E4E4B94B2BBC194C6651E77CAF992EEAAC0232A281BF6B3A739C1226116820AE8DB5847A67CBEF9C9091B462D538CD72B03746AE77F5E62292C311562A846505DC82DB854338AE49F5235C95B91178CCF2DD5CACEF403EC9D1810C6272B045B3B71F9DC6B80D63FDD4A8E9ADB1E6962A69526D43161C1A41D570D7938DAD4A40E329CCFF46AAA36AD004CF600C8381E425A31D951AE64FDB23FCEC9509D43687FEB69EDD1CC5E0B8CC3BDF64B10EF86B63142A3AB8829555B2F747C932665CB2C0F1CC01BD70229388839D2AF05E454504AC78B7582822846C0BA35C35F5C59160CC046FD8251541FC68C9C86B022BB7099876A460E7451A8A93109703FEE1C217E6C3826E52C51AA691E0E423CFC99E9E31650C1217B624816CDAD9A95F9D5B8019488D9C0A0A1FE3075A577E23183F81D4A3F2FA4571EFC8CE0BA8A4FE8B6855DFE72B0A66EDED2FBABFBE58A30FAFABE1C5D71A87E2F741EF8C1FE86FEA6BBFDE530677F0D97D11D49F7A8443D0822E506A9F4614E011E2A94838FF88CD68C8BB7C5C6424CFFFFFFFFFFFFFFFF";
|
||||
|
||||
public static readonly DHParameters rfc7919_ffdhe8192 = Rfc7919Parameters(rfc7919_ffdhe8192_p, 400);
|
||||
|
||||
private static BigInteger FromHex(string hex)
|
||||
{
|
||||
return new BigInteger(1, Hex.Decode(hex));
|
||||
}
|
||||
|
||||
private static DHParameters FromPG(string hexP, string hexG)
|
||||
{
|
||||
return new DHParameters(FromHex(hexP), FromHex(hexG));
|
||||
}
|
||||
|
||||
private static DHParameters FromPGQ(string hexP, string hexG, string hexQ)
|
||||
{
|
||||
return new DHParameters(FromHex(hexP), FromHex(hexG), FromHex(hexQ));
|
||||
}
|
||||
|
||||
private static DHParameters Rfc7919Parameters(string hexP, int l)
|
||||
{
|
||||
BigInteger bigInteger = FromHex(hexP);
|
||||
return new DHParameters(bigInteger, BigInteger.Two, bigInteger.ShiftRight(1), l);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Math.EC;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class ECDHBasicAgreement : IBasicAgreement
|
||||
{
|
||||
protected internal ECPrivateKeyParameters privKey;
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom)parameters).Parameters;
|
||||
}
|
||||
privKey = (ECPrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (privKey.Parameters.Curve.FieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(ICipherParameters pubKey)
|
||||
{
|
||||
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)pubKey;
|
||||
ECDomainParameters parameters = privKey.Parameters;
|
||||
if (!parameters.Equals(eCPublicKeyParameters.Parameters))
|
||||
{
|
||||
throw new InvalidOperationException("ECDH public key has wrong domain parameters");
|
||||
}
|
||||
BigInteger bigInteger = privKey.D;
|
||||
ECPoint eCPoint = ECAlgorithms.CleanPoint(parameters.Curve, eCPublicKeyParameters.Q);
|
||||
if (eCPoint.IsInfinity)
|
||||
{
|
||||
throw new InvalidOperationException("Infinity is not a valid public key for ECDH");
|
||||
}
|
||||
BigInteger h = parameters.H;
|
||||
if (!h.Equals(BigInteger.One))
|
||||
{
|
||||
bigInteger = parameters.HInv.Multiply(bigInteger).Mod(parameters.N);
|
||||
eCPoint = ECAlgorithms.ReferenceMultiply(eCPoint, h);
|
||||
}
|
||||
ECPoint eCPoint2 = eCPoint.Multiply(bigInteger).Normalize();
|
||||
if (eCPoint2.IsInfinity)
|
||||
{
|
||||
throw new InvalidOperationException("Infinity is not a valid agreement value for ECDH");
|
||||
}
|
||||
return eCPoint2.AffineXCoord.ToBigInteger();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Math.EC;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class ECDHCBasicAgreement : IBasicAgreement
|
||||
{
|
||||
private ECPrivateKeyParameters privKey;
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom)parameters).Parameters;
|
||||
}
|
||||
privKey = (ECPrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (privKey.Parameters.Curve.FieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(ICipherParameters pubKey)
|
||||
{
|
||||
ECPublicKeyParameters eCPublicKeyParameters = (ECPublicKeyParameters)pubKey;
|
||||
ECDomainParameters parameters = privKey.Parameters;
|
||||
if (!parameters.Equals(eCPublicKeyParameters.Parameters))
|
||||
{
|
||||
throw new InvalidOperationException("ECDHC public key has wrong domain parameters");
|
||||
}
|
||||
BigInteger b = parameters.H.Multiply(privKey.D).Mod(parameters.N);
|
||||
ECPoint eCPoint = ECAlgorithms.CleanPoint(parameters.Curve, eCPublicKeyParameters.Q);
|
||||
if (eCPoint.IsInfinity)
|
||||
{
|
||||
throw new InvalidOperationException("Infinity is not a valid public key for ECDHC");
|
||||
}
|
||||
ECPoint eCPoint2 = eCPoint.Multiply(b).Normalize();
|
||||
if (eCPoint2.IsInfinity)
|
||||
{
|
||||
throw new InvalidOperationException("Infinity is not a valid agreement value for ECDHC");
|
||||
}
|
||||
return eCPoint2.AffineXCoord.ToBigInteger();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class ECDHWithKdfBasicAgreement : ECDHBasicAgreement
|
||||
{
|
||||
private readonly string algorithm;
|
||||
|
||||
private readonly IDerivationFunction kdf;
|
||||
|
||||
public ECDHWithKdfBasicAgreement(string algorithm, IDerivationFunction kdf)
|
||||
{
|
||||
if (algorithm == null)
|
||||
{
|
||||
throw new ArgumentNullException("algorithm");
|
||||
}
|
||||
if (kdf == null)
|
||||
{
|
||||
throw new ArgumentNullException("kdf");
|
||||
}
|
||||
this.algorithm = algorithm;
|
||||
this.kdf = kdf;
|
||||
}
|
||||
|
||||
public override BigInteger CalculateAgreement(ICipherParameters pubKey)
|
||||
{
|
||||
BigInteger r = base.CalculateAgreement(pubKey);
|
||||
int defaultKeySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
|
||||
DHKdfParameters parameters = new DHKdfParameters(new DerObjectIdentifier(algorithm), defaultKeySize, BigIntToBytes(r));
|
||||
kdf.Init(parameters);
|
||||
byte[] array = new byte[defaultKeySize / 8];
|
||||
kdf.GenerateBytes(array, 0, array.Length);
|
||||
return new BigInteger(1, array);
|
||||
}
|
||||
|
||||
private byte[] BigIntToBytes(BigInteger r)
|
||||
{
|
||||
int byteLength = X9IntegerConverter.GetByteLength(privKey.Parameters.Curve);
|
||||
return X9IntegerConverter.IntegerToBytes(r, byteLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Math.EC;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class ECMqvBasicAgreement : IBasicAgreement
|
||||
{
|
||||
protected internal MqvPrivateParameters privParams;
|
||||
|
||||
public virtual void Init(ICipherParameters parameters)
|
||||
{
|
||||
if (parameters is ParametersWithRandom)
|
||||
{
|
||||
parameters = ((ParametersWithRandom)parameters).Parameters;
|
||||
}
|
||||
privParams = (MqvPrivateParameters)parameters;
|
||||
}
|
||||
|
||||
public virtual int GetFieldSize()
|
||||
{
|
||||
return (privParams.StaticPrivateKey.Parameters.Curve.FieldSize + 7) / 8;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateAgreement(ICipherParameters pubKey)
|
||||
{
|
||||
MqvPublicParameters mqvPublicParameters = (MqvPublicParameters)pubKey;
|
||||
ECPrivateKeyParameters staticPrivateKey = privParams.StaticPrivateKey;
|
||||
ECDomainParameters parameters = staticPrivateKey.Parameters;
|
||||
if (!parameters.Equals(mqvPublicParameters.StaticPublicKey.Parameters))
|
||||
{
|
||||
throw new InvalidOperationException("ECMQV public key components have wrong domain parameters");
|
||||
}
|
||||
ECPoint eCPoint = CalculateMqvAgreement(parameters, staticPrivateKey, privParams.EphemeralPrivateKey, privParams.EphemeralPublicKey, mqvPublicParameters.StaticPublicKey, mqvPublicParameters.EphemeralPublicKey).Normalize();
|
||||
if (eCPoint.IsInfinity)
|
||||
{
|
||||
throw new InvalidOperationException("Infinity is not a valid agreement value for MQV");
|
||||
}
|
||||
return eCPoint.AffineXCoord.ToBigInteger();
|
||||
}
|
||||
|
||||
private static ECPoint CalculateMqvAgreement(ECDomainParameters parameters, ECPrivateKeyParameters d1U, ECPrivateKeyParameters d2U, ECPublicKeyParameters Q2U, ECPublicKeyParameters Q1V, ECPublicKeyParameters Q2V)
|
||||
{
|
||||
BigInteger n = parameters.N;
|
||||
int num = (n.BitLength + 1) / 2;
|
||||
BigInteger m = BigInteger.One.ShiftLeft(num);
|
||||
ECCurve curve = parameters.Curve;
|
||||
ECPoint eCPoint = ECAlgorithms.CleanPoint(curve, Q2U.Q);
|
||||
ECPoint p = ECAlgorithms.CleanPoint(curve, Q1V.Q);
|
||||
ECPoint eCPoint2 = ECAlgorithms.CleanPoint(curve, Q2V.Q);
|
||||
BigInteger bigInteger = eCPoint.AffineXCoord.ToBigInteger();
|
||||
BigInteger bigInteger2 = bigInteger.Mod(m);
|
||||
BigInteger val = bigInteger2.SetBit(num);
|
||||
BigInteger val2 = d1U.D.Multiply(val).Add(d2U.D).Mod(n);
|
||||
BigInteger bigInteger3 = eCPoint2.AffineXCoord.ToBigInteger();
|
||||
BigInteger bigInteger4 = bigInteger3.Mod(m);
|
||||
BigInteger bigInteger5 = bigInteger4.SetBit(num);
|
||||
BigInteger bigInteger6 = parameters.H.Multiply(val2).Mod(n);
|
||||
return ECAlgorithms.SumOfTwoMultiplies(p, bigInteger5.Multiply(bigInteger6).Mod(n), eCPoint2, bigInteger6);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class ECMqvWithKdfBasicAgreement : ECMqvBasicAgreement
|
||||
{
|
||||
private readonly string algorithm;
|
||||
|
||||
private readonly IDerivationFunction kdf;
|
||||
|
||||
public ECMqvWithKdfBasicAgreement(string algorithm, IDerivationFunction kdf)
|
||||
{
|
||||
if (algorithm == null)
|
||||
{
|
||||
throw new ArgumentNullException("algorithm");
|
||||
}
|
||||
if (kdf == null)
|
||||
{
|
||||
throw new ArgumentNullException("kdf");
|
||||
}
|
||||
this.algorithm = algorithm;
|
||||
this.kdf = kdf;
|
||||
}
|
||||
|
||||
public override BigInteger CalculateAgreement(ICipherParameters pubKey)
|
||||
{
|
||||
BigInteger r = base.CalculateAgreement(pubKey);
|
||||
int defaultKeySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
|
||||
DHKdfParameters parameters = new DHKdfParameters(new DerObjectIdentifier(algorithm), defaultKeySize, BigIntToBytes(r));
|
||||
kdf.Init(parameters);
|
||||
byte[] array = new byte[defaultKeySize / 8];
|
||||
kdf.GenerateBytes(array, 0, array.Length);
|
||||
return new BigInteger(1, array);
|
||||
}
|
||||
|
||||
private byte[] BigIntToBytes(BigInteger r)
|
||||
{
|
||||
int byteLength = X9IntegerConverter.GetByteLength(privParams.StaticPrivateKey.Parameters.Curve);
|
||||
return X9IntegerConverter.IntegerToBytes(r, byteLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public class JPakeParticipant
|
||||
{
|
||||
public static readonly int STATE_INITIALIZED = 0;
|
||||
|
||||
public static readonly int STATE_ROUND_1_CREATED = 10;
|
||||
|
||||
public static readonly int STATE_ROUND_1_VALIDATED = 20;
|
||||
|
||||
public static readonly int STATE_ROUND_2_CREATED = 30;
|
||||
|
||||
public static readonly int STATE_ROUND_2_VALIDATED = 40;
|
||||
|
||||
public static readonly int STATE_KEY_CALCULATED = 50;
|
||||
|
||||
public static readonly int STATE_ROUND_3_CREATED = 60;
|
||||
|
||||
public static readonly int STATE_ROUND_3_VALIDATED = 70;
|
||||
|
||||
private string participantId;
|
||||
|
||||
private char[] password;
|
||||
|
||||
private IDigest digest;
|
||||
|
||||
private readonly SecureRandom random;
|
||||
|
||||
private readonly BigInteger p;
|
||||
|
||||
private readonly BigInteger q;
|
||||
|
||||
private readonly BigInteger g;
|
||||
|
||||
private string partnerParticipantId;
|
||||
|
||||
private BigInteger x1;
|
||||
|
||||
private BigInteger x2;
|
||||
|
||||
private BigInteger gx1;
|
||||
|
||||
private BigInteger gx2;
|
||||
|
||||
private BigInteger gx3;
|
||||
|
||||
private BigInteger gx4;
|
||||
|
||||
private BigInteger b;
|
||||
|
||||
private int state;
|
||||
|
||||
public virtual int State => state;
|
||||
|
||||
public JPakeParticipant(string participantId, char[] password)
|
||||
: this(participantId, password, JPakePrimeOrderGroups.NIST_3072)
|
||||
{
|
||||
}
|
||||
|
||||
public JPakeParticipant(string participantId, char[] password, JPakePrimeOrderGroup group)
|
||||
: this(participantId, password, group, new Sha256Digest(), new SecureRandom())
|
||||
{
|
||||
}
|
||||
|
||||
public JPakeParticipant(string participantId, char[] password, JPakePrimeOrderGroup group, IDigest digest, SecureRandom random)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(participantId, "participantId");
|
||||
JPakeUtilities.ValidateNotNull(password, "password");
|
||||
JPakeUtilities.ValidateNotNull(group, "p");
|
||||
JPakeUtilities.ValidateNotNull(digest, "digest");
|
||||
JPakeUtilities.ValidateNotNull(random, "random");
|
||||
if (password.Length == 0)
|
||||
{
|
||||
throw new ArgumentException("Password must not be empty.");
|
||||
}
|
||||
this.participantId = participantId;
|
||||
this.password = new char[password.Length];
|
||||
Array.Copy(password, this.password, password.Length);
|
||||
p = group.P;
|
||||
q = group.Q;
|
||||
g = group.G;
|
||||
this.digest = digest;
|
||||
this.random = random;
|
||||
state = STATE_INITIALIZED;
|
||||
}
|
||||
|
||||
public virtual JPakeRound1Payload CreateRound1PayloadToSend()
|
||||
{
|
||||
if (state >= STATE_ROUND_1_CREATED)
|
||||
{
|
||||
throw new InvalidOperationException("Round 1 payload already created for " + participantId);
|
||||
}
|
||||
x1 = JPakeUtilities.GenerateX1(q, random);
|
||||
x2 = JPakeUtilities.GenerateX2(q, random);
|
||||
gx1 = JPakeUtilities.CalculateGx(p, g, x1);
|
||||
gx2 = JPakeUtilities.CalculateGx(p, g, x2);
|
||||
BigInteger[] knowledgeProofForX = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, g, gx1, x1, participantId, digest, random);
|
||||
BigInteger[] knowledgeProofForX2 = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, g, gx2, x2, participantId, digest, random);
|
||||
state = STATE_ROUND_1_CREATED;
|
||||
return new JPakeRound1Payload(participantId, gx1, gx2, knowledgeProofForX, knowledgeProofForX2);
|
||||
}
|
||||
|
||||
public virtual void ValidateRound1PayloadReceived(JPakeRound1Payload round1PayloadReceived)
|
||||
{
|
||||
if (state >= STATE_ROUND_1_VALIDATED)
|
||||
{
|
||||
throw new InvalidOperationException("Validation already attempted for round 1 payload for " + participantId);
|
||||
}
|
||||
partnerParticipantId = round1PayloadReceived.ParticipantId;
|
||||
gx3 = round1PayloadReceived.Gx1;
|
||||
gx4 = round1PayloadReceived.Gx2;
|
||||
BigInteger[] knowledgeProofForX = round1PayloadReceived.KnowledgeProofForX1;
|
||||
BigInteger[] knowledgeProofForX2 = round1PayloadReceived.KnowledgeProofForX2;
|
||||
JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round1PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateGx4(gx4);
|
||||
JPakeUtilities.ValidateZeroKnowledgeProof(p, q, g, gx3, knowledgeProofForX, round1PayloadReceived.ParticipantId, digest);
|
||||
JPakeUtilities.ValidateZeroKnowledgeProof(p, q, g, gx4, knowledgeProofForX2, round1PayloadReceived.ParticipantId, digest);
|
||||
state = STATE_ROUND_1_VALIDATED;
|
||||
}
|
||||
|
||||
public virtual JPakeRound2Payload CreateRound2PayloadToSend()
|
||||
{
|
||||
if (state >= STATE_ROUND_2_CREATED)
|
||||
{
|
||||
throw new InvalidOperationException("Round 2 payload already created for " + participantId);
|
||||
}
|
||||
if (state < STATE_ROUND_1_VALIDATED)
|
||||
{
|
||||
throw new InvalidOperationException("Round 1 payload must be validated prior to creating round 2 payload for " + participantId);
|
||||
}
|
||||
BigInteger gA = JPakeUtilities.CalculateGA(p, gx1, gx3, gx4);
|
||||
BigInteger s = JPakeUtilities.CalculateS(password);
|
||||
BigInteger bigInteger = JPakeUtilities.CalculateX2s(q, x2, s);
|
||||
BigInteger bigInteger2 = JPakeUtilities.CalculateA(p, q, gA, bigInteger);
|
||||
BigInteger[] knowledgeProofForX2s = JPakeUtilities.CalculateZeroKnowledgeProof(p, q, gA, bigInteger2, bigInteger, participantId, digest, random);
|
||||
state = STATE_ROUND_2_CREATED;
|
||||
return new JPakeRound2Payload(participantId, bigInteger2, knowledgeProofForX2s);
|
||||
}
|
||||
|
||||
public virtual void ValidateRound2PayloadReceived(JPakeRound2Payload round2PayloadReceived)
|
||||
{
|
||||
if (state >= STATE_ROUND_2_VALIDATED)
|
||||
{
|
||||
throw new InvalidOperationException("Validation already attempted for round 2 payload for " + participantId);
|
||||
}
|
||||
if (state < STATE_ROUND_1_VALIDATED)
|
||||
{
|
||||
throw new InvalidOperationException("Round 1 payload must be validated prior to validation round 2 payload for " + participantId);
|
||||
}
|
||||
BigInteger ga = JPakeUtilities.CalculateGA(p, gx3, gx1, gx2);
|
||||
b = round2PayloadReceived.A;
|
||||
BigInteger[] knowledgeProofForX2s = round2PayloadReceived.KnowledgeProofForX2s;
|
||||
JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round2PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateParticipantIdsEqual(partnerParticipantId, round2PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateGa(ga);
|
||||
JPakeUtilities.ValidateZeroKnowledgeProof(p, q, ga, b, knowledgeProofForX2s, round2PayloadReceived.ParticipantId, digest);
|
||||
state = STATE_ROUND_2_VALIDATED;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateKeyingMaterial()
|
||||
{
|
||||
if (state >= STATE_KEY_CALCULATED)
|
||||
{
|
||||
throw new InvalidOperationException("Key already calculated for " + participantId);
|
||||
}
|
||||
if (state < STATE_ROUND_2_VALIDATED)
|
||||
{
|
||||
throw new InvalidOperationException("Round 2 payload must be validated prior to creating key for " + participantId);
|
||||
}
|
||||
BigInteger s = JPakeUtilities.CalculateS(password);
|
||||
Array.Clear(password, 0, password.Length);
|
||||
password = null;
|
||||
BigInteger result = JPakeUtilities.CalculateKeyingMaterial(p, q, gx4, x2, s, b);
|
||||
x1 = null;
|
||||
x2 = null;
|
||||
b = null;
|
||||
state = STATE_KEY_CALCULATED;
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual JPakeRound3Payload CreateRound3PayloadToSend(BigInteger keyingMaterial)
|
||||
{
|
||||
if (state >= STATE_ROUND_3_CREATED)
|
||||
{
|
||||
throw new InvalidOperationException("Round 3 payload already created for " + participantId);
|
||||
}
|
||||
if (state < STATE_KEY_CALCULATED)
|
||||
{
|
||||
throw new InvalidOperationException("Keying material must be calculated prior to creating round 3 payload for " + participantId);
|
||||
}
|
||||
BigInteger magTag = JPakeUtilities.CalculateMacTag(participantId, partnerParticipantId, gx1, gx2, gx3, gx4, keyingMaterial, digest);
|
||||
state = STATE_ROUND_3_CREATED;
|
||||
return new JPakeRound3Payload(participantId, magTag);
|
||||
}
|
||||
|
||||
public virtual void ValidateRound3PayloadReceived(JPakeRound3Payload round3PayloadReceived, BigInteger keyingMaterial)
|
||||
{
|
||||
if (state >= STATE_ROUND_3_VALIDATED)
|
||||
{
|
||||
throw new InvalidOperationException("Validation already attempted for round 3 payload for " + participantId);
|
||||
}
|
||||
if (state < STATE_KEY_CALCULATED)
|
||||
{
|
||||
throw new InvalidOperationException("Keying material must be calculated prior to validating round 3 payload for " + participantId);
|
||||
}
|
||||
JPakeUtilities.ValidateParticipantIdsDiffer(participantId, round3PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateParticipantIdsEqual(partnerParticipantId, round3PayloadReceived.ParticipantId);
|
||||
JPakeUtilities.ValidateMacTag(participantId, partnerParticipantId, gx1, gx2, gx3, gx4, keyingMaterial, digest, round3PayloadReceived.MacTag);
|
||||
gx1 = null;
|
||||
gx2 = null;
|
||||
gx3 = null;
|
||||
gx4 = null;
|
||||
state = STATE_ROUND_3_VALIDATED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public class JPakePrimeOrderGroup
|
||||
{
|
||||
private readonly BigInteger p;
|
||||
|
||||
private readonly BigInteger q;
|
||||
|
||||
private readonly BigInteger g;
|
||||
|
||||
public virtual BigInteger P => p;
|
||||
|
||||
public virtual BigInteger Q => q;
|
||||
|
||||
public virtual BigInteger G => g;
|
||||
|
||||
public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g)
|
||||
: this(p, q, g, skipChecks: false)
|
||||
{
|
||||
}
|
||||
|
||||
public JPakePrimeOrderGroup(BigInteger p, BigInteger q, BigInteger g, bool skipChecks)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(p, "p");
|
||||
JPakeUtilities.ValidateNotNull(q, "q");
|
||||
JPakeUtilities.ValidateNotNull(g, "g");
|
||||
if (!skipChecks)
|
||||
{
|
||||
if (!p.Subtract(JPakeUtilities.One).Mod(q).Equals(JPakeUtilities.Zero))
|
||||
{
|
||||
throw new ArgumentException("p-1 must be evenly divisible by q");
|
||||
}
|
||||
if (g.CompareTo(BigInteger.Two) == -1 || g.CompareTo(p.Subtract(JPakeUtilities.One)) == 1)
|
||||
{
|
||||
throw new ArgumentException("g must be in [2, p-1]");
|
||||
}
|
||||
if (!g.ModPow(q, p).Equals(JPakeUtilities.One))
|
||||
{
|
||||
throw new ArgumentException("g^q mod p must equal 1");
|
||||
}
|
||||
if (!p.IsProbablePrime(20))
|
||||
{
|
||||
throw new ArgumentException("p must be prime");
|
||||
}
|
||||
if (!q.IsProbablePrime(20))
|
||||
{
|
||||
throw new ArgumentException("q must be prime");
|
||||
}
|
||||
}
|
||||
this.p = p;
|
||||
this.q = q;
|
||||
this.g = g;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public class JPakePrimeOrderGroups
|
||||
{
|
||||
public static readonly JPakePrimeOrderGroup SUN_JCE_1024 = new JPakePrimeOrderGroup(new BigInteger("fd7f53811d75122952df4a9c2eece4e7f611b7523cef4400c31e3f80b6512669455d402251fb593d8d58fabfc5f5ba30f6cb9b556cd7813b801d346ff26660b76b9950a5a49f9fe8047b1022c24fbba9d7feb7c61bf83b57e7c6a8a6150f04fb83f6d3c51ec3023554135a169132f675f3ae2b61d72aeff22203199dd14801c7", 16), new BigInteger("9760508f15230bccb292b982a2eb840bf0581cf5", 16), new BigInteger("f7e1a085d69b3ddecbbcab5c36b857b97994afbbfa3aea82f9574c0b3d0782675159578ebad4594fe67107108180b449167123e84c281613b7cf09328cc8a6e13c167a8b547c8d28e0a3ae1e2bb3a675916ea37f0bfa213562f1fb627a01243bcca4f1bea8519089a883dfe15ae59f06928b665e807b552564014c3bfecf492a", 16), skipChecks: true);
|
||||
|
||||
public static readonly JPakePrimeOrderGroup NIST_2048 = new JPakePrimeOrderGroup(new BigInteger("C196BA05AC29E1F9C3C72D56DFFC6154A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A067CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE428782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE619ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD92D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BFFAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E5320121496DC65B3930E38047294FF877831A16D5228418DE8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A0402A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16), new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16), new BigInteger("A59A749A11242C58C894E9E5A91804E8FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35FC9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E5048B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B7159592E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E5745EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDFD049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E695515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED200AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16), skipChecks: true);
|
||||
|
||||
public static readonly JPakePrimeOrderGroup NIST_3072 = new JPakePrimeOrderGroup(new BigInteger("90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD61037E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE05E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA129F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E542D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA632C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0EE6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE030D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504FB0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C560EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16), new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16), new BigInteger("5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B82846F9A0C393914C792E6A923E2117AB805276A975AADB5261D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B67299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D58E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B988567A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A22D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16), skipChecks: true);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public class JPakeRound1Payload
|
||||
{
|
||||
private readonly string participantId;
|
||||
|
||||
private readonly BigInteger gx1;
|
||||
|
||||
private readonly BigInteger gx2;
|
||||
|
||||
private readonly BigInteger[] knowledgeProofForX1;
|
||||
|
||||
private readonly BigInteger[] knowledgeProofForX2;
|
||||
|
||||
public virtual string ParticipantId => participantId;
|
||||
|
||||
public virtual BigInteger Gx1 => gx1;
|
||||
|
||||
public virtual BigInteger Gx2 => gx2;
|
||||
|
||||
public virtual BigInteger[] KnowledgeProofForX1
|
||||
{
|
||||
get
|
||||
{
|
||||
BigInteger[] array = new BigInteger[knowledgeProofForX1.Length];
|
||||
Array.Copy(knowledgeProofForX1, array, knowledgeProofForX1.Length);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual BigInteger[] KnowledgeProofForX2
|
||||
{
|
||||
get
|
||||
{
|
||||
BigInteger[] array = new BigInteger[knowledgeProofForX2.Length];
|
||||
Array.Copy(knowledgeProofForX2, array, knowledgeProofForX2.Length);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
public JPakeRound1Payload(string participantId, BigInteger gx1, BigInteger gx2, BigInteger[] knowledgeProofForX1, BigInteger[] knowledgeProofForX2)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(participantId, "participantId");
|
||||
JPakeUtilities.ValidateNotNull(gx1, "gx1");
|
||||
JPakeUtilities.ValidateNotNull(gx2, "gx2");
|
||||
JPakeUtilities.ValidateNotNull(knowledgeProofForX1, "knowledgeProofForX1");
|
||||
JPakeUtilities.ValidateNotNull(knowledgeProofForX2, "knowledgeProofForX2");
|
||||
this.participantId = participantId;
|
||||
this.gx1 = gx1;
|
||||
this.gx2 = gx2;
|
||||
this.knowledgeProofForX1 = new BigInteger[knowledgeProofForX1.Length];
|
||||
Array.Copy(knowledgeProofForX1, this.knowledgeProofForX1, knowledgeProofForX1.Length);
|
||||
this.knowledgeProofForX2 = new BigInteger[knowledgeProofForX2.Length];
|
||||
Array.Copy(knowledgeProofForX2, this.knowledgeProofForX2, knowledgeProofForX2.Length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public class JPakeRound2Payload
|
||||
{
|
||||
private readonly string participantId;
|
||||
|
||||
private readonly BigInteger a;
|
||||
|
||||
private readonly BigInteger[] knowledgeProofForX2s;
|
||||
|
||||
public virtual string ParticipantId => participantId;
|
||||
|
||||
public virtual BigInteger A => a;
|
||||
|
||||
public virtual BigInteger[] KnowledgeProofForX2s
|
||||
{
|
||||
get
|
||||
{
|
||||
BigInteger[] array = new BigInteger[knowledgeProofForX2s.Length];
|
||||
Array.Copy(knowledgeProofForX2s, array, knowledgeProofForX2s.Length);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
public JPakeRound2Payload(string participantId, BigInteger a, BigInteger[] knowledgeProofForX2s)
|
||||
{
|
||||
JPakeUtilities.ValidateNotNull(participantId, "participantId");
|
||||
JPakeUtilities.ValidateNotNull(a, "a");
|
||||
JPakeUtilities.ValidateNotNull(knowledgeProofForX2s, "knowledgeProofForX2s");
|
||||
this.participantId = participantId;
|
||||
this.a = a;
|
||||
this.knowledgeProofForX2s = new BigInteger[knowledgeProofForX2s.Length];
|
||||
knowledgeProofForX2s.CopyTo(this.knowledgeProofForX2s, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public class JPakeRound3Payload
|
||||
{
|
||||
private readonly string participantId;
|
||||
|
||||
private readonly BigInteger macTag;
|
||||
|
||||
public virtual string ParticipantId => participantId;
|
||||
|
||||
public virtual BigInteger MacTag => macTag;
|
||||
|
||||
public JPakeRound3Payload(string participantId, BigInteger magTag)
|
||||
{
|
||||
this.participantId = participantId;
|
||||
macTag = magTag;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.JPake;
|
||||
|
||||
public abstract class JPakeUtilities
|
||||
{
|
||||
public static readonly BigInteger Zero = BigInteger.Zero;
|
||||
|
||||
public static readonly BigInteger One = BigInteger.One;
|
||||
|
||||
public static BigInteger GenerateX1(BigInteger q, SecureRandom random)
|
||||
{
|
||||
BigInteger zero = Zero;
|
||||
BigInteger max = q.Subtract(One);
|
||||
return BigIntegers.CreateRandomInRange(zero, max, random);
|
||||
}
|
||||
|
||||
public static BigInteger GenerateX2(BigInteger q, SecureRandom random)
|
||||
{
|
||||
BigInteger one = One;
|
||||
BigInteger max = q.Subtract(One);
|
||||
return BigIntegers.CreateRandomInRange(one, max, random);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateS(char[] password)
|
||||
{
|
||||
return new BigInteger(Encoding.UTF8.GetBytes(password));
|
||||
}
|
||||
|
||||
public static BigInteger CalculateGx(BigInteger p, BigInteger g, BigInteger x)
|
||||
{
|
||||
return g.ModPow(x, p);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateGA(BigInteger p, BigInteger gx1, BigInteger gx3, BigInteger gx4)
|
||||
{
|
||||
return gx1.Multiply(gx3).Multiply(gx4).Mod(p);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateX2s(BigInteger q, BigInteger x2, BigInteger s)
|
||||
{
|
||||
return x2.Multiply(s).Mod(q);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateA(BigInteger p, BigInteger q, BigInteger gA, BigInteger x2s)
|
||||
{
|
||||
return gA.ModPow(x2s, p);
|
||||
}
|
||||
|
||||
public static BigInteger[] CalculateZeroKnowledgeProof(BigInteger p, BigInteger q, BigInteger g, BigInteger gx, BigInteger x, string participantId, IDigest digest, SecureRandom random)
|
||||
{
|
||||
BigInteger zero = Zero;
|
||||
BigInteger max = q.Subtract(One);
|
||||
BigInteger bigInteger = BigIntegers.CreateRandomInRange(zero, max, random);
|
||||
BigInteger bigInteger2 = g.ModPow(bigInteger, p);
|
||||
BigInteger val = CalculateHashForZeroKnowledgeProof(g, bigInteger2, gx, participantId, digest);
|
||||
return new BigInteger[2]
|
||||
{
|
||||
bigInteger2,
|
||||
bigInteger.Subtract(x.Multiply(val)).Mod(q)
|
||||
};
|
||||
}
|
||||
|
||||
private static BigInteger CalculateHashForZeroKnowledgeProof(BigInteger g, BigInteger gr, BigInteger gx, string participantId, IDigest digest)
|
||||
{
|
||||
digest.Reset();
|
||||
UpdateDigestIncludingSize(digest, g);
|
||||
UpdateDigestIncludingSize(digest, gr);
|
||||
UpdateDigestIncludingSize(digest, gx);
|
||||
UpdateDigestIncludingSize(digest, participantId);
|
||||
byte[] bytes = DigestUtilities.DoFinal(digest);
|
||||
return new BigInteger(bytes);
|
||||
}
|
||||
|
||||
public static void ValidateGx4(BigInteger gx4)
|
||||
{
|
||||
if (gx4.Equals(One))
|
||||
{
|
||||
throw new CryptoException("g^x validation failed. g^x should not be 1.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ValidateGa(BigInteger ga)
|
||||
{
|
||||
if (ga.Equals(One))
|
||||
{
|
||||
throw new CryptoException("ga is equal to 1. It should not be. The chances of this happening are on the order of 2^160 for a 160-bit q. Try again.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ValidateZeroKnowledgeProof(BigInteger p, BigInteger q, BigInteger g, BigInteger gx, BigInteger[] zeroKnowledgeProof, string participantId, IDigest digest)
|
||||
{
|
||||
BigInteger bigInteger = zeroKnowledgeProof[0];
|
||||
BigInteger e = zeroKnowledgeProof[1];
|
||||
BigInteger e2 = CalculateHashForZeroKnowledgeProof(g, bigInteger, gx, participantId, digest);
|
||||
if (gx.CompareTo(Zero) != 1 || gx.CompareTo(p) != -1 || gx.ModPow(q, p).CompareTo(One) != 0 || g.ModPow(e, p).Multiply(gx.ModPow(e2, p)).Mod(p)
|
||||
.CompareTo(bigInteger) != 0)
|
||||
{
|
||||
throw new CryptoException("Zero-knowledge proof validation failed");
|
||||
}
|
||||
}
|
||||
|
||||
public static BigInteger CalculateKeyingMaterial(BigInteger p, BigInteger q, BigInteger gx4, BigInteger x2, BigInteger s, BigInteger B)
|
||||
{
|
||||
return gx4.ModPow(x2.Multiply(s).Negate().Mod(q), p).Multiply(B).ModPow(x2, p);
|
||||
}
|
||||
|
||||
public static void ValidateParticipantIdsDiffer(string participantId1, string participantId2)
|
||||
{
|
||||
if (participantId1.Equals(participantId2))
|
||||
{
|
||||
throw new CryptoException("Both participants are using the same participantId (" + participantId1 + "). This is not allowed. Each participant must use a unique participantId.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ValidateParticipantIdsEqual(string expectedParticipantId, string actualParticipantId)
|
||||
{
|
||||
if (!expectedParticipantId.Equals(actualParticipantId))
|
||||
{
|
||||
throw new CryptoException("Received payload from incorrect partner (" + actualParticipantId + "). Expected to receive payload from " + expectedParticipantId + ".");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ValidateNotNull(object obj, string description)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException(description);
|
||||
}
|
||||
}
|
||||
|
||||
public static BigInteger CalculateMacTag(string participantId, string partnerParticipantId, BigInteger gx1, BigInteger gx2, BigInteger gx3, BigInteger gx4, BigInteger keyingMaterial, IDigest digest)
|
||||
{
|
||||
byte[] array = CalculateMacKey(keyingMaterial, digest);
|
||||
HMac hMac = new HMac(digest);
|
||||
hMac.Init(new KeyParameter(array));
|
||||
Arrays.Fill(array, 0);
|
||||
UpdateMac(hMac, "KC_1_U");
|
||||
UpdateMac(hMac, participantId);
|
||||
UpdateMac(hMac, partnerParticipantId);
|
||||
UpdateMac(hMac, gx1);
|
||||
UpdateMac(hMac, gx2);
|
||||
UpdateMac(hMac, gx3);
|
||||
UpdateMac(hMac, gx4);
|
||||
byte[] bytes = MacUtilities.DoFinal(hMac);
|
||||
return new BigInteger(bytes);
|
||||
}
|
||||
|
||||
private static byte[] CalculateMacKey(BigInteger keyingMaterial, IDigest digest)
|
||||
{
|
||||
digest.Reset();
|
||||
UpdateDigest(digest, keyingMaterial);
|
||||
UpdateDigest(digest, "JPAKE_KC");
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
public static void ValidateMacTag(string participantId, string partnerParticipantId, BigInteger gx1, BigInteger gx2, BigInteger gx3, BigInteger gx4, BigInteger keyingMaterial, IDigest digest, BigInteger partnerMacTag)
|
||||
{
|
||||
BigInteger bigInteger = CalculateMacTag(partnerParticipantId, participantId, gx3, gx4, gx1, gx2, keyingMaterial, digest);
|
||||
if (!bigInteger.Equals(partnerMacTag))
|
||||
{
|
||||
throw new CryptoException("Partner MacTag validation failed. Therefore, the password, MAC, or digest algorithm of each participant does not match.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateDigest(IDigest digest, BigInteger bigInteger)
|
||||
{
|
||||
UpdateDigest(digest, BigIntegers.AsUnsignedByteArray(bigInteger));
|
||||
}
|
||||
|
||||
private static void UpdateDigest(IDigest digest, string str)
|
||||
{
|
||||
UpdateDigest(digest, Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static void UpdateDigest(IDigest digest, byte[] bytes)
|
||||
{
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
Arrays.Fill(bytes, 0);
|
||||
}
|
||||
|
||||
private static void UpdateDigestIncludingSize(IDigest digest, BigInteger bigInteger)
|
||||
{
|
||||
UpdateDigestIncludingSize(digest, BigIntegers.AsUnsignedByteArray(bigInteger));
|
||||
}
|
||||
|
||||
private static void UpdateDigestIncludingSize(IDigest digest, string str)
|
||||
{
|
||||
UpdateDigestIncludingSize(digest, Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static void UpdateDigestIncludingSize(IDigest digest, byte[] bytes)
|
||||
{
|
||||
digest.BlockUpdate(IntToByteArray(bytes.Length), 0, 4);
|
||||
digest.BlockUpdate(bytes, 0, bytes.Length);
|
||||
Arrays.Fill(bytes, 0);
|
||||
}
|
||||
|
||||
private static void UpdateMac(IMac mac, BigInteger bigInteger)
|
||||
{
|
||||
UpdateMac(mac, BigIntegers.AsUnsignedByteArray(bigInteger));
|
||||
}
|
||||
|
||||
private static void UpdateMac(IMac mac, string str)
|
||||
{
|
||||
UpdateMac(mac, Encoding.UTF8.GetBytes(str));
|
||||
}
|
||||
|
||||
private static void UpdateMac(IMac mac, byte[] bytes)
|
||||
{
|
||||
mac.BlockUpdate(bytes, 0, bytes.Length);
|
||||
Arrays.Fill(bytes, 0);
|
||||
}
|
||||
|
||||
private static byte[] IntToByteArray(int value)
|
||||
{
|
||||
return Pack.UInt32_To_BE((uint)value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
|
||||
public class ConcatenationKdfGenerator : IDerivationFunction
|
||||
{
|
||||
private readonly IDigest mDigest;
|
||||
|
||||
private byte[] mShared;
|
||||
|
||||
private byte[] mOtherInfo;
|
||||
|
||||
private int mHLen;
|
||||
|
||||
public virtual IDigest Digest => mDigest;
|
||||
|
||||
public ConcatenationKdfGenerator(IDigest digest)
|
||||
{
|
||||
mDigest = digest;
|
||||
mHLen = digest.GetDigestSize();
|
||||
}
|
||||
|
||||
public virtual void Init(IDerivationParameters param)
|
||||
{
|
||||
if (!(param is KdfParameters))
|
||||
{
|
||||
throw new ArgumentException("KDF parameters required for ConcatenationKdfGenerator");
|
||||
}
|
||||
KdfParameters kdfParameters = (KdfParameters)param;
|
||||
mShared = kdfParameters.GetSharedSecret();
|
||||
mOtherInfo = kdfParameters.GetIV();
|
||||
}
|
||||
|
||||
public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
|
||||
{
|
||||
if (outBytes.Length - len < outOff)
|
||||
{
|
||||
throw new DataLengthException("output buffer too small");
|
||||
}
|
||||
byte[] array = new byte[mHLen];
|
||||
byte[] array2 = new byte[4];
|
||||
uint n = 1u;
|
||||
int num = 0;
|
||||
mDigest.Reset();
|
||||
if (len > mHLen)
|
||||
{
|
||||
do
|
||||
{
|
||||
Pack.UInt32_To_BE(n, array2);
|
||||
mDigest.BlockUpdate(array2, 0, array2.Length);
|
||||
mDigest.BlockUpdate(mShared, 0, mShared.Length);
|
||||
mDigest.BlockUpdate(mOtherInfo, 0, mOtherInfo.Length);
|
||||
mDigest.DoFinal(array, 0);
|
||||
Array.Copy(array, 0, outBytes, outOff + num, mHLen);
|
||||
num += mHLen;
|
||||
}
|
||||
while (n++ < len / mHLen);
|
||||
}
|
||||
if (num < len)
|
||||
{
|
||||
Pack.UInt32_To_BE(n, array2);
|
||||
mDigest.BlockUpdate(array2, 0, array2.Length);
|
||||
mDigest.BlockUpdate(mShared, 0, mShared.Length);
|
||||
mDigest.BlockUpdate(mOtherInfo, 0, mOtherInfo.Length);
|
||||
mDigest.DoFinal(array, 0);
|
||||
Array.Copy(array, 0, outBytes, outOff + num, len - num);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Org.BouncyCastle.Asn1;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
|
||||
public class DHKdfParameters : IDerivationParameters
|
||||
{
|
||||
private readonly DerObjectIdentifier algorithm;
|
||||
|
||||
private readonly int keySize;
|
||||
|
||||
private readonly byte[] z;
|
||||
|
||||
private readonly byte[] extraInfo;
|
||||
|
||||
public DerObjectIdentifier Algorithm => algorithm;
|
||||
|
||||
public int KeySize => keySize;
|
||||
|
||||
public DHKdfParameters(DerObjectIdentifier algorithm, int keySize, byte[] z)
|
||||
: this(algorithm, keySize, z, null)
|
||||
{
|
||||
}
|
||||
|
||||
public DHKdfParameters(DerObjectIdentifier algorithm, int keySize, byte[] z, byte[] extraInfo)
|
||||
{
|
||||
this.algorithm = algorithm;
|
||||
this.keySize = keySize;
|
||||
this.z = z;
|
||||
this.extraInfo = extraInfo;
|
||||
}
|
||||
|
||||
public byte[] GetZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
public byte[] GetExtraInfo()
|
||||
{
|
||||
return extraInfo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
|
||||
public class DHKekGenerator : IDerivationFunction
|
||||
{
|
||||
private readonly IDigest digest;
|
||||
|
||||
private DerObjectIdentifier algorithm;
|
||||
|
||||
private int keySize;
|
||||
|
||||
private byte[] z;
|
||||
|
||||
private byte[] partyAInfo;
|
||||
|
||||
public virtual IDigest Digest => digest;
|
||||
|
||||
public DHKekGenerator(IDigest digest)
|
||||
{
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(IDerivationParameters param)
|
||||
{
|
||||
DHKdfParameters dHKdfParameters = (DHKdfParameters)param;
|
||||
algorithm = dHKdfParameters.Algorithm;
|
||||
keySize = dHKdfParameters.KeySize;
|
||||
z = dHKdfParameters.GetZ();
|
||||
partyAInfo = dHKdfParameters.GetExtraInfo();
|
||||
}
|
||||
|
||||
public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
|
||||
{
|
||||
if (outBytes.Length - len < outOff)
|
||||
{
|
||||
throw new DataLengthException("output buffer too small");
|
||||
}
|
||||
long num = len;
|
||||
int digestSize = digest.GetDigestSize();
|
||||
if (num > 8589934591L)
|
||||
{
|
||||
throw new ArgumentException("Output length too large");
|
||||
}
|
||||
int num2 = (int)((num + digestSize - 1) / digestSize);
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
uint num3 = 1u;
|
||||
for (int i = 0; i < num2; i++)
|
||||
{
|
||||
digest.BlockUpdate(z, 0, z.Length);
|
||||
DerSequence derSequence = new DerSequence(algorithm, new DerOctetString(Pack.UInt32_To_BE(num3)));
|
||||
Asn1EncodableVector asn1EncodableVector = new Asn1EncodableVector(derSequence);
|
||||
if (partyAInfo != null)
|
||||
{
|
||||
asn1EncodableVector.Add(new DerTaggedObject(explicitly: true, 0, new DerOctetString(partyAInfo)));
|
||||
}
|
||||
asn1EncodableVector.Add(new DerTaggedObject(explicitly: true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
|
||||
byte[] derEncoded = new DerSequence(asn1EncodableVector).GetDerEncoded();
|
||||
digest.BlockUpdate(derEncoded, 0, derEncoded.Length);
|
||||
digest.DoFinal(array, 0);
|
||||
if (len > digestSize)
|
||||
{
|
||||
Array.Copy(array, 0, outBytes, outOff, digestSize);
|
||||
outOff += digestSize;
|
||||
len -= digestSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(array, 0, outBytes, outOff, len);
|
||||
}
|
||||
num3++;
|
||||
}
|
||||
digest.Reset();
|
||||
return (int)num;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using Org.BouncyCastle.Asn1;
|
||||
using Org.BouncyCastle.Asn1.X509;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Kdf;
|
||||
|
||||
public class ECDHKekGenerator : IDerivationFunction
|
||||
{
|
||||
private readonly IDerivationFunction kdf;
|
||||
|
||||
private DerObjectIdentifier algorithm;
|
||||
|
||||
private int keySize;
|
||||
|
||||
private byte[] z;
|
||||
|
||||
public virtual IDigest Digest => kdf.Digest;
|
||||
|
||||
public ECDHKekGenerator(IDigest digest)
|
||||
{
|
||||
kdf = new Kdf2BytesGenerator(digest);
|
||||
}
|
||||
|
||||
public virtual void Init(IDerivationParameters param)
|
||||
{
|
||||
DHKdfParameters dHKdfParameters = (DHKdfParameters)param;
|
||||
algorithm = dHKdfParameters.Algorithm;
|
||||
keySize = dHKdfParameters.KeySize;
|
||||
z = dHKdfParameters.GetZ();
|
||||
}
|
||||
|
||||
public virtual int GenerateBytes(byte[] outBytes, int outOff, int len)
|
||||
{
|
||||
DerSequence derSequence = new DerSequence(new AlgorithmIdentifier(algorithm, DerNull.Instance), new DerTaggedObject(explicitly: true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
|
||||
kdf.Init(new KdfParameters(z, derSequence.GetDerEncoded()));
|
||||
return kdf.GenerateBytes(outBytes, outOff, len);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Utilities;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Math.EC;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public class SM2KeyExchange
|
||||
{
|
||||
private readonly IDigest mDigest;
|
||||
|
||||
private byte[] mUserID;
|
||||
|
||||
private ECPrivateKeyParameters mStaticKey;
|
||||
|
||||
private ECPoint mStaticPubPoint;
|
||||
|
||||
private ECPoint mEphemeralPubPoint;
|
||||
|
||||
private ECDomainParameters mECParams;
|
||||
|
||||
private int mW;
|
||||
|
||||
private ECPrivateKeyParameters mEphemeralKey;
|
||||
|
||||
private bool mInitiator;
|
||||
|
||||
public SM2KeyExchange()
|
||||
: this(new SM3Digest())
|
||||
{
|
||||
}
|
||||
|
||||
public SM2KeyExchange(IDigest digest)
|
||||
{
|
||||
mDigest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(ICipherParameters privParam)
|
||||
{
|
||||
SM2KeyExchangePrivateParameters sM2KeyExchangePrivateParameters;
|
||||
if (privParam is ParametersWithID)
|
||||
{
|
||||
sM2KeyExchangePrivateParameters = (SM2KeyExchangePrivateParameters)((ParametersWithID)privParam).Parameters;
|
||||
mUserID = ((ParametersWithID)privParam).GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
sM2KeyExchangePrivateParameters = (SM2KeyExchangePrivateParameters)privParam;
|
||||
mUserID = new byte[0];
|
||||
}
|
||||
mInitiator = sM2KeyExchangePrivateParameters.IsInitiator;
|
||||
mStaticKey = sM2KeyExchangePrivateParameters.StaticPrivateKey;
|
||||
mEphemeralKey = sM2KeyExchangePrivateParameters.EphemeralPrivateKey;
|
||||
mECParams = mStaticKey.Parameters;
|
||||
mStaticPubPoint = sM2KeyExchangePrivateParameters.StaticPublicPoint;
|
||||
mEphemeralPubPoint = sM2KeyExchangePrivateParameters.EphemeralPublicPoint;
|
||||
mW = mECParams.Curve.FieldSize / 2 - 1;
|
||||
}
|
||||
|
||||
public virtual byte[] CalculateKey(int kLen, ICipherParameters pubParam)
|
||||
{
|
||||
SM2KeyExchangePublicParameters sM2KeyExchangePublicParameters;
|
||||
byte[] userID;
|
||||
if (pubParam is ParametersWithID)
|
||||
{
|
||||
sM2KeyExchangePublicParameters = (SM2KeyExchangePublicParameters)((ParametersWithID)pubParam).Parameters;
|
||||
userID = ((ParametersWithID)pubParam).GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
sM2KeyExchangePublicParameters = (SM2KeyExchangePublicParameters)pubParam;
|
||||
userID = new byte[0];
|
||||
}
|
||||
byte[] z = GetZ(mDigest, mUserID, mStaticPubPoint);
|
||||
byte[] z2 = GetZ(mDigest, userID, sM2KeyExchangePublicParameters.StaticPublicKey.Q);
|
||||
ECPoint u = CalculateU(sM2KeyExchangePublicParameters);
|
||||
if (mInitiator)
|
||||
{
|
||||
return Kdf(u, z, z2, kLen);
|
||||
}
|
||||
return Kdf(u, z2, z, kLen);
|
||||
}
|
||||
|
||||
public virtual byte[][] CalculateKeyWithConfirmation(int kLen, byte[] confirmationTag, ICipherParameters pubParam)
|
||||
{
|
||||
SM2KeyExchangePublicParameters sM2KeyExchangePublicParameters;
|
||||
byte[] userID;
|
||||
if (pubParam is ParametersWithID)
|
||||
{
|
||||
sM2KeyExchangePublicParameters = (SM2KeyExchangePublicParameters)((ParametersWithID)pubParam).Parameters;
|
||||
userID = ((ParametersWithID)pubParam).GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
sM2KeyExchangePublicParameters = (SM2KeyExchangePublicParameters)pubParam;
|
||||
userID = new byte[0];
|
||||
}
|
||||
if (mInitiator && confirmationTag == null)
|
||||
{
|
||||
throw new ArgumentException("if initiating, confirmationTag must be set");
|
||||
}
|
||||
byte[] z = GetZ(mDigest, mUserID, mStaticPubPoint);
|
||||
byte[] z2 = GetZ(mDigest, userID, sM2KeyExchangePublicParameters.StaticPublicKey.Q);
|
||||
ECPoint u = CalculateU(sM2KeyExchangePublicParameters);
|
||||
byte[] array;
|
||||
if (mInitiator)
|
||||
{
|
||||
array = Kdf(u, z, z2, kLen);
|
||||
byte[] inner = CalculateInnerHash(mDigest, u, z, z2, mEphemeralPubPoint, sM2KeyExchangePublicParameters.EphemeralPublicKey.Q);
|
||||
byte[] a = S1(mDigest, u, inner);
|
||||
if (!Arrays.ConstantTimeAreEqual(a, confirmationTag))
|
||||
{
|
||||
throw new InvalidOperationException("confirmation tag mismatch");
|
||||
}
|
||||
return new byte[2][]
|
||||
{
|
||||
array,
|
||||
S2(mDigest, u, inner)
|
||||
};
|
||||
}
|
||||
array = Kdf(u, z2, z, kLen);
|
||||
byte[] inner2 = CalculateInnerHash(mDigest, u, z2, z, sM2KeyExchangePublicParameters.EphemeralPublicKey.Q, mEphemeralPubPoint);
|
||||
return new byte[3][]
|
||||
{
|
||||
array,
|
||||
S1(mDigest, u, inner2),
|
||||
S2(mDigest, u, inner2)
|
||||
};
|
||||
}
|
||||
|
||||
protected virtual ECPoint CalculateU(SM2KeyExchangePublicParameters otherPub)
|
||||
{
|
||||
ECDomainParameters parameters = mStaticKey.Parameters;
|
||||
ECPoint p = ECAlgorithms.CleanPoint(parameters.Curve, otherPub.StaticPublicKey.Q);
|
||||
ECPoint eCPoint = ECAlgorithms.CleanPoint(parameters.Curve, otherPub.EphemeralPublicKey.Q);
|
||||
BigInteger bigInteger = Reduce(mEphemeralPubPoint.AffineXCoord.ToBigInteger());
|
||||
BigInteger val = Reduce(eCPoint.AffineXCoord.ToBigInteger());
|
||||
BigInteger val2 = mStaticKey.D.Add(bigInteger.Multiply(mEphemeralKey.D));
|
||||
BigInteger bigInteger2 = mECParams.H.Multiply(val2).Mod(mECParams.N);
|
||||
BigInteger b = bigInteger2.Multiply(val).Mod(mECParams.N);
|
||||
return ECAlgorithms.SumOfTwoMultiplies(p, bigInteger2, eCPoint, b).Normalize();
|
||||
}
|
||||
|
||||
protected virtual byte[] Kdf(ECPoint u, byte[] za, byte[] zb, int klen)
|
||||
{
|
||||
int digestSize = mDigest.GetDigestSize();
|
||||
byte[] array = new byte[System.Math.Max(4, digestSize)];
|
||||
byte[] array2 = new byte[(klen + 7) / 8];
|
||||
int i = 0;
|
||||
IMemoable memoable = mDigest as IMemoable;
|
||||
IMemoable other = null;
|
||||
if (memoable != null)
|
||||
{
|
||||
AddFieldElement(mDigest, u.AffineXCoord);
|
||||
AddFieldElement(mDigest, u.AffineYCoord);
|
||||
mDigest.BlockUpdate(za, 0, za.Length);
|
||||
mDigest.BlockUpdate(zb, 0, zb.Length);
|
||||
other = memoable.Copy();
|
||||
}
|
||||
uint num = 0u;
|
||||
int num2;
|
||||
for (; i < array2.Length; i += num2)
|
||||
{
|
||||
if (memoable != null)
|
||||
{
|
||||
memoable.Reset(other);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddFieldElement(mDigest, u.AffineXCoord);
|
||||
AddFieldElement(mDigest, u.AffineYCoord);
|
||||
mDigest.BlockUpdate(za, 0, za.Length);
|
||||
mDigest.BlockUpdate(zb, 0, zb.Length);
|
||||
}
|
||||
Pack.UInt32_To_BE(++num, array, 0);
|
||||
mDigest.BlockUpdate(array, 0, 4);
|
||||
mDigest.DoFinal(array, 0);
|
||||
num2 = System.Math.Min(digestSize, array2.Length - i);
|
||||
Array.Copy(array, 0, array2, i, num2);
|
||||
}
|
||||
return array2;
|
||||
}
|
||||
|
||||
private BigInteger Reduce(BigInteger x)
|
||||
{
|
||||
return x.And(BigInteger.One.ShiftLeft(mW).Subtract(BigInteger.One)).SetBit(mW);
|
||||
}
|
||||
|
||||
private byte[] S1(IDigest digest, ECPoint u, byte[] inner)
|
||||
{
|
||||
digest.Update(2);
|
||||
AddFieldElement(digest, u.AffineYCoord);
|
||||
digest.BlockUpdate(inner, 0, inner.Length);
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private byte[] CalculateInnerHash(IDigest digest, ECPoint u, byte[] za, byte[] zb, ECPoint p1, ECPoint p2)
|
||||
{
|
||||
AddFieldElement(digest, u.AffineXCoord);
|
||||
digest.BlockUpdate(za, 0, za.Length);
|
||||
digest.BlockUpdate(zb, 0, zb.Length);
|
||||
AddFieldElement(digest, p1.AffineXCoord);
|
||||
AddFieldElement(digest, p1.AffineYCoord);
|
||||
AddFieldElement(digest, p2.AffineXCoord);
|
||||
AddFieldElement(digest, p2.AffineYCoord);
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private byte[] S2(IDigest digest, ECPoint u, byte[] inner)
|
||||
{
|
||||
digest.Update(3);
|
||||
AddFieldElement(digest, u.AffineYCoord);
|
||||
digest.BlockUpdate(inner, 0, inner.Length);
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private byte[] GetZ(IDigest digest, byte[] userID, ECPoint pubPoint)
|
||||
{
|
||||
AddUserID(digest, userID);
|
||||
AddFieldElement(digest, mECParams.Curve.A);
|
||||
AddFieldElement(digest, mECParams.Curve.B);
|
||||
AddFieldElement(digest, mECParams.G.AffineXCoord);
|
||||
AddFieldElement(digest, mECParams.G.AffineYCoord);
|
||||
AddFieldElement(digest, pubPoint.AffineXCoord);
|
||||
AddFieldElement(digest, pubPoint.AffineYCoord);
|
||||
return DigestUtilities.DoFinal(digest);
|
||||
}
|
||||
|
||||
private void AddUserID(IDigest digest, byte[] userID)
|
||||
{
|
||||
uint num = (uint)(userID.Length * 8);
|
||||
digest.Update((byte)(num >> 8));
|
||||
digest.Update((byte)num);
|
||||
digest.BlockUpdate(userID, 0, userID.Length);
|
||||
}
|
||||
|
||||
private void AddFieldElement(IDigest digest, ECFieldElement v)
|
||||
{
|
||||
byte[] encoded = v.GetEncoded();
|
||||
digest.BlockUpdate(encoded, 0, encoded.Length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
|
||||
public class Srp6Client
|
||||
{
|
||||
protected BigInteger N;
|
||||
|
||||
protected BigInteger g;
|
||||
|
||||
protected BigInteger privA;
|
||||
|
||||
protected BigInteger pubA;
|
||||
|
||||
protected BigInteger B;
|
||||
|
||||
protected BigInteger x;
|
||||
|
||||
protected BigInteger u;
|
||||
|
||||
protected BigInteger S;
|
||||
|
||||
protected BigInteger M1;
|
||||
|
||||
protected BigInteger M2;
|
||||
|
||||
protected BigInteger Key;
|
||||
|
||||
protected IDigest digest;
|
||||
|
||||
protected SecureRandom random;
|
||||
|
||||
public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
|
||||
{
|
||||
this.N = N;
|
||||
this.g = g;
|
||||
this.digest = digest;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
public virtual void Init(Srp6GroupParameters group, IDigest digest, SecureRandom random)
|
||||
{
|
||||
Init(group.N, group.G, digest, random);
|
||||
}
|
||||
|
||||
public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password)
|
||||
{
|
||||
x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
|
||||
privA = SelectPrivateValue();
|
||||
pubA = g.ModPow(privA, N);
|
||||
return pubA;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateSecret(BigInteger serverB)
|
||||
{
|
||||
B = Srp6Utilities.ValidatePublicValue(N, serverB);
|
||||
u = Srp6Utilities.CalculateU(digest, N, pubA, B);
|
||||
S = CalculateS();
|
||||
return S;
|
||||
}
|
||||
|
||||
protected virtual BigInteger SelectPrivateValue()
|
||||
{
|
||||
return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
|
||||
}
|
||||
|
||||
private BigInteger CalculateS()
|
||||
{
|
||||
BigInteger val = Srp6Utilities.CalculateK(digest, N, g);
|
||||
BigInteger e = u.Multiply(x).Add(privA);
|
||||
BigInteger n = g.ModPow(x, N).Multiply(val).Mod(N);
|
||||
return B.Subtract(n).Mod(N).ModPow(e, N);
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateClientEvidenceMessage()
|
||||
{
|
||||
if (pubA == null || B == null || S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute M1: some data are missing from the previous operations (A,B,S)");
|
||||
}
|
||||
M1 = Srp6Utilities.CalculateM1(digest, N, pubA, B, S);
|
||||
return M1;
|
||||
}
|
||||
|
||||
public virtual bool VerifyServerEvidenceMessage(BigInteger serverM2)
|
||||
{
|
||||
if (pubA == null || M1 == null || S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute and verify M2: some data are missing from the previous operations (A,M1,S)");
|
||||
}
|
||||
BigInteger bigInteger = Srp6Utilities.CalculateM2(digest, N, pubA, M1, S);
|
||||
if (bigInteger.Equals(serverM2))
|
||||
{
|
||||
M2 = serverM2;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateSessionKey()
|
||||
{
|
||||
if (S == null || M1 == null || M2 == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute Key: some data are missing from the previous operations (S,M1,M2)");
|
||||
}
|
||||
Key = Srp6Utilities.CalculateKey(digest, N, S);
|
||||
return Key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
|
||||
public class Srp6Server
|
||||
{
|
||||
protected BigInteger N;
|
||||
|
||||
protected BigInteger g;
|
||||
|
||||
protected BigInteger v;
|
||||
|
||||
protected SecureRandom random;
|
||||
|
||||
protected IDigest digest;
|
||||
|
||||
protected BigInteger A;
|
||||
|
||||
protected BigInteger privB;
|
||||
|
||||
protected BigInteger pubB;
|
||||
|
||||
protected BigInteger u;
|
||||
|
||||
protected BigInteger S;
|
||||
|
||||
protected BigInteger M1;
|
||||
|
||||
protected BigInteger M2;
|
||||
|
||||
protected BigInteger Key;
|
||||
|
||||
public virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest digest, SecureRandom random)
|
||||
{
|
||||
this.N = N;
|
||||
this.g = g;
|
||||
this.v = v;
|
||||
this.random = random;
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(Srp6GroupParameters group, BigInteger v, IDigest digest, SecureRandom random)
|
||||
{
|
||||
Init(group.N, group.G, v, digest, random);
|
||||
}
|
||||
|
||||
public virtual BigInteger GenerateServerCredentials()
|
||||
{
|
||||
BigInteger bigInteger = Srp6Utilities.CalculateK(digest, N, g);
|
||||
privB = SelectPrivateValue();
|
||||
pubB = bigInteger.Multiply(v).Mod(N).Add(g.ModPow(privB, N))
|
||||
.Mod(N);
|
||||
return pubB;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateSecret(BigInteger clientA)
|
||||
{
|
||||
A = Srp6Utilities.ValidatePublicValue(N, clientA);
|
||||
u = Srp6Utilities.CalculateU(digest, N, A, pubB);
|
||||
S = CalculateS();
|
||||
return S;
|
||||
}
|
||||
|
||||
protected virtual BigInteger SelectPrivateValue()
|
||||
{
|
||||
return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
|
||||
}
|
||||
|
||||
private BigInteger CalculateS()
|
||||
{
|
||||
return v.ModPow(u, N).Multiply(A).Mod(N)
|
||||
.ModPow(privB, N);
|
||||
}
|
||||
|
||||
public virtual bool VerifyClientEvidenceMessage(BigInteger clientM1)
|
||||
{
|
||||
if (A == null || pubB == null || S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute and verify M1: some data are missing from the previous operations (A,B,S)");
|
||||
}
|
||||
BigInteger bigInteger = Srp6Utilities.CalculateM1(digest, N, A, pubB, S);
|
||||
if (bigInteger.Equals(clientM1))
|
||||
{
|
||||
M1 = clientM1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateServerEvidenceMessage()
|
||||
{
|
||||
if (A == null || M1 == null || S == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute M2: some data are missing from the previous operations (A,M1,S)");
|
||||
}
|
||||
M2 = Srp6Utilities.CalculateM2(digest, N, A, M1, S);
|
||||
return M2;
|
||||
}
|
||||
|
||||
public virtual BigInteger CalculateSessionKey()
|
||||
{
|
||||
if (S == null || M1 == null || M2 == null)
|
||||
{
|
||||
throw new CryptoException("Impossible to compute Key: some data are missing from the previous operations (S,M1,M2)");
|
||||
}
|
||||
Key = Srp6Utilities.CalculateKey(digest, N, S);
|
||||
return Key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Utilities.Encoders;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
|
||||
public class Srp6StandardGroups
|
||||
{
|
||||
private const string rfc5054_1024_N = "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3";
|
||||
|
||||
private const string rfc5054_1024_g = "02";
|
||||
|
||||
private const string rfc5054_1536_N = "9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB";
|
||||
|
||||
private const string rfc5054_1536_g = "02";
|
||||
|
||||
private const string rfc5054_2048_N = "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73";
|
||||
|
||||
private const string rfc5054_2048_g = "02";
|
||||
|
||||
private const string rfc5054_3072_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
|
||||
|
||||
private const string rfc5054_3072_g = "05";
|
||||
|
||||
private const string rfc5054_4096_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF";
|
||||
|
||||
private const string rfc5054_4096_g = "05";
|
||||
|
||||
private const string rfc5054_6144_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF";
|
||||
|
||||
private const string rfc5054_6144_g = "05";
|
||||
|
||||
private const string rfc5054_8192_N = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF";
|
||||
|
||||
private const string rfc5054_8192_g = "13";
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_1024 = FromNG("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3", "02");
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_1536 = FromNG("9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB", "02");
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_2048 = FromNG("AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF6095179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B9078717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB3786160279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DBFBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73", "02");
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_3072 = FromNG("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", "05");
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_4096 = FromNG("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", "05");
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_6144 = FromNG("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF", "05");
|
||||
|
||||
public static readonly Srp6GroupParameters rfc5054_8192 = FromNG("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF", "13");
|
||||
|
||||
private static BigInteger FromHex(string hex)
|
||||
{
|
||||
return new BigInteger(1, Hex.Decode(hex));
|
||||
}
|
||||
|
||||
private static Srp6GroupParameters FromNG(string hexN, string hexG)
|
||||
{
|
||||
return new Srp6GroupParameters(FromHex(hexN), FromHex(hexG));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using System;
|
||||
using Org.BouncyCastle.Math;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Utilities;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
|
||||
public class Srp6Utilities
|
||||
{
|
||||
public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g)
|
||||
{
|
||||
return HashPaddedPair(digest, N, N, g);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B)
|
||||
{
|
||||
return HashPaddedPair(digest, N, A, B);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
|
||||
{
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
digest.BlockUpdate(identity, 0, identity.Length);
|
||||
digest.Update(58);
|
||||
digest.BlockUpdate(password, 0, password.Length);
|
||||
digest.DoFinal(array, 0);
|
||||
digest.BlockUpdate(salt, 0, salt.Length);
|
||||
digest.BlockUpdate(array, 0, array.Length);
|
||||
digest.DoFinal(array, 0);
|
||||
return new BigInteger(1, array);
|
||||
}
|
||||
|
||||
public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random)
|
||||
{
|
||||
int num = System.Math.Min(256, N.BitLength / 2);
|
||||
BigInteger min = BigInteger.One.ShiftLeft(num - 1);
|
||||
BigInteger max = N.Subtract(BigInteger.One);
|
||||
return BigIntegers.CreateRandomInRange(min, max, random);
|
||||
}
|
||||
|
||||
public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val)
|
||||
{
|
||||
val = val.Mod(N);
|
||||
if (val.Equals(BigInteger.Zero))
|
||||
{
|
||||
throw new CryptoException("Invalid public value: 0");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
public static BigInteger CalculateM1(IDigest digest, BigInteger N, BigInteger A, BigInteger B, BigInteger S)
|
||||
{
|
||||
return HashPaddedTriplet(digest, N, A, B, S);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateM2(IDigest digest, BigInteger N, BigInteger A, BigInteger M1, BigInteger S)
|
||||
{
|
||||
return HashPaddedTriplet(digest, N, A, M1, S);
|
||||
}
|
||||
|
||||
public static BigInteger CalculateKey(IDigest digest, BigInteger N, BigInteger S)
|
||||
{
|
||||
int length = (N.BitLength + 7) / 8;
|
||||
byte[] padded = GetPadded(S, length);
|
||||
digest.BlockUpdate(padded, 0, padded.Length);
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
digest.DoFinal(array, 0);
|
||||
return new BigInteger(1, array);
|
||||
}
|
||||
|
||||
private static BigInteger HashPaddedTriplet(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2, BigInteger n3)
|
||||
{
|
||||
int length = (N.BitLength + 7) / 8;
|
||||
byte[] padded = GetPadded(n1, length);
|
||||
byte[] padded2 = GetPadded(n2, length);
|
||||
byte[] padded3 = GetPadded(n3, length);
|
||||
digest.BlockUpdate(padded, 0, padded.Length);
|
||||
digest.BlockUpdate(padded2, 0, padded2.Length);
|
||||
digest.BlockUpdate(padded3, 0, padded3.Length);
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
digest.DoFinal(array, 0);
|
||||
return new BigInteger(1, array);
|
||||
}
|
||||
|
||||
private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2)
|
||||
{
|
||||
int length = (N.BitLength + 7) / 8;
|
||||
byte[] padded = GetPadded(n1, length);
|
||||
byte[] padded2 = GetPadded(n2, length);
|
||||
digest.BlockUpdate(padded, 0, padded.Length);
|
||||
digest.BlockUpdate(padded2, 0, padded2.Length);
|
||||
byte[] array = new byte[digest.GetDigestSize()];
|
||||
digest.DoFinal(array, 0);
|
||||
return new BigInteger(1, array);
|
||||
}
|
||||
|
||||
private static byte[] GetPadded(BigInteger n, int length)
|
||||
{
|
||||
byte[] array = BigIntegers.AsUnsignedByteArray(n);
|
||||
if (array.Length < length)
|
||||
{
|
||||
byte[] array2 = new byte[length];
|
||||
Array.Copy(array, 0, array2, length - array.Length, array.Length);
|
||||
array = array2;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Math;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement.Srp;
|
||||
|
||||
public class Srp6VerifierGenerator
|
||||
{
|
||||
protected BigInteger N;
|
||||
|
||||
protected BigInteger g;
|
||||
|
||||
protected IDigest digest;
|
||||
|
||||
public virtual void Init(BigInteger N, BigInteger g, IDigest digest)
|
||||
{
|
||||
this.N = N;
|
||||
this.g = g;
|
||||
this.digest = digest;
|
||||
}
|
||||
|
||||
public virtual void Init(Srp6GroupParameters group, IDigest digest)
|
||||
{
|
||||
Init(group.N, group.G, digest);
|
||||
}
|
||||
|
||||
public virtual BigInteger GenerateVerifier(byte[] salt, byte[] identity, byte[] password)
|
||||
{
|
||||
BigInteger e = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
|
||||
return g.ModPow(e, N);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public sealed class X25519Agreement : IRawAgreement
|
||||
{
|
||||
private X25519PrivateKeyParameters privateKey;
|
||||
|
||||
public int AgreementSize => X25519PrivateKeyParameters.SecretSize;
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
privateKey = (X25519PrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off)
|
||||
{
|
||||
privateKey.GenerateSecret((X25519PublicKeyParameters)publicKey, buf, off);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
namespace Org.BouncyCastle.Crypto.Agreement;
|
||||
|
||||
public sealed class X448Agreement : IRawAgreement
|
||||
{
|
||||
private X448PrivateKeyParameters privateKey;
|
||||
|
||||
public int AgreementSize => X448PrivateKeyParameters.SecretSize;
|
||||
|
||||
public void Init(ICipherParameters parameters)
|
||||
{
|
||||
privateKey = (X448PrivateKeyParameters)parameters;
|
||||
}
|
||||
|
||||
public void CalculateAgreement(ICipherParameters publicKey, byte[] buf, int off)
|
||||
{
|
||||
privateKey.GenerateSecret((X448PublicKeyParameters)publicKey, buf, off);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user