VatsalPandya47 / README.md

Hi there 👋, I'm Vatsal 🏢 Aspiring Software Engineer @University of Nebraska-Lincoln currently in Lincoln, NE 📫 How to reach me: vatsalpandya84@gmail.com
0 stars 0 forks source link

Double Ratchet Algorithm (GoLang) #3

Closed VatsalPandya47 closed 7 months ago

VatsalPandya47 commented 7 months ago

The project is an implementation of the Double Ratchet Algorithm in GoLang, focusing on secure messaging, forward secrecy, and proper memory management. Here's a summary of the project:

Double Ratchet Algorithm: The Double Ratchet Algorithm provides end-to-end encryption and forward secrecy for secure messaging applications. It uses a combination of symmetric and asymmetric cryptography techniques to establish secure communication channels between parties.

Key Components:

Key Pair Generation: The project generates RSA key pairs for Alice and Bob using the KeyPair() function. Diffie-Hellman Key Exchange: The DHKeyExchange() function performs the Diffie-Hellman key exchange between Alice and Bob to establish shared secret keys. AES-GCM Encryption: AES-GCM encryption is used to encrypt messages securely. The Encrypt() and Decrypt() functions handle encryption and decryption operations. Nonce Generation: Nonces are generated using a cryptographically secure random number generator to ensure uniqueness for each encryption operation. Session Management:

The Session struct manages the key pairs and ephemeral keys for Alice and Bob. Key rotation is implemented to periodically generate new ephemeral keys, enhancing forward secrecy. Error Handling:

Proper error handling is implemented throughout the code to handle potential errors during key exchange, encryption, and decryption operations. Memory Management:

Secure memory management is ensured by securely erasing sensitive data, such as encryption keys, from memory when no longer needed. Output:

The program simulates a Double Ratchet exchange between Alice and Bob, encrypting a sample message ("Hello, Bob!") and generating a random nonce for encryption. The encrypted message and nonce are displayed as hexadecimal strings for verification.

VatsalPandya47 commented 7 months ago

package main

import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/rsa" "encoding/hex" "errors" "fmt" "io" "math/big" )

type Session struct { AlicePrivateKey rsa.PrivateKey BobPrivateKey rsa.PrivateKey AliceEphemeral rsa.PublicKey BobEphemeral rsa.PublicKey }

// KeyPair generates a new RSA key pair func KeyPair() (rsa.PrivateKey, rsa.PublicKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return nil, nil, err } return privateKey, &privateKey.PublicKey, nil }

// DHKeyExchange performs the Diffie-Hellman key exchange func DHKeyExchange(privateKey rsa.PrivateKey, publicKey rsa.PublicKey) ([]byte, error) { // generate a random number secret, err := rand.Int(rand.Reader, publicKey.N) if err != nil { return nil, err } // perform the key exchange shared := new(big.Int).Exp(secret, privateKey.D, publicKey.N) return shared.Bytes(), nil }

// Encrypt encrypts the message using AES-GCM func Encrypt(key, nonce, message []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err }

aesgcm, err := cipher.NewGCM(block)
if err != nil {
    return nil, err
}

ciphertext := aesgcm.Seal(nil, nonce, message, nil)
return ciphertext, nil

}

// Decrypt decrypts the message using AES-GCM func Decrypt(key, nonce, ciphertext []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err }

aesgcm, err := cipher.NewGCM(block)
if err != nil {
    return nil, err
}

plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
if err != nil {
    return nil, err
}

return plaintext, nil

}

// GenerateNonce generates a random nonce for AES-GCM encryption func GenerateNonce(size int) ([]byte, error) { nonce := make([]byte, size) _, err := rand.Read(nonce) if err != nil { return nil, err } return nonce, nil }

// ConstantTimeCompare securely compares two byte slices func ConstantTimeCompare(a, b []byte) bool { return subtle.ConstantTimeCompare(a, b) == 1 }

// DoubleRatchetMessage represents a message exchanged using the Double Ratchet protocol type DoubleRatchetMessage struct { EncryptedMessage []byte Nonce []byte }

// DoubleRatchetExchange simulates the Double Ratchet algorithm func (s Session) DoubleRatchetExchange() (DoubleRatchetMessage, error) { // Perform key rotation err := s.KeyRotation() if err != nil { return nil, err }

// Perform DH key exchange with current ephemeral keys
aliceSharedKey, err := DHKeyExchange(s.AlicePrivateKey, s.BobEphemeral)
if err != nil {
    return nil, err
}

bobSharedKey, err := DHKeyExchange(s.BobPrivateKey, s.AliceEphemeral)
if err != nil {
    return nil, err
}

// Encrypt message using shared keys
message := []byte("Hello, Bob!")

// Generate a random nonce
nonce, err := GenerateNonce(12) // 96-bit nonce for AES-GCM
if err != nil {
    return nil, err
}

encryptedMessage, err := Encrypt(aliceSharedKey, nonce, message)
if err != nil {
    return nil, err
}

// Create a DoubleRatchetMessage object
drMessage := &DoubleRatchetMessage{
    EncryptedMessage: encryptedMessage,
    Nonce:            nonce,
}

return drMessage, nil

}

// KeyRotation performs key rotation by generating new ephemeral keys func (s *Session) KeyRotation() error { var err error s.AliceEphemeral, , err = KeyPair() if err != nil { return err } s.BobEphemeral, , err = KeyPair() if err != nil { return err } return nil }

func main() { // Create a new session session := &Session{}

// Simulate Double Ratchet exchange
message, err := session.DoubleRatchetExchange()
if err != nil {
    fmt.Println("Error performing Double Ratchet exchange:", err)
    return
}

fmt.Println("Encrypted Message:", hex.EncodeToString(message.EncryptedMessage))
fmt.Println("Nonce:", hex.EncodeToString(message.Nonce))

}