diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 0000000..04d7376
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,31 @@
+name: .NET Build and Test
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+
+ - name: Set up .NET SDK
+ uses: actions/setup-dotnet@v1
+ with:
+ dotnet-version: '8.0'
+
+ - name: Restore dependencies
+ run: dotnet restore
+
+ - name: Build the project
+ run: dotnet build --configuration Release
+
+ - name: Run tests
+ run: dotnet test --configuration Release --no-build --verbosity normal
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cbca89e..07b9753 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## [Unreleased]
+## [1.1.1] - 2025-01-01
### Added
- New method for range proofs (`ProveRange` and `VerifyRange`).
@@ -8,7 +8,7 @@
- Support for proving set membership (`ProveSetMembership` and `VerifySetMembership`).
### Changed
-- Updated HMAC implementation to use more secure random salts.
+- Refined HMAC implementation to retrieve the secret key from environment variables for enhanced security and flexibility.
### Fixed
- Bug in age verification logic that caused incorrect validation for dates close to the required age.
diff --git a/README.md b/README.md
index 2e2b141..9ba9ec7 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,12 @@
- **Proof of Age**: Prove that your age is above a certain threshold without revealing your actual birthdate.
- **Proof of Balance**: Prove that you have sufficient balance to make a transaction without revealing your full balance.
+- **Proof of Membership**: Prove that a given value belongs to a set of valid values (e.g., proving you belong to a specific group).
+- **Proof of Range**: Prove that a value lies within a specified range without revealing the exact value.
+- **Proof of Time Condition**: Prove that an event occurred before or after a specified date without revealing the event date.
- **Secure Hashing**: Uses SHA-256 hashing combined with a random salt to ensure secure and non-reversible proofs.
+
## Installation
You can install **ZkpSharp** via NuGet. Run the following command in your project directory:
@@ -15,6 +19,45 @@ You can install **ZkpSharp** via NuGet. Run the following command in your projec
```bash
dotnet add package ZkpSharp
```
+
+## Setup
+
+Before using the ZkpSharp library, you need to configure a secret key for HMAC (SHA-256) hashing. This key is required for generating and verifying proofs.
+
+### Setting Up the HMAC Key in Code
+
+Instead of using environment variables, you can pass the HMAC secret key directly when creating the ProofProvider. The key should be a 256-bit key (32 bytes) encoded in Base64.
+
+Here’s an example of how to configure the HMAC key directly in your application:
+
+```csharp
+using ZkpSharp;
+using ZkpSharp.Security;
+using System;
+
+class Program
+{
+ static void Main()
+ {
+ // Example base64-encoded HMAC secret key (256 bits / 32 bytes)
+ string hmacSecretKeyBase64 = "your-base64-encoded-key-here";
+
+ // Create an instance of ProofProvider with the provided HMAC key
+ var proofProvider = new ProofProvider(hmacSecretKeyBase64);
+
+ var zkp = new ZKP(proofProvider);
+ var dateOfBirth = new DateTime(2000, 1, 1); // The user's date of birth
+
+ // Generate proof of age
+ var (proof, salt) = zkp.ProveAge(dateOfBirth);
+
+ // Verify the proof of age
+ bool isValid = zkp.VerifyAge(proof, dateOfBirth, salt);
+ Console.WriteLine($"Age proof valid: {isValid}");
+ }
+}
+```
+
## Usage
### Proof of Age
@@ -70,14 +113,16 @@ class Program
}
}
```
+
## Contributing
We welcome contributions! To contribute:
- 1. Fork the repository.
- 2. Create a new branch for your changes (git checkout -b feature/your-feature).
- 3. Commit your changes (git commit -m 'Add new feature').
- 4. Push to your branch (git push origin feature/your-feature).
- 5. Create a pull request.
+
+1. Fork the repository.
+2. Create a new branch for your changes (`git checkout -b feature/your-feature`).
+3. Commit your changes (`git commit -m 'Add new feature'`).
+4. Push to your branch (`git push origin feature/your-feature`).
+5. Create a pull request.
Please ensure that your code passes all tests and adheres to the code style of the project.
@@ -85,11 +130,6 @@ Please ensure that your code passes all tests and adheres to the code style of t
This project is licensed under the MIT License - see the LICENSE file for details.
-## Roadmap
- • Add more proof types (e.g., Proof of Identity, Proof of Transaction History).
- • Improve performance and scalability for large datasets.
- • Enhance security features (e.g., multi-factor authentication for proofs).
-
## Contact
For questions, issues, or suggestions, feel free to open an issue or contact Azimbek Sagynbaev at [sagynbaev6@gmail.com].
\ No newline at end of file
diff --git a/ZkpSharp.Tests/ZKPTests.cs b/ZkpSharp.Tests/ZKPTests.cs
index 728b685..8e57788 100644
--- a/ZkpSharp.Tests/ZKPTests.cs
+++ b/ZkpSharp.Tests/ZKPTests.cs
@@ -10,7 +10,7 @@ public class ZKPTests
[Fact]
public void TestProveAndVerifyAge_ValidAge_ShouldPass()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
var dateOfBirth = new DateTime(2000, 1, 1); // Age 25
var (proof, salt) = zkp.ProveAge(dateOfBirth);
@@ -21,7 +21,7 @@ public void TestProveAndVerifyAge_ValidAge_ShouldPass()
[Fact]
public void TestProveAndVerifyAge_InsufficientAge_ShouldFail()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
var dateOfBirth = new DateTime(2010, 1, 1); // Age 15
@@ -32,7 +32,7 @@ public void TestProveAndVerifyAge_InsufficientAge_ShouldFail()
[Fact]
public void TestProveAndVerifyBalance_ValidBalance_ShouldPass()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
double userBalance = 1000.0;
double requestedAmount = 500.0;
@@ -46,7 +46,7 @@ public void TestProveAndVerifyBalance_ValidBalance_ShouldPass()
[Fact]
public void TestProveAndVerifyBalance_InsufficientBalance_ShouldFail()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
double userBalance = 300.0;
double requestedAmount = 500.0;
@@ -59,7 +59,7 @@ public void TestProveAndVerifyBalance_InsufficientBalance_ShouldFail()
[Fact]
public void TestBalanceVerificationWithSalt_ValidBalance_ShouldPass()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
double userBalance = 1000.0;
double requestedAmount = 500.0;
@@ -71,7 +71,7 @@ public void TestBalanceVerificationWithSalt_ValidBalance_ShouldPass()
[Fact]
public void TestBalanceVerificationWithSalt_InsufficientBalance_ShouldFail()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
double userBalance = 100.0;
double requestedAmount = 150.0;
@@ -83,7 +83,7 @@ public void TestBalanceVerificationWithSalt_InsufficientBalance_ShouldFail()
[Fact]
public void TestProveAndVerifyAge_InvalidSalt_ShouldFail()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
var dateOfBirth = new DateTime(2000, 1, 1); // Возраст 25 лет
var (proof, salt) = zkp.ProveAge(dateOfBirth);
@@ -96,7 +96,7 @@ public void TestProveAndVerifyAge_InvalidSalt_ShouldFail()
[Fact]
public void TestBalanceVerificationWithSalt_InvalidSalt_ShouldFail()
{
- var proofProvider = new ProofProvider();
+ var proofProvider = new ProofProvider("hmacSecretKeyBase64");
var zkp = new ZKP(proofProvider);
double userBalance = 1000.0;
double requestedAmount = 500.0;
@@ -105,5 +105,8 @@ public void TestBalanceVerificationWithSalt_InvalidSalt_ShouldFail()
string incorrectSalt = Guid.NewGuid().ToString();
Assert.False(zkp.VerifyBalance(proof, requestedAmount, incorrectSalt, userBalance), "Proof should fail due to incorrect salt");
}
+
+ // TODO: Add more tests for:
+ // ProveRange, VerifyRange, ProveTimestamp, VerifyTimestamp, ProveSetMembership, VerifySetMembership.
}
}
\ No newline at end of file
diff --git a/ZkpSharp/Core/ZKP.cs b/ZkpSharp/Core/ZKP.cs
index 5cdc20f..5d94e2d 100644
--- a/ZkpSharp/Core/ZKP.cs
+++ b/ZkpSharp/Core/ZKP.cs
@@ -58,5 +58,79 @@ public bool VerifyBalance(string proof, double requestedAmount, string salt, dou
string calculatedProof = _proofProvider.GenerateHMAC(balance.ToString() + salt);
return _proofProvider.SecureEqual(calculatedProof, proof) && balance >= requestedAmount;
}
+
+ // Proof of Membership
+ public string ProveMembership(string value, string[] validValues)
+ {
+ string salt = _proofProvider.GenerateSalt();
+ var validValueHash = validValues.Select(v => _proofProvider.GenerateHMAC(v)).ToArray();
+
+ foreach (var hash in validValueHash)
+ {
+ if (_proofProvider.SecureEqual(_proofProvider.GenerateHMAC(value + salt), hash))
+ {
+ return salt;
+ }
+ }
+
+ throw new ArgumentException("Value does not belong to the set.");
+ }
+
+ public bool VerifyMembership(string value, string salt, string[] validValues)
+ {
+ var validValueHash = validValues.Select(v => _proofProvider.GenerateHMAC(v)).ToArray();
+ string proof = _proofProvider.GenerateHMAC(value + salt);
+
+ return validValueHash.Contains(proof);
+ }
+
+ // Proof of Range
+ public string ProveRange(double value, double minValue, double maxValue)
+ {
+ if (value < minValue || value > maxValue)
+ {
+ throw new ArgumentException("Value out of range.");
+ }
+
+ string salt = _proofProvider.GenerateSalt();
+ string proof = _proofProvider.GenerateHMAC(value.ToString() + salt);
+ return proof;
+ }
+
+ public bool VerifyRange(string proof, double minValue, double maxValue, double value)
+ {
+ if (value < minValue || value > maxValue)
+ {
+ return false;
+ }
+
+ string calculatedProof = _proofProvider.GenerateHMAC(value.ToString() + _proofProvider.GenerateSalt());
+ return _proofProvider.SecureEqual(proof, calculatedProof);
+ }
+
+
+ // Proof of Time Condition
+ public string ProveTimeCondition(DateTime eventDate, DateTime conditionDate)
+ {
+ if (eventDate < conditionDate)
+ {
+ throw new ArgumentException("Event does not meet the time condition.");
+ }
+
+ string salt = _proofProvider.GenerateSalt();
+ string proof = _proofProvider.GenerateHMAC(eventDate.ToString("yyyy-MM-dd") + salt);
+ return proof;
+ }
+
+ public bool VerifyTimeCondition(string proof, DateTime eventDate, DateTime conditionDate, string salt)
+ {
+ if (eventDate < conditionDate)
+ {
+ return false;
+ }
+
+ string calculatedProof = _proofProvider.GenerateHMAC(eventDate.ToString("yyyy-MM-dd") + salt);
+ return _proofProvider.SecureEqual(proof, calculatedProof);
+ }
}
}
\ No newline at end of file
diff --git a/ZkpSharp/Security/ProofProvider.cs b/ZkpSharp/Security/ProofProvider.cs
index 0a1b993..c265b2a 100644
--- a/ZkpSharp/Security/ProofProvider.cs
+++ b/ZkpSharp/Security/ProofProvider.cs
@@ -14,9 +14,9 @@ public class ProofProvider : IProofProvider
{
private readonly byte[] _hmacKey;
- public ProofProvider()
+ public ProofProvider(string hmacSecretKeyBase64)
{
- _hmacKey = LoadHmacKey();
+ _hmacKey = Convert.FromBase64String(hmacSecretKeyBase64);
}
public string GenerateSalt()
@@ -50,11 +50,5 @@ public bool SecureEqual(string a, string b)
return diff == 0;
}
-
- private byte[] LoadHmacKey()
- {
- // Load HMAC key from secure storage
- return new byte[32]; // Here we just return a dummy key
- }
}
}
\ No newline at end of file
diff --git a/ZkpSharp/ZkpSharp.csproj b/ZkpSharp/ZkpSharp.csproj
index 013cc5b..f443697 100644
--- a/ZkpSharp/ZkpSharp.csproj
+++ b/ZkpSharp/ZkpSharp.csproj
@@ -4,7 +4,7 @@
net8.0
enable
enable
- 1.1.0
+ 1.1.1
README.md