-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Remove libsodium dependencies * Added crypto tests; * Impemented ConvertEd25519PublicKeyToCurve25519PublicKey; * Removed hardcoded PUBLIC_KEY_BYTES value; * SealedPublicKeyBox * Fix README.md * Fix SealedPublicKeyBox keys * Decreased BYTES_MIN param to 0 in GenericHash; * 1.0.18 --------- Co-authored-by: Igor Matsak <[email protected]>
- Loading branch information
Showing
35 changed files
with
1,597 additions
and
1,163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
namespace Beacon.Sdk.Tests | ||
{ | ||
using Core.Infrastructure.Cryptography; | ||
using Core.Infrastructure.Cryptography.NaCl; | ||
using Core.Infrastructure.Cryptography.BouncyCastle; | ||
using Microsoft.VisualStudio.TestTools.UnitTesting; | ||
using System.Text; | ||
|
||
[TestClass] | ||
public class CryptoTests | ||
{ | ||
private byte[] randomPubKeyBytes { get; } = | ||
{ | ||
0x58, 0x96, 0xB4, 0xDE, 0x36, 0x93, 0x5F, 0x5, 0x79, 0x4E, 0xB8, 0x7, 0x3F, 0xB1, 0x7F, 0xE6, 0xAD, | ||
0x64, 0xFF, 0xE3, 0x48, 0x60, 0x81, 0x1C, 0x9D, 0xDF, 0xB9, 0xE4, 0xF3, 0x2F, 0xF7, 0x5B, | ||
}; | ||
|
||
private byte[] convertedPubKeyBytes { get; } = | ||
{ | ||
0x50, 0x94, 0xD3, 0xF3, 0x88, 0xFD, 0x19, 0xF3, 0x3D, 0xBF, 0xA7, 0x3A, 0x6C, 0x9E, 0xCD, 0x80, 0x7C, | ||
0x1C, 0x92, 0x74, 0xE3, 0xA0, 0x71, 0x8F, 0xEC, 0xB8, 0xDD, 0x8D, 0x3E, 0x78, 0x66, 0x15 | ||
}; | ||
|
||
[TestMethod] | ||
public void TestSodiumConvertEd25519PublicKeyToCurve25519PublicKey() | ||
{ | ||
var actual = PublicKeyAuth.ConvertEd25519PublicKeyToCurve25519PublicKey(randomPubKeyBytes); | ||
CollectionAssert.AreEqual(convertedPubKeyBytes, actual); | ||
} | ||
|
||
[TestMethod] | ||
public void TestConvertEd25519PublicKeyToCurve25519PublicKey() | ||
{ | ||
var actual = new byte[32]; | ||
MontgomeryCurve25519.EdwardsToMontgomery(actual, randomPubKeyBytes); | ||
CollectionAssert.AreEqual(convertedPubKeyBytes, actual); | ||
} | ||
|
||
[TestMethod] | ||
public void CanEncryptAndDecryptBySecretBox() | ||
{ | ||
var key = SecureRandom.GetRandomBytes(32); | ||
var nonce = SecureRandom.GetRandomBytes(24); | ||
var message = Encoding.UTF8.GetBytes("Test message for secret box"); | ||
|
||
var cipher = SecretBox.Create(message, nonce, key); | ||
|
||
var decrypted = SecretBox.Open(cipher, nonce, key); | ||
|
||
CollectionAssert.AreEqual(message, decrypted); | ||
} | ||
|
||
[TestMethod] | ||
public void CanEncryptAndDecryptBySealedSecretBox() | ||
{ | ||
var seed = SecureRandom.GetRandomBytes(32); | ||
|
||
var ed25519keyPair = PublicKeyAuth.GenerateKeyPair(seed); | ||
|
||
var curve25519sk = Ed25519Extensions.ConvertEd25519SecretKeyToCurve25519SecretKey(ed25519keyPair.PrivateKey); | ||
var curve25519pk = Ed25519Extensions.ConvertEd25519PublicKeyToCurve25519PublicKey(ed25519keyPair.PublicKey); | ||
|
||
var message = Encoding.UTF8.GetBytes("Test message for secret box"); | ||
|
||
var cipher = SealedPublicKeyBox.Create(message, curve25519pk); | ||
|
||
var decrypted = SealedPublicKeyBox.Open(cipher, curve25519sk, curve25519pk); | ||
|
||
CollectionAssert.AreEqual(message, decrypted); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
Beacon.Sdk/Core/Infrastructure/Cryptography/BouncyCastle/Ed25519Extensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Org.BouncyCastle.Crypto.Digests; | ||
using System; | ||
|
||
namespace Beacon.Sdk.Core.Infrastructure.Cryptography.BouncyCastle | ||
{ | ||
using NaCl; | ||
|
||
public static class Ed25519Extensions | ||
{ | ||
private const int PUBLIC_KEY_BYTES = 32; | ||
private const int SCALAR_BYTES = 32; | ||
private const int SECRET_KEY_BYTES = 32 + 32; | ||
|
||
/// <summary>Converts the ed25519 public key to curve25519 public key.</summary> | ||
/// <param name="ed25519PublicKey">Ed25519 public key.</param> | ||
/// <returns>The curve25519 public key.</returns> | ||
/// <exception cref="ArgumentOutOfRangeException"></exception> | ||
public static byte[] ConvertEd25519PublicKeyToCurve25519PublicKey(byte[] ed25519PublicKey) | ||
{ | ||
if (ed25519PublicKey == null || ed25519PublicKey.Length != PUBLIC_KEY_BYTES) | ||
throw new ArgumentOutOfRangeException(nameof(ed25519PublicKey), ed25519PublicKey?.Length ?? 0, $"ed25519PublicKey must be {PUBLIC_KEY_BYTES} bytes in length."); | ||
|
||
var result = new byte[PUBLIC_KEY_BYTES]; | ||
MontgomeryCurve25519.EdwardsToMontgomery(result, ed25519PublicKey); | ||
return result; | ||
} | ||
|
||
/// <summary>Converts the ed25519 secret key to curve25519 secret key.</summary> | ||
/// <param name="ed25519SecretKey">Ed25519 secret key.</param> | ||
/// <returns>The curve25519 secret key.</returns> | ||
/// <exception cref="ArgumentOutOfRangeException"></exception> | ||
public static byte[] ConvertEd25519SecretKeyToCurve25519SecretKey(byte[] ed25519SecretKey) | ||
{ | ||
// key can be appended with the public key or not (both are allowed) | ||
if (ed25519SecretKey == null || (ed25519SecretKey.Length != PUBLIC_KEY_BYTES && ed25519SecretKey.Length != SECRET_KEY_BYTES)) | ||
throw new ArgumentOutOfRangeException(nameof(ed25519SecretKey), ed25519SecretKey?.Length ?? 0, $"ed25519SecretKey must be either {PUBLIC_KEY_BYTES} or {SECRET_KEY_BYTES} bytes in length."); | ||
|
||
var sha512 = new Sha512Digest(); | ||
|
||
byte[] h = new byte[sha512.GetDigestSize()]; | ||
|
||
sha512.BlockUpdate(ed25519SecretKey, 0, SCALAR_BYTES); | ||
sha512.DoFinal(h, 0); | ||
|
||
PruneScalar(h); | ||
|
||
return h.AsSpan(0, 32).ToArray(); | ||
} | ||
|
||
private static void PruneScalar(byte[] n) | ||
{ | ||
n[0] &= 0xF8; | ||
n[SCALAR_BYTES - 1] &= 0x7F; | ||
n[SCALAR_BYTES - 1] |= 0x40; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
Beacon.Sdk/Core/Infrastructure/Cryptography/GenericHash.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
using System; | ||
using System.Text; | ||
|
||
using Org.BouncyCastle.Crypto.Digests; | ||
|
||
namespace Beacon.Sdk.Core.Infrastructure.Cryptography | ||
{ | ||
public static partial class GenericHash | ||
{ | ||
private const int BYTES_MIN = 0; | ||
private const int BYTES_MAX = 64; | ||
|
||
/// <summary>Hashes a message, using the BLAKE2b primitive.</summary> | ||
/// <param name="message">The message to be hashed.</param> | ||
/// <param name="resultLength">The size (in bytes) of the desired result.</param> | ||
/// <returns>Returns a byte array.</returns> | ||
/// <exception cref="ArgumentOutOfRangeException"></exception> | ||
public static byte[] Hash(string message, int resultLength) | ||
{ | ||
return Hash(Encoding.UTF8.GetBytes(message), resultLength); | ||
} | ||
|
||
/// <summary>Hashes a message, using the BLAKE2b primitive.</summary> | ||
/// <param name="message">The message to be hashed.</param> | ||
/// <param name="resultLength">The size (in bytes) of the desired result.</param> | ||
/// <returns>Returns a byte array.</returns> | ||
/// <exception cref="ArgumentOutOfRangeException"></exception> | ||
public static byte[] Hash(byte[] message, int resultLength) | ||
{ | ||
if (resultLength > BYTES_MAX || resultLength < BYTES_MIN) | ||
throw new ArgumentOutOfRangeException(nameof(resultLength), resultLength, $"bytes must be between {BYTES_MIN} and {BYTES_MAX} bytes in length."); | ||
|
||
var array = new byte[resultLength]; | ||
|
||
var blake2bDigest = new Blake2bDigest(resultLength * 8); | ||
blake2bDigest.BlockUpdate(message, 0, message.Length); | ||
blake2bDigest.DoFinal(array, 0); | ||
|
||
return array; | ||
} | ||
} | ||
} |
Oops, something went wrong.