WIP crypto prototyping

This commit is contained in:
2024-08-13 15:18:22 +02:00
parent f4e568479e
commit a5dda01654
5 changed files with 335 additions and 29 deletions

113
crypto/age/age.go Normal file
View File

@@ -0,0 +1,113 @@
package age
import (
"fmt"
"os"
"io"
"bytes"
"errors"
"filippo.io/age"
)
var (
ageKeyFileName = "age.key"
)
func GenerateAgeKey(filename string) (*age.X25519Identity, error) {
// Generate a new X25519 identity (private key)
identity, err := age.GenerateX25519Identity()
if err != nil {
return nil, fmt.Errorf("failed to generate identity: %w", err)
}
// Convert the identity to its string representation
privateKey := identity.String()
// Write the private key to a file
err = os.WriteFile(filename, []byte(privateKey), 0600)
if err != nil {
return nil, fmt.Errorf("failed to save private key to file: %w", err)
}
fmt.Printf("Private key saved to %s\n", filename)
return identity, nil
}
func LoadAgeKey(filename string) (*age.X25519Identity, error) {
// Read the private key from the file
privateKeyBytes, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read private key from file: %w", err)
}
// Parse the private key
identity, err := age.ParseX25519Identity(string(privateKeyBytes))
if err != nil {
return nil, fmt.Errorf("failed to parse private key: %w", err)
}
return identity, nil
}
func LoadOrGenerateKeys(filename string) (*age.X25519Identity, error) {
_, err := os.Open(filename)
if errors.Is(err, os.ErrNotExist) {
fmt.Println("Not Exists - Generate Keys")
return GenerateAgeKey(filename)
}
return LoadAgeKey(filename)
}
func Decrypt(encryptedData []byte, identity *age.X25519Identity) ([]byte, error) {
// Create a new decryptor using the recipient's identity
decryptor, err := age.Decrypt(bytes.NewReader(encryptedData), identity)
if err != nil {
return nil, fmt.Errorf("failed to create decryptor: %w", err)
}
// Read the decrypted data
decryptedData, err := io.ReadAll(decryptor)
if err != nil {
return nil, fmt.Errorf("failed to decrypt data: %w", err)
}
return decryptedData, nil
}
func Encrypt(data []byte, recipientKeys []string) ([]byte, error) {
var recipients []age.Recipient
// Parse all recipient keys
for _, key := range recipientKeys {
recipient, err := age.ParseX25519Recipient(key)
if err != nil {
return nil, fmt.Errorf("failed to parse recipient key: %w", err)
}
recipients = append(recipients, recipient)
}
// Create a new buffer to hold the encrypted data
var encryptedData bytes.Buffer
// Create a new age encryptor for the recipients
encryptor, err := age.Encrypt(&encryptedData, recipients...)
if err != nil {
return nil, fmt.Errorf("failed to create encryptor: %w", err)
}
// Write the data to the encryptor
_, err = encryptor.Write(data)
if err != nil {
return nil, fmt.Errorf("failed to encrypt data: %w", err)
}
// Close the encryptor to finalize the encryption process
if err := encryptor.Close(); err != nil {
return nil, fmt.Errorf("failed to finalize encryption: %w", err)
}
return encryptedData.Bytes(), nil
}

View File

@@ -1,12 +1,9 @@
package crypto
import (
"fmt"
"bytes"
"io"
"encoding/json"
"filippo.io/age"
"github.com/google/uuid"
)
type Password struct {
@@ -15,6 +12,7 @@ type Password struct {
Username string `json:"Username"`
Password string `json:"Password"`
Tags []string `json:"Tags"`
Id uuid.UUID `json:"Id"`
}
func (p *Password) ToJson() ([]byte, error) {
@@ -32,25 +30,9 @@ func GetPasswordFromJson(b []byte) (Password, error) {
return result, nil
}
func Encrypt() {
publicKey := "age1cy0su9fwf3gf9mw868g5yut09p6nytfmmnktexz2ya5uqg9vl9sss4euqm"
recipient, err := age.ParseX25519Recipient(publicKey)
if err != nil {
fmt.Printf("Failed to parse public key %q: %v", publicKey, err)
func NewPassword() *Password {
return &Password{
Id: uuid.New(),
}
out := &bytes.Buffer{}
w, err := age.Encrypt(out, recipient)
if err != nil {
fmt.Printf("Failed to create encrypted file: %v\n", err)
}
if _, err := io.WriteString(w, "Black lives matter."); err != nil {
fmt.Printf("Failed to write to encrypted file: %v\n", err)
}
if err := w.Close(); err != nil {
fmt.Printf("Failed to close encrypted file: %v\n", err)
}
fmt.Printf("Encrypted file size: %d\n", out.Len())
}

147
crypto/rsa/rsa.go Normal file
View File

@@ -0,0 +1,147 @@
package rsa
import (
"fmt"
"errors"
"os"
"log"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
)
var (
privateKeyName = "rsa_private_key.pem"
publicKeyName = "rsa_public_key.pem"
)
func GenerateKeys(path string) (*rsa.PrivateKey, *rsa.PublicKey, error) {
// Generate a new RSA key pair
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, err
}
// Save the private key to a file
privateKeyPath := path + privateKeyName
privateKeyFile, err := os.Create(privateKeyPath)
if err != nil {
return nil, nil, err
}
defer privateKeyFile.Close()
privateKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
})
_, err = privateKeyFile.Write(privateKeyPEM)
if err != nil {
return nil, nil, err
}
fmt.Printf("Private key saved to %s\n", privateKeyPath)
// Extract and save the public key
publicKeyPath := path + publicKeyName
publicKeyFile, err := os.Create(publicKeyPath)
if err != nil {
return nil, nil, err
}
defer publicKeyFile.Close()
publicKey := &privateKey.PublicKey
publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return nil, nil, err
}
publicKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PUBLIC KEY",
Bytes: publicKeyBytes,
})
_, err = publicKeyFile.Write(publicKeyPEM)
if err != nil {
return nil, nil, err
}
fmt.Printf("Public key saved to %s\n", publicKeyPath)
return privateKey, publicKey, nil
}
func LoadKeys(path string) (*rsa.PrivateKey, *rsa.PublicKey, error) {
// Load private key from file
privateKeyPath := path + privateKeyName
privateKeyData, err := os.ReadFile(privateKeyPath)
if err != nil {
log.Fatalf("Failed to read private key: %v", err)
return nil, nil, err
}
block, _ := pem.Decode(privateKeyData)
if block == nil || block.Type != "RSA PRIVATE KEY" {
log.Fatalf("Failed to decode PEM block containing private key")
return nil, nil, err
}
privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
log.Fatalf("Failed to parse private key: %v", err)
return nil, nil, err
}
// Load public key from file
publicKeyPath := path + publicKeyName
publicKeyData, err := os.ReadFile(publicKeyPath)
if err != nil {
log.Fatalf("Failed to read public key: %v", err)
return nil, nil, err
}
block, _ = pem.Decode(publicKeyData)
if block == nil || block.Type != "RSA PUBLIC KEY" {
log.Fatalf("Failed to decode PEM block containing public key")
return nil, nil, err
}
publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
log.Fatalf("Failed to parse public key: %v", err)
return nil, nil, err
}
publicKey := publicKeyInterface.(*rsa.PublicKey)
return privateKey, publicKey, nil
}
func LoadOrGenerateKeys(path string) (*rsa.PrivateKey, *rsa.PublicKey, error) {
_, err := os.Open(path + privateKeyName)
if errors.Is(err, os.ErrNotExist) {
fmt.Println("Not Exists - Generate Keys")
return GenerateKeys(path)
}
return LoadKeys(path)
}
func Encrypt(data []byte, key *rsa.PublicKey) ([]byte, error) {
ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, key, data)
if err != nil {
log.Fatalf("Failed to encrypt: %v", err)
return nil, err
}
return ciphertext, nil
}
func Decrypt(data []byte, key *rsa.PrivateKey) ([]byte, error) {
decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, key, data)
if err != nil {
log.Fatalf("Failed to decrypt: %v", err)
return nil, err
}
return decrypted, nil
}