Hi all, 來到17天 今天就來解決key 存放的問題吧!!!
目前的想法: 把儲存這份工放在 sdk作業,一方面可以隱藏 BigInteger 的基礎型別,另一方面也比較符合單一職責。
直接來說明下目前想到的作法:
首先動工的點會在這支類別中,我期望使用端只需透過一個 method GetKeyDomain
就可以取得 key pair 及 session key。
主要邏輯會是: 先查看 key file 存不存在:
KeyDomain
進行回傳
public static class EccGenerator
{
private static readonly string KeyPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "key.json");
private static readonly X9ECParameters Curve = SecNamedCurves.GetByName("secp256k1");
private static readonly ECDomainParameters Domain = new(Curve.Curve, Curve.G, Curve.N, Curve.H);
public static KeyPairDomain GetKeyDomain()
{
if (File.Exists(KeyPath))
{
var keyInText = File.ReadAllText(KeyPath);
var keyPairSaved = JsonSerializer.Deserialize<KeyPairSaved>(keyInText);
return LoadEccKeyPair(keyPairSaved);
}
return GenerateKeyPairWithSessionKey();
}
private static KeyPairDomain GenerateKeyPairWithSessionKey()
{
var keyGen = new ECKeyPairGenerator();
var keyGenParam = new ECKeyGenerationParameters(Domain, new SecureRandom());
keyGen.Init(keyGenParam);
var keyPair = keyGen.GenerateKeyPair();
var keyPairDomain = new KeyPairDomain
{
PrivateKey = (ECPrivateKeyParameters)keyPair.Private,
PublicKey = (ECPublicKeyParameters)keyPair.Public,
SessionKey = new BigInteger(256, new SecureRandom())
};
keyPairDomain.SaveAsFile(KeyPath);
return keyPairDomain;
}
private static KeyPairDomain LoadEccKeyPair(KeyPairSaved keyPairSaved)
{
var privateKeyD = new BigInteger(keyPairSaved.StrPrivateKey, 16);
var privateKey = new ECPrivateKeyParameters(privateKeyD, Domain);
var q = Domain.G.Multiply(privateKey.D);
var publicKey = new ECPublicKeyParameters(q, Domain);
return new KeyPairDomain
{
PrivateKey = privateKey,
PublicKey = publicKey,
SessionKey = new BigInteger(keyPairSaved.StrSessionKey, 16)
};
}
}
透過測試執行後,確保呼叫兩次 GetKeyDomain
的值都會是一致的
[Test]
public void key_should_be_same()
{
var keyDomain1 = EccGenerator.GetKeyDomain();
var keyDomain2 = EccGenerator.GetKeyDomain();
Assert.Multiple(() =>
{
Assert.That(keyDomain2.PrivateKey.D, Is.EqualTo(keyDomain1.PrivateKey.D));
Assert.That(keyDomain2.SessionKey, Is.EqualTo(keyDomain1.SessionKey));
});
}
這次儲存的 key.json 預期上要長成這樣
不愧是 free style 的鐵人賽... 每天遇到的坑都是意料外的,好險都想的到方式解決嗚嗚嗚。
但因為大改 EccGenerator
的緣故,其他計算變色龍雜湊函數的地方都需要修改,當然測試那些也要重寫…
結語: 修完這些要接著修另個 side project 的 bug,我是甚麼專案渣男嗎