added session tests
This commit is contained in:
parent
fd47ade07b
commit
3cb4da4004
75
tests/session/testSessionClean.cs
Normal file
75
tests/session/testSessionClean.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using chestcrypto.session;
|
||||||
|
using chestcrypto.exceptions;
|
||||||
|
using Sodium;
|
||||||
|
|
||||||
|
namespace sessionPrivateTestsCleaning
|
||||||
|
{
|
||||||
|
public class Tests
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFutureTime(int seconds){return DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (long) seconds;}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSessionCleanPrivate(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
session.setMinimumKeyExpireSeconds(1);
|
||||||
|
session.setMessageDelay((long) 1);
|
||||||
|
session.addPrivate(newK, getFutureTime(2));
|
||||||
|
bool atLeastOneLoop = false;
|
||||||
|
while(true){
|
||||||
|
try{
|
||||||
|
if (Enumerable.SequenceEqual(session.getLatestPrivateKey(), newK)){
|
||||||
|
Thread.Sleep(25); // ms
|
||||||
|
atLeastOneLoop = true; // key should not be deleted instantly
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(System.ArgumentOutOfRangeException){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
session.cleanPrivate();
|
||||||
|
}
|
||||||
|
Assert.IsTrue(atLeastOneLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSessionCleanPublic(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
session.setMinimumKeyExpireSeconds(1);
|
||||||
|
session.setMessageDelay((long) 1);
|
||||||
|
session.addPublic(newK, getFutureTime(2));
|
||||||
|
bool atLeastOneLoop = false;
|
||||||
|
while(true){
|
||||||
|
try{
|
||||||
|
if (Enumerable.SequenceEqual(session.getLatestPublicKey(), newK)){
|
||||||
|
Thread.Sleep(25); // ms
|
||||||
|
atLeastOneLoop = true; // key should not be deleted instantly
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(System.ArgumentOutOfRangeException){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
session.cleanPublic();
|
||||||
|
}
|
||||||
|
Assert.IsTrue(atLeastOneLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
35
tests/session/testSessionEncrypt.cs
Normal file
35
tests/session/testSessionEncrypt.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using chestcrypto.session;
|
||||||
|
using chestcrypto.exceptions;
|
||||||
|
using Sodium;
|
||||||
|
|
||||||
|
namespace sessionTestEncrypt
|
||||||
|
{
|
||||||
|
public class Tests
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFutureTime(int seconds){return DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (long) seconds;}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEncrypt(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte message = ""
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
SessionCrypto sessionCrypto = new SessionCrypto(session);
|
||||||
|
session.setMinimumKeyExpireSeconds(1);
|
||||||
|
session.setMessageDelay((long) 1);
|
||||||
|
session.addPublic(newK, getFutureTime(9));
|
||||||
|
sessionCrypto.encrypt()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
55
tests/session/testSessionPrivate.cs
Normal file
55
tests/session/testSessionPrivate.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using chestcrypto.session;
|
||||||
|
using chestcrypto.exceptions;
|
||||||
|
using Sodium;
|
||||||
|
|
||||||
|
namespace sessionPrivateTests
|
||||||
|
{
|
||||||
|
public class Tests
|
||||||
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFutureTime(int seconds){return DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (long) seconds;}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSessionAddValidPrivate(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
session.addPrivate(newK, getFutureTime(670));
|
||||||
|
Assert.IsTrue(Enumerable.SequenceEqual(newK, session.getLatestPrivateKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSessionAddInvalidPrivateTime(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
try{
|
||||||
|
session.addPrivate(newK, getFutureTime(1));
|
||||||
|
}
|
||||||
|
catch(System.ArgumentOutOfRangeException){return;}
|
||||||
|
Assert.Fail();
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public void TestSessionAddInvalidPrivate(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = {5, 3, 2, 1};
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
try{
|
||||||
|
session.addPrivate(newK, getFutureTime(7010));
|
||||||
|
}
|
||||||
|
catch(InvalidKeyLength){return;}
|
||||||
|
Assert.Fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -14,8 +14,19 @@ namespace sessionTests
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getFutureTime(int seconds){
|
public long getFutureTime(int seconds){return DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (long) seconds;}
|
||||||
return DateTimeOffset.UtcNow.ToUnixTimeSeconds() + (long) seconds;
|
|
||||||
|
[Test]
|
||||||
|
public void TestSessionGetLatestPublic(){
|
||||||
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
|
for (int i = 0; i < 5; i++){
|
||||||
|
session.addPublic(PublicKeyBox.GenerateKeyPair().PublicKey, getFutureTime(630));
|
||||||
|
}
|
||||||
|
session.addPublic(newK, getFutureTime(650));
|
||||||
|
Assert.IsTrue(Enumerable.SequenceEqual(newK, session.getLatestPublicKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -23,8 +34,8 @@ namespace sessionTests
|
|||||||
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
Session session = new Session(privateK, publicK, true);
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
session.addPublic(newK, getFutureTime(61));
|
session.addPublic(newK, getFutureTime(610));
|
||||||
Assert.IsTrue(Enumerable.SequenceEqual(newK, session.getLatestPublicKey()));
|
Assert.IsTrue(Enumerable.SequenceEqual(newK, session.getLatestPublicKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,10 +44,10 @@ namespace sessionTests
|
|||||||
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
Session session = new Session(privateK, publicK, true);
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
session.addPublic(newK, getFutureTime(61));
|
session.addPublic(newK, getFutureTime(615));
|
||||||
try{
|
try{
|
||||||
session.addPublic(newK, getFutureTime(61));
|
session.addPublic(newK, getFutureTime(615));
|
||||||
}
|
}
|
||||||
catch(DuplicatePublicKey){return;}
|
catch(DuplicatePublicKey){return;}
|
||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
@ -47,7 +58,7 @@ namespace sessionTests
|
|||||||
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
byte[] newK = {3, 5};
|
byte[] newK = {3, 5};
|
||||||
Session session = new Session(privateK, publicK, true);
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
try{
|
try{
|
||||||
session.addPublic(newK, getFutureTime(61));
|
session.addPublic(newK, getFutureTime(61));
|
||||||
}
|
}
|
||||||
@ -62,7 +73,7 @@ namespace sessionTests
|
|||||||
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] newK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
Session session = new Session(privateK, publicK, true);
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
try{
|
try{
|
||||||
session.addPublic(newK, getFutureTime(-1));
|
session.addPublic(newK, getFutureTime(-1));
|
||||||
}
|
}
|
||||||
@ -77,11 +88,11 @@ namespace sessionTests
|
|||||||
{
|
{
|
||||||
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
byte[] publicK = PublicKeyBox.GenerateKeyPair().PublicKey;
|
||||||
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
byte[] privateK = PublicKeyBox.GenerateKeyPair().PrivateKey;
|
||||||
Session session = new Session(privateK, publicK, true);
|
Session session = new Session(privateK, publicK, true, 5);
|
||||||
byte[] invalid = {0, 0, 0};
|
byte[] invalid = {0, 0, 0};
|
||||||
|
|
||||||
try{
|
try{
|
||||||
new Session(invalid, publicK, true);
|
new Session(invalid, publicK, true, 5);
|
||||||
}
|
}
|
||||||
catch(InvalidKeyLength){
|
catch(InvalidKeyLength){
|
||||||
goto secondAssert;
|
goto secondAssert;
|
||||||
@ -89,7 +100,7 @@ namespace sessionTests
|
|||||||
Assert.Fail();
|
Assert.Fail();
|
||||||
secondAssert:
|
secondAssert:
|
||||||
try{
|
try{
|
||||||
new Session(privateK, invalid, true);
|
new Session(privateK, invalid, true, 5);
|
||||||
}
|
}
|
||||||
catch(InvalidKeyLength){
|
catch(InvalidKeyLength){
|
||||||
return;
|
return;
|
18
treasurechest/chestcrypto/session/crypto/encrypt.cs
Normal file
18
treasurechest/chestcrypto/session/crypto/encrypt.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Sodium;
|
||||||
|
|
||||||
|
using chestcrypto.session;
|
||||||
|
using chestcrypto;
|
||||||
|
|
||||||
|
namespace chestcrypto.session.crypto{
|
||||||
|
|
||||||
|
internal class SessionEncrypt{
|
||||||
|
|
||||||
|
public static byte[] Encrypt(Session activeSession, byte[] message){
|
||||||
|
byte[] publicKey = activeSession.getLatestPublicKey();
|
||||||
|
byte[] privateKey = activeSession.getLatestPrivateKey();
|
||||||
|
return Curve25519.encrypt(privateKey, publicKey, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -18,6 +18,40 @@ namespace chestcrypto{
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public class DuplicatePrivateKey : Exception
|
||||||
|
{
|
||||||
|
public DuplicatePrivateKey()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DuplicatePrivateKey(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DuplicatePrivateKey(string message, Exception inner)
|
||||||
|
: base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoSessionKeyAvailable : Exception
|
||||||
|
{
|
||||||
|
public NoSessionKeyAvailable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoSessionKeyAvailable(string message)
|
||||||
|
: base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NoSessionKeyAvailable(string message, Exception inner)
|
||||||
|
: base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ namespace chestcrypto{
|
|||||||
|
|
||||||
namespace session{
|
namespace session{
|
||||||
|
|
||||||
internal class Session{
|
public class Session{
|
||||||
|
|
||||||
// Create List of tuples(time, byte[])
|
// Create List of tuples(time, byte[])
|
||||||
// Where the tuple contains a time stamp for expiry and a ed25519 key
|
// Where the tuple contains a time stamp for expiry and a ed25519 key
|
||||||
@ -17,14 +17,27 @@ namespace chestcrypto{
|
|||||||
private byte[] ourMasterPrivateKey;
|
private byte[] ourMasterPrivateKey;
|
||||||
private byte[] theirMasterPublicKey;
|
private byte[] theirMasterPublicKey;
|
||||||
private bool strictMode;
|
private bool strictMode;
|
||||||
private const int minimumKeyExpireSeconds = 60;
|
|
||||||
|
|
||||||
private void validateKey(byte[] key){
|
private long messageDelay = 25;
|
||||||
|
|
||||||
|
private int minimumKeyExpireSeconds = 600;
|
||||||
|
|
||||||
|
private void validateKeyLength(byte[] key){
|
||||||
if (key.Length != 32){
|
if (key.Length != 32){
|
||||||
throw new InvalidKeyLength();
|
throw new InvalidKeyLength();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long getEpoch(){
|
||||||
|
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateTimestamp(long ts){
|
||||||
|
if (ts < getEpoch() + minimumKeyExpireSeconds){
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool publicKeyExists(byte[] key){
|
private bool publicKeyExists(byte[] key){
|
||||||
foreach((int, byte[]) k in theirPublicKeys){
|
foreach((int, byte[]) k in theirPublicKeys){
|
||||||
if (Enumerable.SequenceEqual(k.Item2, key)){
|
if (Enumerable.SequenceEqual(k.Item2, key)){
|
||||||
@ -34,27 +47,88 @@ namespace chestcrypto{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Session(byte[] masterPrivate, byte[] masterPublic, bool strictMode){
|
private bool privateKeyExists(byte[] key){
|
||||||
validateKey(masterPrivate);
|
foreach((int, byte[]) k in ourPrivateKeys){
|
||||||
validateKey(masterPublic);
|
if (Enumerable.SequenceEqual(k.Item2, key)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Session(byte[] masterPrivate, byte[] masterPublic, bool strictMode, long messageDelay){
|
||||||
|
validateKeyLength(masterPrivate);
|
||||||
|
validateKeyLength(masterPublic);
|
||||||
ourMasterPrivateKey = masterPrivate;
|
ourMasterPrivateKey = masterPrivate;
|
||||||
theirMasterPublicKey = masterPublic;
|
theirMasterPublicKey = masterPublic;
|
||||||
this.strictMode = strictMode;
|
this.strictMode = strictMode;
|
||||||
|
this.messageDelay = messageDelay;
|
||||||
ourPrivateKeys = new List<(long, byte[])>();
|
ourPrivateKeys = new List<(long, byte[])>();
|
||||||
theirPublicKeys = new List<(long, byte[])>();
|
theirPublicKeys = new List<(long, byte[])>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPublic(byte[] publicKey, long timestamp){
|
public void setMinimumKeyExpireSeconds(int newSeconds){minimumKeyExpireSeconds = newSeconds;}
|
||||||
validateKey(publicKey);
|
public void setMessageDelay(long newDelay){
|
||||||
if (publicKeyExists(publicKey)){throw new DuplicatePublicKey();}
|
messageDelay = newDelay;
|
||||||
if (timestamp < DateTimeOffset.UtcNow.ToUnixTimeSeconds() + minimumKeyExpireSeconds){
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addPublic(byte[] publicKey, long timestamp){
|
||||||
|
timestamp -= messageDelay; // Subtract some time from the specified timestamp because we don't want to use it close to expiry
|
||||||
|
validateKeyLength(publicKey);
|
||||||
|
validateTimestamp(timestamp);
|
||||||
|
if (publicKeyExists(publicKey)){throw new DuplicatePublicKey();}
|
||||||
theirPublicKeys.Add((timestamp, publicKey));
|
theirPublicKeys.Add((timestamp, publicKey));
|
||||||
}
|
}
|
||||||
public byte[] getLatestPublicKey(){return theirPublicKeys[theirPublicKeys.Count - 1].Item2;}
|
public byte[] getLatestPublicKey(){
|
||||||
|
if (theirPublicKeys.Count == 0 && strictMode)
|
||||||
|
throw new NoSessionKeyAvailable();
|
||||||
|
var key = theirPublicKeys[theirPublicKeys.Count - 1];
|
||||||
|
validateTimestamp(key.Item1);
|
||||||
|
return key.Item2;
|
||||||
|
}
|
||||||
|
public byte[] getLatestPrivateKey(){
|
||||||
|
if (ourPrivateKeys.Count == 0 && strictMode)
|
||||||
|
throw new NoSessionKeyAvailable();
|
||||||
|
var key = ourPrivateKeys[ourPrivateKeys.Count -1];
|
||||||
|
validateTimestamp(key.Item1);
|
||||||
|
return key.Item2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPrivate(byte[] privateKey, long timestamp){
|
||||||
|
validateKeyLength(privateKey);
|
||||||
|
validateTimestamp(timestamp);
|
||||||
|
if (privateKeyExists(privateKey)){throw new DuplicatePrivateKey();}
|
||||||
|
ourPrivateKeys.Add((timestamp, privateKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanPublic(){
|
||||||
|
long epoch = getEpoch();
|
||||||
|
bool expired((long, byte[]) k){
|
||||||
|
if (k.Item1 > epoch){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
theirPublicKeys.RemoveAll(expired); // remove all keys who are truthy with expired()
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanPrivate(){
|
||||||
|
// Can't use predicate approach because we want to zero out private keys
|
||||||
|
List<int> remove = new List<int>();
|
||||||
|
|
||||||
|
for (int i = 0; i < ourPrivateKeys.Count; i++){
|
||||||
|
if (ourPrivateKeys[i].Item1 > getEpoch()){
|
||||||
|
remove.Add(i);
|
||||||
|
// We manually clear memory to reduce attack surface a tiny bit (GC may take too long)
|
||||||
|
Array.Clear(ourPrivateKeys[i].Item2, 0, ourPrivateKeys[i].Item2.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach(int i in remove){
|
||||||
|
ourPrivateKeys.RemoveAt((int) i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user