split the aes package into one file per component

This commit is contained in:
eyedeekay
2025-03-26 18:24:31 -04:00
parent 17a789bed7
commit 4533c2fd92
8 changed files with 228 additions and 201 deletions

View File

@ -28,9 +28,14 @@ payload :: data
*/
import (
"crypto/ecdsa"
"crypto/ed25519"
"fmt"
"github.com/go-i2p/go-i2p/lib/common/signature"
"github.com/go-i2p/go-i2p/lib/crypto/dsa"
elgamal "github.com/go-i2p/go-i2p/lib/crypto/elg"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/samber/oops"
"github.com/go-i2p/logger"
@ -38,7 +43,6 @@ import (
. "github.com/go-i2p/go-i2p/lib/common/certificate"
. "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/crypto"
)
var log = logger.GetGoI2PLogger()
@ -133,7 +137,7 @@ func (keyCertificate KeyCertificate) PublicKeyType() (pubkey_type int) {
// ConstructPublicKey returns a publicKey constructed using any excess data that may be stored in the KeyCertififcate.
// Returns enr errors encountered while parsing.
func (keyCertificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.RecievingPublicKey, err error) {
func (keyCertificate KeyCertificate) ConstructPublicKey(data []byte) (public_key types.RecievingPublicKey, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Constructing publicKey from keyCertificate")
@ -154,12 +158,12 @@ func (keyCertificate KeyCertificate) ConstructPublicKey(data []byte) (public_key
}
switch key_type {
case KEYCERT_CRYPTO_ELG:
var elg_key crypto.ElgPublicKey
var elg_key elgamal.ElgPublicKey
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = elg_key
log.Debug("Constructed ElgPublicKey")
case KEYCERT_CRYPTO_X25519:
var ed25519_key crypto.Ed25519PublicKey
var ed25519_key ed25519.Ed25519PublicKey
copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = ed25519_key
log.Debug("Constructed Ed25519PublicKey")
@ -225,7 +229,7 @@ func (keyCertificate *KeyCertificate) SigningPublicKeySize() int {
// ConstructSigningPublicKey returns a SingingPublicKey constructed using any excess data that may be stored in the KeyCertificate.
// Returns any errors encountered while parsing.
func (keyCertificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) {
func (keyCertificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key types.SigningPublicKey, err error) {
log.WithFields(logrus.Fields{
"input_length": len(data),
}).Debug("Constructing signingPublicKey from keyCertificate")
@ -246,17 +250,17 @@ func (keyCertificate KeyCertificate) ConstructSigningPublicKey(data []byte) (sig
}
switch signing_key_type {
case KEYCERT_SIGN_DSA_SHA1:
var dsa_key crypto.DSAPublicKey
var dsa_key dsa.DSAPublicKey
copy(dsa_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_DSA_SHA1_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = dsa_key
log.Debug("Constructed DSAPublicKey")
case KEYCERT_SIGN_P256:
var ec_p256_key crypto.ECP256PublicKey
var ec_p256_key ecdsa.ECP256PublicKey
copy(ec_p256_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p256_key
log.Debug("Constructed P256PublicKey")
case KEYCERT_SIGN_P384:
var ec_p384_key crypto.ECP384PublicKey
var ec_p384_key ecdsa.ECP384PublicKey
copy(ec_p384_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p384_key
log.Debug("Constructed P384PublicKey")
@ -285,12 +289,12 @@ func (keyCertificate KeyCertificate) ConstructSigningPublicKey(data []byte) (sig
log.Debug("Constructed RSA4096PublicKey")*/
panic("unimplemented RSA4096SigningPublicKey")
case KEYCERT_SIGN_ED25519:
var ed25519_key crypto.Ed25519PublicKey
var ed25519_key ed25519.Ed25519PublicKey
copy(ed25519_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_ED25519_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ed25519_key
log.Debug("Constructed Ed25519PublicKey")
case KEYCERT_SIGN_ED25519PH:
var ed25519ph_key crypto.Ed25519PublicKey
var ed25519ph_key ed25519.Ed25519PublicKey
copy(ed25519ph_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_ED25519PH_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ed25519ph_key
log.Debug("Constructed Ed25519PHPublicKey")

View File

@ -1,182 +0,0 @@
package aes
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/go-i2p/logger"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
var log = logger.GetGoI2PLogger()
// AESSymmetricKey represents a symmetric key for AES encryption/decryption
type AESSymmetricKey struct {
Key []byte // AES key (must be 16, 24, or 32 bytes for AES-128, AES-192, AES-256)
IV []byte // Initialization Vector (must be 16 bytes for AES)
}
// AESSymmetricEncrypter implements the Encrypter interface using AES
type AESSymmetricEncrypter struct {
Key []byte
IV []byte
}
// Encrypt encrypts data using AES-CBC with PKCS#7 padding
func (e *AESSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) {
log.WithField("data_length", len(data)).Debug("Encrypting data")
block, err := aes.NewCipher(e.Key)
if err != nil {
log.WithError(err).Error("Failed to create AES cipher")
return nil, err
}
plaintext := pkcs7Pad(data, aes.BlockSize)
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, e.IV)
mode.CryptBlocks(ciphertext, plaintext)
log.WithField("ciphertext_length", len(ciphertext)).Debug("Data encrypted successfully")
return ciphertext, nil
}
// AESSymmetricDecrypter implements the Decrypter interface using AES
type AESSymmetricDecrypter struct {
Key []byte
IV []byte
}
// Decrypt decrypts data using AES-CBC with PKCS#7 padding
func (d *AESSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) {
log.WithField("data_length", len(data)).Debug("Decrypting data")
block, err := aes.NewCipher(d.Key)
if err != nil {
log.WithError(err).Error("Failed to create AES cipher")
return nil, err
}
if len(data)%aes.BlockSize != 0 {
log.Error("Ciphertext is not a multiple of the block size")
return nil, oops.Errorf("ciphertext is not a multiple of the block size")
}
plaintext := make([]byte, len(data))
mode := cipher.NewCBCDecrypter(block, d.IV)
mode.CryptBlocks(plaintext, data)
plaintext, err = pkcs7Unpad(plaintext)
if err != nil {
log.WithError(err).Error("Failed to unpad plaintext")
return nil, err
}
log.WithField("plaintext_length", len(plaintext)).Debug("Data decrypted successfully")
return plaintext, nil
}
// NewEncrypter creates a new AESSymmetricEncrypter
func (k *AESSymmetricKey) NewEncrypter() (types.Encrypter, error) {
log.Debug("Creating new AESSymmetricEncrypter")
return &AESSymmetricEncrypter{
Key: k.Key,
IV: k.IV,
}, nil
}
// Len returns the length of the key
func (k *AESSymmetricKey) Len() int {
return len(k.Key)
}
// NewDecrypter creates a new AESSymmetricDecrypter
func (k *AESSymmetricKey) NewDecrypter() (types.Decrypter, error) {
return &AESSymmetricDecrypter{
Key: k.Key,
IV: k.IV,
}, nil
}
func pkcs7Pad(data []byte, blockSize int) []byte {
log.WithFields(logrus.Fields{
"data_length": len(data),
"block_size": blockSize,
}).Debug("Applying PKCS#7 padding")
padding := blockSize - (len(data) % blockSize)
padText := bytes.Repeat([]byte{byte(padding)}, padding)
padded := append(data, padText...)
log.WithField("padded_length", len(padded)).Debug("PKCS#7 padding applied")
return append(data, padText...)
}
func pkcs7Unpad(data []byte) ([]byte, error) {
log.WithField("data_length", len(data)).Debug("Removing PKCS#7 padding")
length := len(data)
if length == 0 {
log.Error("Data is empty")
return nil, oops.Errorf("data is empty")
}
padding := int(data[length-1])
if padding == 0 || padding > aes.BlockSize {
log.WithField("padding", padding).Error("Invalid padding")
return nil, oops.Errorf("invalid padding")
}
paddingStart := length - padding
for i := paddingStart; i < length; i++ {
if data[i] != byte(padding) {
log.Error("Invalid padding")
return nil, oops.Errorf("invalid padding")
}
}
unpadded := data[:paddingStart]
log.WithField("unpadded_length", len(unpadded)).Debug("PKCS#7 padding removed")
return unpadded, nil
}
// EncryptNoPadding encrypts data using AES-CBC without padding
func (e *AESSymmetricEncrypter) EncryptNoPadding(data []byte) ([]byte, error) {
if len(data)%aes.BlockSize != 0 {
return nil, oops.Errorf("data length must be a multiple of block size")
}
block, err := aes.NewCipher(e.Key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, len(data))
mode := cipher.NewCBCEncrypter(block, e.IV)
mode.CryptBlocks(ciphertext, data)
return ciphertext, nil
}
// DecryptNoPadding decrypts data using AES-CBC without padding
func (d *AESSymmetricDecrypter) DecryptNoPadding(data []byte) ([]byte, error) {
if len(data)%aes.BlockSize != 0 {
return nil, oops.Errorf("data length must be a multiple of block size")
}
block, err := aes.NewCipher(d.Key)
if err != nil {
return nil, err
}
plaintext := make([]byte, len(data))
mode := cipher.NewCBCDecrypter(block, d.IV)
mode.CryptBlocks(plaintext, data)
return plaintext, nil
}
func NewCipher(c []byte) (cipher.Block, error) {
return aes.NewCipher(c)
}

View File

@ -0,0 +1,68 @@
package aes
import (
"crypto/aes"
"crypto/cipher"
"github.com/go-i2p/logger"
"github.com/samber/oops"
)
var log = logger.GetGoI2PLogger()
// AESSymmetricDecrypter implements the Decrypter interface using AES
type AESSymmetricDecrypter struct {
Key []byte
IV []byte
}
// Decrypt decrypts data using AES-CBC with PKCS#7 padding
func (d *AESSymmetricDecrypter) Decrypt(data []byte) ([]byte, error) {
log.WithField("data_length", len(data)).Debug("Decrypting data")
block, err := aes.NewCipher(d.Key)
if err != nil {
log.WithError(err).Error("Failed to create AES cipher")
return nil, err
}
if len(data)%aes.BlockSize != 0 {
log.Error("Ciphertext is not a multiple of the block size")
return nil, oops.Errorf("ciphertext is not a multiple of the block size")
}
plaintext := make([]byte, len(data))
mode := cipher.NewCBCDecrypter(block, d.IV)
mode.CryptBlocks(plaintext, data)
plaintext, err = pkcs7Unpad(plaintext)
if err != nil {
log.WithError(err).Error("Failed to unpad plaintext")
return nil, err
}
log.WithField("plaintext_length", len(plaintext)).Debug("Data decrypted successfully")
return plaintext, nil
}
// DecryptNoPadding decrypts data using AES-CBC without padding
func (d *AESSymmetricDecrypter) DecryptNoPadding(data []byte) ([]byte, error) {
if len(data)%aes.BlockSize != 0 {
return nil, oops.Errorf("data length must be a multiple of block size")
}
block, err := aes.NewCipher(d.Key)
if err != nil {
return nil, err
}
plaintext := make([]byte, len(data))
mode := cipher.NewCBCDecrypter(block, d.IV)
mode.CryptBlocks(plaintext, data)
return plaintext, nil
}
func NewCipher(c []byte) (cipher.Block, error) {
return aes.NewCipher(c)
}

View File

@ -0,0 +1,51 @@
package aes
import (
"crypto/aes"
"crypto/cipher"
"github.com/samber/oops"
)
// AESSymmetricEncrypter implements the Encrypter interface using AES
type AESSymmetricEncrypter struct {
Key []byte
IV []byte
}
// Encrypt encrypts data using AES-CBC with PKCS#7 padding
func (e *AESSymmetricEncrypter) Encrypt(data []byte) ([]byte, error) {
log.WithField("data_length", len(data)).Debug("Encrypting data")
block, err := aes.NewCipher(e.Key)
if err != nil {
log.WithError(err).Error("Failed to create AES cipher")
return nil, err
}
plaintext := pkcs7Pad(data, aes.BlockSize)
ciphertext := make([]byte, len(plaintext))
mode := cipher.NewCBCEncrypter(block, e.IV)
mode.CryptBlocks(ciphertext, plaintext)
log.WithField("ciphertext_length", len(ciphertext)).Debug("Data encrypted successfully")
return ciphertext, nil
}
// EncryptNoPadding encrypts data using AES-CBC without padding
func (e *AESSymmetricEncrypter) EncryptNoPadding(data []byte) ([]byte, error) {
if len(data)%aes.BlockSize != 0 {
return nil, oops.Errorf("data length must be a multiple of block size")
}
block, err := aes.NewCipher(e.Key)
if err != nil {
return nil, err
}
ciphertext := make([]byte, len(data))
mode := cipher.NewCBCEncrypter(block, e.IV)
mode.CryptBlocks(ciphertext, data)
return ciphertext, nil
}

31
lib/crypto/aes/aes_key.go Normal file
View File

@ -0,0 +1,31 @@
package aes
import "github.com/go-i2p/go-i2p/lib/crypto/types"
// AESSymmetricKey represents a symmetric key for AES encryption/decryption
type AESSymmetricKey struct {
Key []byte // AES key (must be 16, 24, or 32 bytes for AES-128, AES-192, AES-256)
IV []byte // Initialization Vector (must be 16 bytes for AES)
}
// NewEncrypter creates a new AESSymmetricEncrypter
func (k *AESSymmetricKey) NewEncrypter() (types.Encrypter, error) {
log.Debug("Creating new AESSymmetricEncrypter")
return &AESSymmetricEncrypter{
Key: k.Key,
IV: k.IV,
}, nil
}
// Len returns the length of the key
func (k *AESSymmetricKey) Len() int {
return len(k.Key)
}
// NewDecrypter creates a new AESSymmetricDecrypter
func (k *AESSymmetricKey) NewDecrypter() (types.Decrypter, error) {
return &AESSymmetricDecrypter{
Key: k.Key,
IV: k.IV,
}, nil
}

View File

@ -0,0 +1,49 @@
package aes
import (
"bytes"
"crypto/aes"
"github.com/samber/oops"
"github.com/sirupsen/logrus"
)
func pkcs7Pad(data []byte, blockSize int) []byte {
log.WithFields(logrus.Fields{
"data_length": len(data),
"block_size": blockSize,
}).Debug("Applying PKCS#7 padding")
padding := blockSize - (len(data) % blockSize)
padText := bytes.Repeat([]byte{byte(padding)}, padding)
padded := append(data, padText...)
log.WithField("padded_length", len(padded)).Debug("PKCS#7 padding applied")
return append(data, padText...)
}
func pkcs7Unpad(data []byte) ([]byte, error) {
log.WithField("data_length", len(data)).Debug("Removing PKCS#7 padding")
length := len(data)
if length == 0 {
log.Error("Data is empty")
return nil, oops.Errorf("data is empty")
}
padding := int(data[length-1])
if padding == 0 || padding > aes.BlockSize {
log.WithField("padding", padding).Error("Invalid padding")
return nil, oops.Errorf("invalid padding")
}
paddingStart := length - padding
for i := paddingStart; i < length; i++ {
if data[i] != byte(padding) {
log.Error("Invalid padding")
return nil, oops.Errorf("invalid padding")
}
}
unpadded := data[:paddingStart]
log.WithField("unpadded_length", len(unpadded)).Debug("PKCS#7 padding removed")
return unpadded, nil
}

View File

@ -1,4 +1,4 @@
package crypto
package dsa
import (
"crypto/dsa"
@ -7,9 +7,13 @@ import (
"io"
"math/big"
"github.com/go-i2p/go-i2p/lib/crypto/types"
"github.com/go-i2p/logger"
"github.com/sirupsen/logrus"
)
var log = logger.GetGoI2PLogger()
var dsap = new(big.Int).SetBytes([]byte{
0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c,
0x30, 0x26, 0xe9, 0xb8, 0xed, 0x92, 0xfa, 0xd0, 0xa6, 0x9c, 0xc8, 0x86, 0xd5, 0xbf, 0x80, 0x15,
@ -100,7 +104,7 @@ func (k DSAPublicKey) Bytes() []byte {
}
// create a new dsa verifier
func (k DSAPublicKey) NewVerifier() (v Verifier, err error) {
func (k DSAPublicKey) NewVerifier() (v types.Verifier, err error) {
log.Debug("Creating new DSA verifier")
v = &DSAVerifier{
k: createDSAPublicKey(new(big.Int).SetBytes(k[:])),
@ -134,11 +138,11 @@ func (v *DSAVerifier) VerifyHash(h, sig []byte) (err error) {
} else {
// invalid signature
log.Warn("Invalid DSA signature")
err = ErrInvalidSignature
err = types.ErrInvalidSignature
}
} else {
log.Error("Bad DSA signature size")
err = ErrBadSignatureSize
err = types.ErrBadSignatureSize
}
return
}
@ -154,7 +158,7 @@ type DSASigner struct {
type DSAPrivateKey [20]byte
// create a new dsa signer
func (k DSAPrivateKey) NewSigner() (s Signer, err error) {
func (k DSAPrivateKey) NewSigner() (s types.Signer, err error) {
log.Debug("Creating new DSA signer")
s = &DSASigner{
k: createDSAPrivkey(new(big.Int).SetBytes(k[:])),
@ -166,7 +170,7 @@ func (k DSAPrivateKey) Public() (pk DSAPublicKey, err error) {
p := createDSAPrivkey(new(big.Int).SetBytes(k[:]))
if p == nil {
log.Error("Invalid DSA private key format")
err = ErrInvalidKeyFormat
err = types.ErrInvalidKeyFormat
} else {
copy(pk[:], p.Y.Bytes())
log.Debug("DSA public key derived successfully")

View File

@ -1,9 +1,11 @@
package crypto
package dsa
import (
"crypto/rand"
"io"
"testing"
"github.com/go-i2p/go-i2p/lib/crypto/types"
)
func TestDSA(t *testing.T) {
@ -27,13 +29,13 @@ func TestDSA(t *testing.T) {
io.ReadFull(rand.Reader, data)
if err == nil {
var sig []byte
var signer Signer
var signer types.Signer
signer, err = sk.NewSigner()
if err == nil {
sig, err = signer.Sign(data)
if err == nil {
t.Logf("sig=%q", sig)
var verify Verifier
var verify types.Verifier
verify, err = pk.NewVerifier()
if err == nil {
err = verify.Verify(data, sig)