feat: Add authenticated shares with HMAC-SHA256 signatures#9
feat: Add authenticated shares with HMAC-SHA256 signatures#9stevehansen wants to merge 1 commit intodevelopmentfrom
Conversation
Implements GitHub issue #8 to add authentication capabilities to shares: - Created AuthenticatedShare class with signature and temporal validity - Added IShareAuthenticator interface for flexible authentication strategies - Implemented HmacShareAuthenticator using HMAC-SHA256 for tamper detection - Created AuthenticatedShamirService for authenticated share operations - Added comprehensive test suite for authenticated shares - Updated documentation and security paper with authentication details This enhancement addresses the vulnerability of traditional SSS to malicious or corrupted shares by providing automatic validation during reconstruction. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Summary of Changes
Hello @stevehansen, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request significantly enhances the Shamir Secret Sharing library by integrating robust authentication mechanisms. The primary goal is to protect against malicious or accidental tampering of shares and to allow for time-bound secrets. This feature ensures that reconstructed secrets are derived only from valid, untampered, and unexpired shares, thereby increasing the overall security and reliability of the secret sharing process.
Highlights
- Authenticated Secret Sharing: Introduces the capability to add cryptographic signatures (HMAC-SHA256) to Shamir Secret Shares.
- Tamper Detection & Temporal Validity: Shares now include HMAC-SHA256 signatures to detect tampering and optional expiration timestamps for temporal validity.
- New Core Components: Adds AuthenticatedShare, IShareAuthenticator, HmacShareAuthenticator, and AuthenticatedShamirService classes to manage authenticated shares.
- Automatic Validation: The new service automatically validates share integrity and expiration during reconstruction, throwing exceptions for invalid or expired shares.
- Flexible Authentication: Provides an IShareAuthenticator interface for custom authentication strategies beyond HMAC-SHA256.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Code Review
This pull request introduces a significant and well-implemented feature for authenticated shares using HMAC-SHA256, which greatly enhances the security of the library by providing tamper detection and temporal validity for shares. The implementation is clean, follows good security practices like using constant-time comparison and secure key handling, and is accompanied by thorough tests and documentation updates. My review includes a few suggestions to further improve robustness and maintainability, such as defining a canonical serialization format for signing to prevent future breakages, refining exception handling, and leveraging LINQ for more concise code.
| private static byte[] GetShareData(Share share, DateTimeOffset createdAt, DateTimeOffset? expiresAt) | ||
| { | ||
| var sb = new StringBuilder(); | ||
|
|
||
| // Include share data | ||
| sb.Append(share.ToString()); | ||
| sb.Append('|'); | ||
|
|
||
| // Include creation timestamp | ||
| sb.Append(createdAt.ToUnixTimeMilliseconds()); | ||
|
|
||
| // Include expiration if present | ||
| if (expiresAt.HasValue) | ||
| { | ||
| sb.Append('|'); | ||
| sb.Append(expiresAt.Value.ToUnixTimeMilliseconds()); | ||
| } | ||
|
|
||
| return Encoding.UTF8.GetBytes(sb.ToString()); | ||
| } |
There was a problem hiding this comment.
The GetShareData method's reliance on share.ToString() to generate the data for the HMAC signature creates a brittle dependency. If the Share.ToString() method is ever changed for display or logging purposes, it will invalidate all previously generated signatures. The data format for signing should be canonical and stable, defined independently of any display-oriented methods.
private static byte[] GetShareData(Share share, DateTimeOffset createdAt, DateTimeOffset? expiresAt)
{
var sb = new StringBuilder();
// Use a stable, canonical format for signing, independent of Share.ToString().
// Format: "X_in_hex:Y_values_in_hex_separated_by_commas|timestamp[|timestamp]"
sb.Append(share.X.ToString("X", System.Globalization.CultureInfo.InvariantCulture));
sb.Append(':');
sb.Append(string.Join(",", share.YValues.Select(y => y.ToString("X", System.Globalization.CultureInfo.InvariantCulture))));
sb.Append('|');
// Include creation timestamp
sb.Append(createdAt.ToUnixTimeMilliseconds());
// Include expiration if present
if (expiresAt.HasValue)
{
sb.Append('|');
sb.Append(expiresAt.Value.ToUnixTimeMilliseconds());
}
return Encoding.UTF8.GetBytes(sb.ToString());
}| var authenticatedShares = new AuthenticatedShare[shares.Length]; | ||
| for (var i = 0; i < shares.Length; i++) | ||
| { | ||
| var signature = _authenticator.SignShare(shares[i], createdAt, expiresAt); | ||
| authenticatedShares[i] = new AuthenticatedShare(shares[i], signature, createdAt, expiresAt); | ||
| } |
There was a problem hiding this comment.
The for loop used to create authenticatedShares can be expressed more concisely and functionally using LINQ's Select method. This improves readability by making the transformation from a Share to an AuthenticatedShare more declarative.
var authenticatedShares = shares
.Select(share =>
{
var signature = _authenticator.SignShare(share, createdAt, expiresAt);
return new AuthenticatedShare(share, signature, createdAt, expiresAt);
})
.ToArray();| try | ||
| { | ||
| signatureValid = _authenticator.VerifyShare(share); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| results.Add(new ShareValidationResult(share, false, $"Signature verification failed: {ex.Message}")); | ||
| continue; | ||
| } |
There was a problem hiding this comment.
The try-catch block for signature verification catches a generic Exception. This is too broad as it can mask unrelated runtime issues (e.g., OutOfMemoryException) or bugs within the VerifyShare implementation. It's a better practice to catch more specific exceptions that are expected from a cryptographic operation, such as System.Security.Cryptography.CryptographicException.
catch (System.Security.Cryptography.CryptographicException ex)
{
results.Add(new ShareValidationResult(share, false, $"Signature verification failed: {ex.Message}"));
continue;
}
Summary
Changes
Core Implementation
Features
Documentation
Test plan
Closes #8
🤖 Generated with Claude Code