Add rsa3072 implementation

This commit is contained in:
eyedeekay
2025-04-03 14:57:08 -04:00
parent 816df5642c
commit 35b47969b0
2 changed files with 160 additions and 17 deletions

View File

@ -1,34 +1,127 @@
package rsa
import "github.com/go-i2p/go-i2p/lib/crypto/types"
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha512"
"crypto/x509"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/samber/oops"
)
type (
RSA3072PrivateKey [786]byte
)
// Sign implements types.Signer.
// Len implements types.SigningPrivateKey.
func (r *RSA3072PrivateKey) Len() int {
panic("unimplemented")
}
// NewSigner implements types.SigningPrivateKey.
func (r *RSA3072PrivateKey) NewSigner() (types.Signer, error) {
panic("unimplemented")
}
// Sign implements types.Signer - signs data with SHA512 hash
func (r RSA3072PrivateKey) Sign(data []byte) (sig []byte, err error) {
panic("unimplemented")
// Hash the data with SHA-512 which is appropriate for RSA-3072
hash := sha512.Sum512(data)
return r.SignHash(hash[:])
}
// SignHash implements types.Signer.
// SignHash implements types.Signer - signs a pre-computed hash
func (r RSA3072PrivateKey) SignHash(h []byte) (sig []byte, err error) {
panic("unimplemented")
// Convert byte array to rsa.PrivateKey
privKey, err := r.toRSAPrivateKey()
if err != nil {
return nil, oops.Errorf("failed to parse RSA private key: %w", err)
}
// Sign the hash with PKCS#1 v1.5
sig, err = rsa.SignPKCS1v15(rand.Reader, privKey, crypto.SHA512, h)
if err != nil {
return nil, oops.Errorf("failed to sign hash: %w", err)
}
log.Debug("RSA-3072 signature created successfully")
return sig, nil
}
// Bytes implements types.PrivateKey.
// Bytes implements types.PrivateKey - returns raw key bytes
func (r RSA3072PrivateKey) Bytes() []byte {
panic("unimplemented")
return r[:]
}
// Public implements types.PrivateKey.
// Public implements types.PrivateKey - derives public key from private key
func (r RSA3072PrivateKey) Public() (types.SigningPublicKey, error) {
panic("unimplemented")
// Convert byte array to rsa.PrivateKey
privKey, err := r.toRSAPrivateKey()
if err != nil {
return nil, oops.Errorf("failed to parse RSA private key: %w", err)
}
// Extract public key from private key
pubBytes := x509.MarshalPKCS1PublicKey(&privKey.PublicKey)
if len(pubBytes) > 384 {
return nil, oops.Errorf("RSA public key exceeds expected size")
}
// Create and return RSA3072PublicKey
var pubKey RSA3072PublicKey
copy(pubKey[:], pubBytes)
log.Debug("RSA-3072 public key derived successfully")
return pubKey, nil
}
// Zero implements types.PrivateKey.
// Zero implements types.PrivateKey - securely erases key material
func (r RSA3072PrivateKey) Zero() {
panic("unimplemented")
// Overwrite private key material with zeros
for i := range r {
r[i] = 0
}
log.Debug("RSA-3072 private key securely erased")
}
// Helper method to convert byte array to rsa.PrivateKey
func (r RSA3072PrivateKey) toRSAPrivateKey() (*rsa.PrivateKey, error) {
// Parse PKCS#1 encoded private key
privKey, err := x509.ParsePKCS1PrivateKey(r[:])
if err != nil {
return nil, oops.Errorf("invalid RSA private key format: %w", err)
}
// Validate key size is 3072 bits (384 bytes)
if privKey.Size() != 384 {
return nil, oops.Errorf("unexpected RSA key size: got %d, want 384", privKey.Size())
}
return privKey, nil
}
// Generate creates a new RSA-3072 private key
func (r *RSA3072PrivateKey) Generate() (types.SigningPrivateKey, error) {
// Generate a new RSA-3072 private key
privateKey, err := rsa.GenerateKey(rand.Reader, 3072)
if err != nil {
return nil, oops.Errorf("failed to generate RSA-3072 key: %w", err)
}
// Convert to PKCS#1 format
privBytes := x509.MarshalPKCS1PrivateKey(privateKey)
if len(privBytes) > 786 {
return nil, oops.Errorf("RSA private key exceeds expected size")
}
// Copy bytes into fixed-size array
var newKey RSA3072PrivateKey
copy(newKey[:], privBytes)
log.Debug("RSA-3072 private key generated successfully")
return &newKey, nil
}
var _ types.PrivateKey = RSA3072PrivateKey{}

View File

@ -1,6 +1,14 @@
package rsa
import "github.com/go-i2p/go-i2p/lib/crypto/types"
import (
"crypto"
"crypto/rsa"
"crypto/sha512"
"math/big"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/samber/oops"
)
type (
RSA3072PublicKey [384]byte
@ -8,27 +16,69 @@ type (
// Verify implements types.Verifier.
func (r RSA3072PublicKey) Verify(data []byte, sig []byte) error {
panic("unimplemented")
// Hash the data with SHA512 (commonly used with RSA3072 in I2P)
hash := sha512.Sum512(data)
return r.VerifyHash(hash[:], sig)
}
// VerifyHash implements types.Verifier.
func (r RSA3072PublicKey) VerifyHash(h []byte, sig []byte) error {
panic("unimplemented")
pubKey, err := rsaPublicKeyFromBytes(r[:])
if err != nil {
return oops.Errorf("failed to parse RSA3072 public key: %w", err)
}
// For RSA3072, SHA512 is often used
hashed := h
if len(h) != sha512.Size {
// If we received a different hash size, warn but continue
log.Warnf("RSA3072 verification received unexpected hash size: %d", len(h))
}
err = rsa.VerifyPKCS1v15(pubKey, crypto.SHA512, hashed, sig)
if err != nil {
return oops.Errorf("RSA signature verification failed: %w", err)
}
return nil
}
// Bytes implements SigningPublicKey.
func (r RSA3072PublicKey) Bytes() []byte {
panic("unimplemented")
return r[:]
}
// Len implements SigningPublicKey.
func (r RSA3072PublicKey) Len() int {
panic("unimplemented")
return len(r)
}
// NewVerifier implements SigningPublicKey.
func (r RSA3072PublicKey) NewVerifier() (types.Verifier, error) {
panic("unimplemented")
// The RSA3072PublicKey itself implements the Verifier interface
return r, nil
}
// rsaPublicKeyFromBytes converts raw bytes to an rsa.PublicKey
func rsaPublicKeyFromBytes(data []byte) (*rsa.PublicKey, error) {
// For RSA3072, the public exponent is typically 65537 (0x10001)
e := int(65537)
// The modulus is the full key
n := new(big.Int).SetBytes(data)
pubKey := &rsa.PublicKey{
N: n,
E: e,
}
// Validate key size
bitSize := pubKey.Size() * 8
if bitSize < 3072 {
return nil, oops.Errorf("invalid RSA key size: %d (expected 3072)", bitSize)
}
return pubKey, nil
}
var _ types.PublicKey = RSA3072PublicKey{}