Switch to X25519 + ML-KEM-768 encryption
This commit is contained in:
parent
9183651c4f
commit
79af6fcddf
5 changed files with 62 additions and 85 deletions
|
|
@ -6,6 +6,7 @@ using LarpixServer.Filesystem;
|
||||||
using LarpixServer.Utils;
|
using LarpixServer.Utils;
|
||||||
using LarpixServer.Utils.Jsons;
|
using LarpixServer.Utils.Jsons;
|
||||||
using static LarpixServer.Utils.Utils;
|
using static LarpixServer.Utils.Utils;
|
||||||
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
|
|
||||||
namespace LarpixServer.Account;
|
namespace LarpixServer.Account;
|
||||||
|
|
||||||
|
|
@ -81,12 +82,10 @@ public class Requests
|
||||||
|
|
||||||
context.Response.ContentType = mimeTypes["json"];
|
context.Response.ContentType = mimeTypes["json"];
|
||||||
|
|
||||||
(BigInteger p, BigInteger g, BigInteger pubServer, BigInteger secretServer) serverInfo =
|
var serverInfo = Encryption.Encryption.InitHybridKEM();
|
||||||
Encryption.Encryption.Init();
|
|
||||||
KeyExchangePayload payload = new KeyExchangePayload();
|
KeyExchangePayload payload = new KeyExchangePayload();
|
||||||
payload.p = serverInfo.p.ToString();
|
payload.pubX25519 = Convert.ToBase64String(serverInfo.pubX25519);
|
||||||
payload.g = serverInfo.g.ToString();
|
payload.pubMlKem = Convert.ToBase64String(serverInfo.pubMlKem);
|
||||||
payload.pubServer = serverInfo.pubServer.ToString();
|
|
||||||
payload.idKey = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + "\n";
|
payload.idKey = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + "\n";
|
||||||
|
|
||||||
while (createHolder.ContainsKey(payload.idKey))
|
while (createHolder.ContainsKey(payload.idKey))
|
||||||
|
|
@ -96,7 +95,8 @@ public class Requests
|
||||||
|
|
||||||
CreateHolder dataHolder = new();
|
CreateHolder dataHolder = new();
|
||||||
dataHolder.date = DateTimeOffset.UtcNow;
|
dataHolder.date = DateTimeOffset.UtcNow;
|
||||||
dataHolder.serverInfo = serverInfo;
|
dataHolder.privX25519Server = serverInfo.privX25519;
|
||||||
|
dataHolder.privMlKemServer = serverInfo.privMlKem;
|
||||||
|
|
||||||
createHolder.TryAdd(payload.idKey, dataHolder);
|
createHolder.TryAdd(payload.idKey, dataHolder);
|
||||||
|
|
||||||
|
|
@ -123,9 +123,12 @@ public class Requests
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.date = DateTimeOffset.UtcNow;
|
entry.date = DateTimeOffset.UtcNow;
|
||||||
entry.pubClient = BigInteger.Parse(serializedBody.pubClient);
|
|
||||||
byte[] sharedKey = Encryption.Encryption.CalcCommunicationKey(entry.pubClient,
|
byte[] pubX25519Client = Convert.FromBase64String(serializedBody.pubX25519);
|
||||||
entry.serverInfo.secretServer, entry.serverInfo.p);
|
byte[] ciphertextMlKem = Convert.FromBase64String(serializedBody.ciphertextMlKem);
|
||||||
|
|
||||||
|
byte[] sharedKey = Encryption.Encryption.CalcHybridSharedKey(
|
||||||
|
pubX25519Client, entry.privX25519Server, ciphertextMlKem, entry.privMlKemServer);
|
||||||
|
|
||||||
|
|
||||||
entry.name = Encryption.Encryption.Decrypt(serializedBody.username, sharedKey);
|
entry.name = Encryption.Encryption.Decrypt(serializedBody.username, sharedKey);
|
||||||
|
|
@ -649,6 +652,6 @@ public class CreateHolder
|
||||||
public string name;
|
public string name;
|
||||||
public string pass;
|
public string pass;
|
||||||
public string captcha;
|
public string captcha;
|
||||||
public (BigInteger p, BigInteger g, BigInteger pubServer, BigInteger secretServer) serverInfo;
|
public X25519PrivateKeyParameters privX25519Server;
|
||||||
public BigInteger pubClient;
|
public MLKemPrivateKeyParameters privMlKemServer;
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ public class Utils
|
||||||
|
|
||||||
public static bool IsUserLocal(string usernameWD, out string domain)
|
public static bool IsUserLocal(string usernameWD, out string domain)
|
||||||
{
|
{
|
||||||
if (usernameWD.EndsWith(":" + DOMAIN))
|
if (!usernameWD.Contains(':') || usernameWD.EndsWith(":" + DOMAIN))
|
||||||
{
|
{
|
||||||
domain = DOMAIN;
|
domain = DOMAIN;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2,87 +2,60 @@ using System.Globalization;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
|
using Org.BouncyCastle.Crypto.Generators;
|
||||||
|
using Org.BouncyCastle.Crypto.Kems;
|
||||||
|
using Org.BouncyCastle.Security;
|
||||||
|
|
||||||
namespace LarpixServer.Encryption;
|
namespace LarpixServer.Encryption;
|
||||||
|
|
||||||
public class Encryption
|
public class Encryption
|
||||||
{
|
{
|
||||||
private static readonly string PrimeHex =
|
public static (byte[] pubX25519, X25519PrivateKeyParameters privX25519, byte[] pubMlKem, MLKemPrivateKeyParameters privMlKem) InitHybridKEM()
|
||||||
"0" +
|
|
||||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
|
|
||||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
|
|
||||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
|
|
||||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
|
|
||||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
|
|
||||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
|
|
||||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
|
|
||||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
|
|
||||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
|
|
||||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
|
|
||||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" +
|
|
||||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" +
|
|
||||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" +
|
|
||||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" +
|
|
||||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" +
|
|
||||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" +
|
|
||||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" +
|
|
||||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" +
|
|
||||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" +
|
|
||||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" +
|
|
||||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" +
|
|
||||||
"FFFFFFFFFFFFFFFF";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// RFC 3526 4096-bit MODP Group (ID: 16) Prime
|
|
||||||
/// </summary>
|
|
||||||
public static BigInteger Prime { get; } = BigInteger.Parse(PrimeHex, NumberStyles.AllowHexSpecifier);
|
|
||||||
|
|
||||||
public static void Chuj()
|
|
||||||
{
|
{
|
||||||
(BigInteger p, BigInteger g, BigInteger pubServer, BigInteger secretServer) serverInfo = Init();
|
var random = new SecureRandom();
|
||||||
(BigInteger pubClient, byte[] aesKey) clientInfo = CalcCommunicationKeyClient(serverInfo.p, serverInfo.g, serverInfo.pubServer);
|
|
||||||
byte[] sharedKey = CalcCommunicationKey(clientInfo.pubClient, serverInfo.secretServer, serverInfo.p);
|
|
||||||
|
|
||||||
if (sharedKey == clientInfo.aesKey)
|
// X25519
|
||||||
{
|
var x25519KeyGen = new X25519KeyPairGenerator();
|
||||||
Console.WriteLine("key ok");
|
x25519KeyGen.Init(new X25519KeyGenerationParameters(random));
|
||||||
}
|
var x25519Kp = x25519KeyGen.GenerateKeyPair();
|
||||||
|
|
||||||
|
// ML-KEM-768
|
||||||
|
var mlkemGenParams = new MLKemKeyGenerationParameters(random, MLKemParameters.ml_kem_768);
|
||||||
|
var mlkemKeyGen = new MLKemKeyPairGenerator();
|
||||||
|
mlkemKeyGen.Init(mlkemGenParams);
|
||||||
|
var mlkemKp = mlkemKeyGen.GenerateKeyPair();
|
||||||
|
|
||||||
|
return (
|
||||||
|
((X25519PublicKeyParameters)x25519Kp.Public).GetEncoded(),
|
||||||
|
(X25519PrivateKeyParameters)x25519Kp.Private,
|
||||||
|
((MLKemPublicKeyParameters)mlkemKp.Public).GetEncoded(),
|
||||||
|
(MLKemPrivateKeyParameters)mlkemKp.Private
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (BigInteger p, BigInteger g, BigInteger pubServer, BigInteger secretServer) Init()
|
public static byte[] CalcHybridSharedKey(byte[] pubX25519Client, X25519PrivateKeyParameters privX25519Server, byte[] ciphertextMlKem, MLKemPrivateKeyParameters privMlKemServer)
|
||||||
{
|
{
|
||||||
BigInteger p = Prime;//GenerateRandomBigInt(4096);
|
// X25519 Agreement
|
||||||
BigInteger g = 2;
|
var x25519Agreement = new Org.BouncyCastle.Crypto.Agreement.X25519Agreement();
|
||||||
BigInteger secretServer = GenerateRandomBigInt(4096);
|
x25519Agreement.Init(privX25519Server);
|
||||||
|
var secretX25519 = new byte[32];
|
||||||
|
x25519Agreement.CalculateAgreement(new X25519PublicKeyParameters(pubX25519Client), secretX25519, 0);
|
||||||
|
|
||||||
BigInteger pubServer = BigInteger.ModPow(g, secretServer, p);
|
// ML-KEM Decapsulation
|
||||||
|
var decapsulator = new MLKemDecapsulator(MLKemParameters.ml_kem_768);
|
||||||
|
decapsulator.Init(privMlKemServer);
|
||||||
|
var secretMlKem = new byte[decapsulator.SecretLength];
|
||||||
|
decapsulator.Decapsulate(ciphertextMlKem, secretMlKem);
|
||||||
|
|
||||||
return (p, g, pubServer, secretServer);
|
// Combine and Hash: SHA256(X25519_Secret || MLKEM_Secret)
|
||||||
}
|
var combined = new byte[secretX25519.Length + secretMlKem.Length];
|
||||||
|
Buffer.BlockCopy(secretX25519, 0, combined, 0, secretX25519.Length);
|
||||||
|
Buffer.BlockCopy(secretMlKem, 0, combined, secretX25519.Length, secretMlKem.Length);
|
||||||
|
|
||||||
public static (BigInteger pubClient, byte[] aesKey) CalcCommunicationKeyClient(BigInteger p, BigInteger g, BigInteger pubServer)
|
|
||||||
{
|
|
||||||
BigInteger secretClient = GenerateRandomBigInt(4096);
|
|
||||||
|
|
||||||
BigInteger pubClient = BigInteger.ModPow(g, secretClient, p);
|
|
||||||
|
|
||||||
BigInteger sharedSecret = BigInteger.ModPow(pubServer, secretClient, p);
|
|
||||||
|
|
||||||
byte[] aesKey;
|
|
||||||
using (SHA256 sha256 = SHA256.Create())
|
using (SHA256 sha256 = SHA256.Create())
|
||||||
{
|
{
|
||||||
aesKey = sha256.ComputeHash(sharedSecret.ToByteArray(isUnsigned: true, isBigEndian: true));
|
return sha256.ComputeHash(combined);
|
||||||
}
|
|
||||||
|
|
||||||
return (pubClient, aesKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] CalcCommunicationKey(BigInteger pubClient, BigInteger secretServer, BigInteger p)
|
|
||||||
{
|
|
||||||
BigInteger sharedSecret = BigInteger.ModPow(pubClient, secretServer, p);
|
|
||||||
using (SHA256 sha256 = SHA256.Create())
|
|
||||||
{
|
|
||||||
return sha256.ComputeHash(sharedSecret.ToByteArray(isUnsigned: true, isBigEndian: true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />
|
||||||
<PackageReference Include="SkiaSharp" Version="3.119.2" />
|
<PackageReference Include="SkiaSharp" Version="3.119.2" />
|
||||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="3.119.2" />
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="3.119.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -21,15 +21,15 @@ public class Universal3String
|
||||||
|
|
||||||
public class KeyExchangePayload
|
public class KeyExchangePayload
|
||||||
{
|
{
|
||||||
public string p { get; set; }
|
public string pubX25519 { get; set; }
|
||||||
public string g { get; set; }
|
public string pubMlKem { get; set; }
|
||||||
public string pubServer { get; set; }
|
|
||||||
public string idKey { get; set; }
|
public string idKey { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KeyExchangePayloadClient
|
public class KeyExchangePayloadClient
|
||||||
{
|
{
|
||||||
public string pubClient { get; set; }
|
public string pubX25519 { get; set; }
|
||||||
|
public string ciphertextMlKem { get; set; }
|
||||||
public string idKey { get; set; }
|
public string idKey { get; set; }
|
||||||
public string username { get; set; }
|
public string username { get; set; }
|
||||||
public string password { get; set; }
|
public string password { get; set; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue