Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Support .netstandard2.1 #3424

Open
wants to merge 1 commit into
base: release/1.5.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/AElf.Cryptography/AElf.Cryptography.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\common.props"/>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>netstandard2.1;net6.0</TargetFrameworks>
<PackageId>AElf.Cryptography</PackageId>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Description>Cryptographic primitives used in AElf.</Description>
Expand Down
267 changes: 134 additions & 133 deletions src/AElf.Cryptography/CryptoHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,157 +7,158 @@
using Secp256k1Net;
using Virgil.Crypto;

namespace AElf.Cryptography;

public static class CryptoHelper
namespace AElf.Cryptography
{
private static readonly Secp256k1 Secp256K1 = new();

// ReaderWriterLock for thread-safe with Secp256k1 APIs
private static readonly ReaderWriterLock Lock = new();

static CryptoHelper()
{
AppDomain.CurrentDomain.ProcessExit += (sender, arg) => { Secp256K1.Dispose(); };
}

public static ECKeyPair FromPrivateKey(byte[] privateKey)

public static class CryptoHelper
{
if (privateKey == null || privateKey.Length != 32)
throw new InvalidPrivateKeyException(
$"Private key has to have length of 32. Current length is {privateKey?.Length}.");

try
private static readonly Secp256k1 Secp256K1 = new Secp256k1();

// ReaderWriterLock for thread-safe with Secp256k1 APIs
private static readonly ReaderWriterLock Lock = new ReaderWriterLock();

static CryptoHelper()
{
Lock.AcquireWriterLock(Timeout.Infinite);
var secp256K1PubKey = new byte[64];

if (!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey))
throw new InvalidPrivateKeyException("Create public key failed.");
var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey))
throw new PublicKeyOperationException("Serialize public key failed.");
return new ECKeyPair(privateKey, pubKey);
AppDomain.CurrentDomain.ProcessExit += (sender, arg) => { Secp256K1.Dispose(); };
}
finally

public static ECKeyPair FromPrivateKey(byte[] privateKey)
{
Lock.ReleaseWriterLock();
}
}

public static ECKeyPair GenerateKeyPair()
{
try
{
Lock.AcquireWriterLock(Timeout.Infinite);
var privateKey = new byte[32];
var secp256K1PubKey = new byte[64];

// Generate a private key.
var rnd = RandomNumberGenerator.Create();
do
if (privateKey == null || privateKey.Length != 32)
throw new InvalidPrivateKeyException(
$"Private key has to have length of 32. Current length is {privateKey?.Length}.");

try
{
rnd.GetBytes(privateKey);
} while (!Secp256K1.SecretKeyVerify(privateKey));

if (!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey))
throw new InvalidPrivateKeyException("Create public key failed.");
var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey))
throw new PublicKeyOperationException("Serialize public key failed.");
return new ECKeyPair(privateKey, pubKey);
Lock.AcquireWriterLock(Timeout.Infinite);
var secp256K1PubKey = new byte[64];

if (!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey))
throw new InvalidPrivateKeyException("Create public key failed.");
var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey))
throw new PublicKeyOperationException("Serialize public key failed.");
return new ECKeyPair(privateKey, pubKey);
}
finally
{
Lock.ReleaseWriterLock();
}
}
finally

public static ECKeyPair GenerateKeyPair()
{
Lock.ReleaseWriterLock();
try
{
Lock.AcquireWriterLock(Timeout.Infinite);
var privateKey = new byte[32];
var secp256K1PubKey = new byte[64];

// Generate a private key.
var rnd = RandomNumberGenerator.Create();
do
{
rnd.GetBytes(privateKey);
} while (!Secp256K1.SecretKeyVerify(privateKey));

if (!Secp256K1.PublicKeyCreate(secp256K1PubKey, privateKey))
throw new InvalidPrivateKeyException("Create public key failed.");
var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.PublicKeySerialize(pubKey, secp256K1PubKey))
throw new PublicKeyOperationException("Serialize public key failed.");
return new ECKeyPair(privateKey, pubKey);
}
finally
{
Lock.ReleaseWriterLock();
}
}
}

public static byte[] SignWithPrivateKey(byte[] privateKey, byte[] hash)
{
try

public static byte[] SignWithPrivateKey(byte[] privateKey, byte[] hash)
{
Lock.AcquireWriterLock(Timeout.Infinite);
var recSig = new byte[65];
var compactSig = new byte[65];
if (!Secp256K1.SignRecoverable(recSig, hash, privateKey))
throw new SignatureOperationException("Create a recoverable ECDSA signature failed.");
if (!Secp256K1.RecoverableSignatureSerializeCompact(compactSig, out var recoverId, recSig))
throw new SignatureOperationException("Serialize an ECDSA signature failed.");
compactSig[64] = (byte)recoverId; // put recover id at the last slot
return compactSig;
try
{
Lock.AcquireWriterLock(Timeout.Infinite);
var recSig = new byte[65];
var compactSig = new byte[65];
if (!Secp256K1.SignRecoverable(recSig, hash, privateKey))
throw new SignatureOperationException("Create a recoverable ECDSA signature failed.");
if (!Secp256K1.RecoverableSignatureSerializeCompact(compactSig, out var recoverId, recSig))
throw new SignatureOperationException("Serialize an ECDSA signature failed.");
compactSig[64] = (byte)recoverId; // put recover id at the last slot
return compactSig;
}
finally
{
Lock.ReleaseWriterLock();
}
}
finally

public static bool VerifySignature(byte[] signature, byte[] data, byte[] publicKey)
{
Lock.ReleaseWriterLock();
var recoverResult = RecoverPublicKey(signature, data, out var recoverPublicKey);
return recoverResult && publicKey.BytesEqual(recoverPublicKey);
}
}

public static bool VerifySignature(byte[] signature, byte[] data, byte[] publicKey)
{
var recoverResult = RecoverPublicKey(signature, data, out var recoverPublicKey);
return recoverResult && publicKey.BytesEqual(recoverPublicKey);
}

public static bool RecoverPublicKey(byte[] signature, byte[] hash, out byte[] pubkey)
{
pubkey = null;
try

public static bool RecoverPublicKey(byte[] signature, byte[] hash, out byte[] pubkey)
{
Lock.AcquireWriterLock(Timeout.Infinite);
// Recover id should be greater than or equal to 0 and less than 4
if (signature.Length != Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH || signature.Last() >= 4)
return false;
var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
var recoveredPubKey = new byte[Secp256k1.PUBKEY_LENGTH];
var recSig = new byte[65];
if (!Secp256K1.RecoverableSignatureParseCompact(recSig, signature, signature.Last()))
return false;
if (!Secp256K1.Recover(recoveredPubKey, recSig, hash))
return false;
if (!Secp256K1.PublicKeySerialize(pubKey, recoveredPubKey))
return false;
pubkey = pubKey;
return true;
pubkey = null;
try
{
Lock.AcquireWriterLock(Timeout.Infinite);
// Recover id should be greater than or equal to 0 and less than 4
if (signature.Length != Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH || signature.Last() >= 4)
return false;
var pubKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
var recoveredPubKey = new byte[Secp256k1.PUBKEY_LENGTH];
var recSig = new byte[65];
if (!Secp256K1.RecoverableSignatureParseCompact(recSig, signature, signature.Last()))
return false;
if (!Secp256K1.Recover(recoveredPubKey, recSig, hash))
return false;
if (!Secp256K1.PublicKeySerialize(pubKey, recoveredPubKey))
return false;
pubkey = pubKey;
return true;
}
finally
{
Lock.ReleaseWriterLock();
}
}
finally

public static byte[] EncryptMessage(byte[] senderPrivateKey, byte[] receiverPublicKey, byte[] plainText)
{
Lock.ReleaseWriterLock();
var crypto = new VirgilCrypto(KeyPairType.EC_SECP256K1);
var ecdhKey = Ecdh(senderPrivateKey, receiverPublicKey);
var newKeyPair = crypto.GenerateKeys(KeyPairType.EC_SECP256K1, ecdhKey);
return crypto.Encrypt(plainText, newKeyPair.PublicKey);
}
}

public static byte[] EncryptMessage(byte[] senderPrivateKey, byte[] receiverPublicKey, byte[] plainText)
{
var crypto = new VirgilCrypto(KeyPairType.EC_SECP256K1);
var ecdhKey = Ecdh(senderPrivateKey, receiverPublicKey);
var newKeyPair = crypto.GenerateKeys(KeyPairType.EC_SECP256K1, ecdhKey);
return crypto.Encrypt(plainText, newKeyPair.PublicKey);
}

public static byte[] DecryptMessage(byte[] senderPublicKey, byte[] receiverPrivateKey, byte[] cipherText)
{
var crypto = new VirgilCrypto(KeyPairType.EC_SECP256K1);
var ecdhKey = Ecdh(receiverPrivateKey, senderPublicKey);
var newKeyPair = crypto.GenerateKeys(KeyPairType.EC_SECP256K1, ecdhKey);
return crypto.Decrypt(cipherText, newKeyPair.PrivateKey);
}

public static byte[] Ecdh(byte[] privateKey, byte[] publicKey)
{
try

public static byte[] DecryptMessage(byte[] senderPublicKey, byte[] receiverPrivateKey, byte[] cipherText)
{
Lock.AcquireWriterLock(Timeout.Infinite);
var usablePublicKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.PublicKeyParse(usablePublicKey, publicKey))
throw new PublicKeyOperationException("Parse public key failed.");
var ecdhKey = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.Ecdh(ecdhKey, usablePublicKey, privateKey))
throw new EcdhOperationException("Compute EC Diffie- secret failed.");
return ecdhKey;
var crypto = new VirgilCrypto(KeyPairType.EC_SECP256K1);
var ecdhKey = Ecdh(receiverPrivateKey, senderPublicKey);
var newKeyPair = crypto.GenerateKeys(KeyPairType.EC_SECP256K1, ecdhKey);
return crypto.Decrypt(cipherText, newKeyPair.PrivateKey);
}
finally

public static byte[] Ecdh(byte[] privateKey, byte[] publicKey)
{
Lock.ReleaseWriterLock();
try
{
Lock.AcquireWriterLock(Timeout.Infinite);
var usablePublicKey = new byte[Secp256k1.SERIALIZED_UNCOMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.PublicKeyParse(usablePublicKey, publicKey))
throw new PublicKeyOperationException("Parse public key failed.");
var ecdhKey = new byte[Secp256k1.SERIALIZED_COMPRESSED_PUBKEY_LENGTH];
if (!Secp256K1.Ecdh(ecdhKey, usablePublicKey, privateKey))
throw new EcdhOperationException("Compute EC Diffie- secret failed.");
return ecdhKey;
}
finally
{
Lock.ReleaseWriterLock();
}
}
}
}
}}
23 changes: 12 additions & 11 deletions src/AElf.Cryptography/ECDSA/ECKeyPair.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using Secp256k1Net;

namespace AElf.Cryptography.ECDSA;

public class ECKeyPair : IAElfAsymmetricCipherKeyPair
namespace AElf.Cryptography.ECDSA
{
internal ECKeyPair(byte[] privateKey, byte[] publicKey)

public class ECKeyPair : IAElfAsymmetricCipherKeyPair
{
PublicKey = publicKey;
PrivateKey = privateKey.LeftPad(Secp256k1.PRIVKEY_LENGTH);
}

public byte[] PrivateKey { get; }
public byte[] PublicKey { get; }
}
internal ECKeyPair(byte[] privateKey, byte[] publicKey)
{
PublicKey = publicKey;
PrivateKey = privateKey.LeftPad(Secp256k1.PRIVKEY_LENGTH);
}

public byte[] PrivateKey { get; }
public byte[] PublicKey { get; }
}}
13 changes: 7 additions & 6 deletions src/AElf.Cryptography/ECDSA/ECParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto.Parameters;

namespace AElf.Cryptography.ECDSA;

public static class ECParameters
namespace AElf.Cryptography.ECDSA
{
public static readonly X9ECParameters Curve = SecNamedCurves.GetByName("secp256k1");
public static readonly ECDomainParameters DomainParams = new(Curve.Curve, Curve.G, Curve.N, Curve.H);
}

public static class ECParameters
{
public static readonly X9ECParameters Curve = SecNamedCurves.GetByName("secp256k1");
public static readonly ECDomainParameters DomainParams = new ECDomainParameters(Curve.Curve, Curve.G, Curve.N, Curve.H);
}}
13 changes: 7 additions & 6 deletions src/AElf.Cryptography/Exceptions/EcdhOperationException.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;

namespace AElf.Cryptography.Exceptions;

public class EcdhOperationException : Exception
namespace AElf.Cryptography.Exceptions
{
public EcdhOperationException(string message) : base(message)

public class EcdhOperationException : Exception
{
}
}
public EcdhOperationException(string message) : base(message)
{
}
}}
13 changes: 7 additions & 6 deletions src/AElf.Cryptography/Exceptions/InvalidKeyPairException.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System;

namespace AElf.Cryptography.Exceptions;

public class InvalidKeyPairException : Exception
namespace AElf.Cryptography.Exceptions
{
public InvalidKeyPairException(string message, Exception innerException) : base(message, innerException)

public class InvalidKeyPairException : Exception
{
}
}
public InvalidKeyPairException(string message, Exception innerException) : base(message, innerException)
{
}
}}
Loading