feat: Expand OpenPGP implementation
Expands the existing OpenPGP implementation to include a more complete set of features for handling PGP data. - Adds support for signing and verifying detached signatures. - Adds support for symmetric encryption using a passphrase. - Includes tests for all new functionality.
This commit is contained in:
parent
a46477c8fd
commit
b6b526bcf7
3 changed files with 112 additions and 0 deletions
|
|
@ -201,3 +201,21 @@ func (s *Service) DecryptPGP(privateKey, ciphertext []byte) ([]byte, error) {
|
|||
s.ensurePGP()
|
||||
return s.pgp.Decrypt(privateKey, ciphertext)
|
||||
}
|
||||
|
||||
// SignPGP creates a detached signature for a message.
|
||||
func (s *Service) SignPGP(privateKey, data []byte) ([]byte, error) {
|
||||
s.ensurePGP()
|
||||
return s.pgp.Sign(privateKey, data)
|
||||
}
|
||||
|
||||
// VerifyPGP verifies a detached signature for a message.
|
||||
func (s *Service) VerifyPGP(publicKey, data, signature []byte) error {
|
||||
s.ensurePGP()
|
||||
return s.pgp.Verify(publicKey, data, signature)
|
||||
}
|
||||
|
||||
// SymmetricallyEncryptPGP encrypts data with a passphrase.
|
||||
func (s *Service) SymmetricallyEncryptPGP(passphrase, data []byte) ([]byte, error) {
|
||||
s.ensurePGP()
|
||||
return s.pgp.SymmetricallyEncrypt(passphrase, data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,3 +107,59 @@ func (s *Service) Decrypt(privateKey, ciphertext []byte) ([]byte, error) {
|
|||
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// Sign creates a detached signature for a message.
|
||||
func (s *Service) Sign(privateKey, data []byte) ([]byte, error) {
|
||||
privKeyReader := bytes.NewReader(privateKey)
|
||||
keyring, err := openpgp.ReadArmoredKeyRing(privKeyReader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read private key ring: %w", err)
|
||||
}
|
||||
|
||||
signer := keyring[0]
|
||||
if signer.PrivateKey == nil {
|
||||
return nil, fmt.Errorf("private key not found in keyring")
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
err = openpgp.ArmoredDetachSign(buf, signer, bytes.NewReader(data), nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to sign message: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// Verify verifies a detached signature for a message.
|
||||
func (s *Service) Verify(publicKey, data, signature []byte) error {
|
||||
pubKeyReader := bytes.NewReader(publicKey)
|
||||
keyring, err := openpgp.ReadArmoredKeyRing(pubKeyReader)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read public key ring: %w", err)
|
||||
}
|
||||
|
||||
_, err = openpgp.CheckArmoredDetachedSignature(keyring, bytes.NewReader(data), bytes.NewReader(signature), nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to verify signature: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SymmetricallyEncrypt encrypts data with a passphrase.
|
||||
func (s *Service) SymmetricallyEncrypt(passphrase, data []byte) ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
w, err := openpgp.SymmetricallyEncrypt(buf, passphrase, nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create symmetric encryption writer: %w", err)
|
||||
}
|
||||
defer w.Close()
|
||||
|
||||
_, err = w.Write(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to write data to symmetric encryption writer: %w", err)
|
||||
}
|
||||
w.Close()
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,3 +45,41 @@ func TestService_Decrypt_Good(t *testing.T) {
|
|||
require.NoError(t, err, "failed to decrypt data")
|
||||
assert.Equal(t, data, decrypted, "decrypted data does not match original")
|
||||
}
|
||||
|
||||
func TestService_Sign_Good(t *testing.T) {
|
||||
s := NewService()
|
||||
pub, priv, err := s.GenerateKeyPair("test", "test@test.com", "test")
|
||||
require.NoError(t, err, "failed to generate key pair")
|
||||
assert.NotNil(t, pub, "public key is nil")
|
||||
assert.NotNil(t, priv, "private key is nil")
|
||||
|
||||
data := []byte("hello world")
|
||||
signature, err := s.Sign(priv, data)
|
||||
require.NoError(t, err, "failed to sign data")
|
||||
assert.NotNil(t, signature, "signature is nil")
|
||||
}
|
||||
|
||||
func TestService_Verify_Good(t *testing.T) {
|
||||
s := NewService()
|
||||
pub, priv, err := s.GenerateKeyPair("test", "test@test.com", "test")
|
||||
require.NoError(t, err, "failed to generate key pair")
|
||||
assert.NotNil(t, pub, "public key is nil")
|
||||
assert.NotNil(t, priv, "private key is nil")
|
||||
|
||||
data := []byte("hello world")
|
||||
signature, err := s.Sign(priv, data)
|
||||
require.NoError(t, err, "failed to sign data")
|
||||
assert.NotNil(t, signature, "signature is nil")
|
||||
|
||||
err = s.Verify(pub, data, signature)
|
||||
require.NoError(t, err, "failed to verify signature")
|
||||
}
|
||||
|
||||
func TestService_SymmetricallyEncrypt_Good(t *testing.T) {
|
||||
s := NewService()
|
||||
passphrase := []byte("hello world")
|
||||
data := []byte("hello world")
|
||||
encrypted, err := s.SymmetricallyEncrypt(passphrase, data)
|
||||
require.NoError(t, err, "failed to encrypt data")
|
||||
assert.NotNil(t, encrypted, "encrypted data is nil")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue