Thanks to visit codestin.com
Credit goes to github.com

Skip to content

IzyPro/otp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

One-Time Pad (OTP) Encryption

A simple, secure implementation of One-Time Pad encryption in Go.

What is a One-Time Pad?

A One-Time Pad (OTP) is a theoretically unbreakable encryption technique when used correctly. It works by combining a message with a random secret (the "pad") that is:

  • As long as the message - The key must be exactly the same length as the plaintext
  • Truly random - Generated using cryptographically secure random number generation
  • Used only once - Each key must never be reused (hence "one-time")
  • Kept secret - Both sender and receiver must have the key, but no one else

When these conditions are met, OTP provides perfect secrecy - the encrypted message reveals absolutely nothing about the original message to an attacker.

How It Works

  1. Encryption: Each byte of the message is added to the corresponding byte of the key (modulo 256)
  2. Decryption: Each byte of the encrypted message has the corresponding key byte subtracted (modulo 256)
Plaintext:  "HELLO"
Key:        [Random bytes]
Encrypted:  [XOR result]
Decrypted:  "HELLO" (using same key)

Installation

go get github.com/IzyPro/otp

Usage

Basic Example

package main

import (
    "fmt"
    "log"
    
    "github.com/IzyPro/otp"
)

func main() {
    // Your secret message
    message := []byte("Hello, this is a secret message!")
    
    // Step 1: Generate a one-time pad (same length as message)
    secret, err := otp.GenerateOTP(len(message))
    if err != nil {
        log.Fatal("Failed to generate OTP:", err)
    }
    
    fmt.Printf("Generated OTP (%d bytes)\n", len(secret))
    
    // Step 2: Encrypt the message
    encrypted, err := otp.Encrypt(message, secret)
    if err != nil {
        log.Fatal("Encryption failed:", err)
    }
    
    fmt.Printf("Original:  %s\n", message)
    fmt.Printf("Encrypted: %x\n", encrypted)
    
    // Step 3: Decrypt the message
    decrypted, err := otp.Decrypt(encrypted, secret)
    if err != nil {
        log.Fatal("Decryption failed:", err)
    }
    
    fmt.Printf("Decrypted: %s\n", decrypted)
    
    // Output:
    // Generated OTP (33 bytes)
    // Original:  Hello, this is a secret message!
    // Encrypted: 7a3f2e1b... (hex representation)
    // Decrypted: Hello, this is a secret message!
}

Secure Message Exchange

package main

import (
    "encoding/base64"
    "fmt"
    "log"
    
    "github.com/yourusername/otp"
)

func main() {
    message := []byte("Transfer $1000 to account 12345")
    
    // Sender: Generate OTP and encrypt
    secret, _ := otp.GenerateOTP(len(message))
    encrypted, _ := otp.Encrypt(message, secret)
    
    // Convert to base64 for transmission
    encryptedB64 := base64.StdEncoding.EncodeToString(encrypted)
    secretB64 := base64.StdEncoding.EncodeToString(secret)
    
    fmt.Println("Send this encrypted message:", encryptedB64)
    fmt.Println("Share this secret key (securely!):", secretB64)
    
    // Receiver: Decrypt the message
    // (In practice, decode from base64 first)
    decrypted, _ := otp.Decrypt(encrypted, secret)
    fmt.Printf("Decrypted message: %s\n", decrypted)
}

Working with Files

package main

import (
    "io/ioutil"
    "log"
    
    "github.com/yourusername/otp"
)

func encryptFile(inputPath, outputPath, keyPath string) error {
    // Read the file
    plaintext, err := ioutil.ReadFile(inputPath)
    if err != nil {
        return err
    }
    
    // Generate OTP
    secret, err := otp.GenerateOTP(len(plaintext))
    if err != nil {
        return err
    }
    
    // Encrypt
    encrypted, err := otp.Encrypt(plaintext, secret)
    if err != nil {
        return err
    }
    
    // Save encrypted file
    if err := ioutil.WriteFile(outputPath, encrypted, 0644); err != nil {
        return err
    }
    
    // Save key file (keep this secure!)
    if err := ioutil.WriteFile(keyPath, secret, 0600); err != nil {
        return err
    }
    
    return nil
}

func decryptFile(inputPath, keyPath, outputPath string) error {
    // Read encrypted file
    encrypted, err := ioutil.ReadFile(inputPath)
    if err != nil {
        return err
    }
    
    // Read key
    secret, err := ioutil.ReadFile(keyPath)
    if err != nil {
        return err
    }
    
    // Decrypt
    decrypted, err := otp.Decrypt(encrypted, secret)
    if err != nil {
        return err
    }
    
    // Save decrypted file
    return ioutil.WriteFile(outputPath, decrypted, 0644)
}

func main() {
    // Encrypt a file
    if err := encryptFile("secret.txt", "secret.enc", "secret.key"); err != nil {
        log.Fatal(err)
    }
    
    // Decrypt a file
    if err := decryptFile("secret.enc", "secret.key", "decrypted.txt"); err != nil {
        log.Fatal(err)
    }
}

API Reference

GenerateOTP(length int) ([]byte, error)

Generates a cryptographically secure random one-time pad of the specified length.

Parameters:

  • length - The number of random bytes to generate

Returns:

  • []byte - The generated one-time pad
  • error - Error if random generation fails

Example:

secret, err := otp.GenerateOTP(32)
if err != nil {
    log.Fatal(err)
}

Encrypt(message, secret []byte) ([]byte, error)

Encrypts a message using a one-time pad.

Parameters:

  • message - The plaintext message to encrypt
  • secret - The one-time pad (must be same length as message)

Returns:

  • []byte - The encrypted ciphertext
  • error - Error if message and secret lengths don't match

Example:

message := []byte("Secret message")
secret, _ := otp.GenerateOTP(len(message))
encrypted, err := otp.Encrypt(message, secret)

Decrypt(message, secret []byte) ([]byte, error)

Decrypts a message using a one-time pad.

Parameters:

  • message - The encrypted ciphertext
  • secret - The one-time pad used for encryption

Returns:

  • []byte - The decrypted plaintext
  • error - Error if message and secret lengths don't match

Example:

decrypted, err := otp.Decrypt(encrypted, secret)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Decrypted: %s\n", decrypted)

Security Considerations

⚠️ IMPORTANT: To maintain security, you MUST follow these rules:

  1. Never reuse a key - Each OTP must be used exactly once. Reusing a key completely breaks the security.

  2. Keep keys secure - The secret key must be transmitted through a secure channel separate from the encrypted message.

  3. Key length equals message length - The key must be exactly as long as the message you're encrypting.

  4. Use truly random keys - This implementation uses crypto/rand which is cryptographically secure. Don't use weaker random sources.

  5. Destroy keys after use - Once a key is used, it should be securely deleted from both sender and receiver.

Example of What NOT to Do

// ❌ WRONG: Reusing the same key
secret, _ := otp.GenerateOTP(100)
encrypted1, _ := otp.Encrypt(message1, secret)
encrypted2, _ := otp.Encrypt(message2, secret) // INSECURE!

// ❌ WRONG: Key shorter than message
secret, _ := otp.GenerateOTP(10)
message := []byte("This message is much longer than 10 bytes")
encrypted, err := otp.Encrypt(message, secret) // Returns error

// ❌ WRONG: Using predictable "random" data
secret := []byte{1, 2, 3, 4, 5} // NOT random!

Best Practices

// ✅ CORRECT: Generate new key for each message
message := []byte("Secret message")
secret, _ := otp.GenerateOTP(len(message))
encrypted, _ := otp.Encrypt(message, secret)

// Use the encrypted message and key once, then discard the key

// ✅ CORRECT: Check for errors
encrypted, err := otp.Encrypt(message, secret)
if err != nil {
    log.Fatal("Encryption failed:", err)
}

Limitations

  • Key Distribution Problem: Both parties need to securely share the one-time pad before communication. This is the main practical limitation of OTP.
  • Key Size: You need as much key material as you have data to encrypt, which can be impractical for large amounts of data.
  • One-Time Use Only: Keys cannot be reused, requiring constant generation and secure distribution of new keys.

When to Use OTP

OTP is ideal when:

  • Maximum security is required
  • Message size is relatively small
  • You have a secure channel for key distribution
  • You can ensure keys are never reused

For most applications, modern algorithms like AES-GCM are more practical while still being very secure.

Testing

Run the tests:

go test -v

Run benchmarks:

go test -bench=.

License

MIT License - See LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

References

About

Cryptographic Library for OTP (One-time Pad)

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages