pastebin - collaborative debugging tool
kpaste.net RSS


blow
Posted by Anonymous on Fri 1st May 2026 11:28
raw | new post

  1. package irc
  2.  
  3. import (
  4.         "crypto/cipher"
  5.         "crypto/rand"
  6.         "crypto/sha1"
  7.         "encoding/base64"
  8.         "fmt"
  9.         "strings"
  10.  
  11.         "golang.org/x/crypto/blowfish"
  12. )
  13.  
  14. // BlowfishEncryptor handles Blowfish encryption/decryption
  15. type BlowfishEncryptor struct {
  16.         cipher cipher.Block
  17.         mode   string // "ECB" or "CBC"
  18. }
  19.  
  20. // NewBlowfishEncryptor creates a new encryptor with a key
  21. // Key format: "cbc:keystring" or "ecb:keystring" or just "keystring" (defaults to ECB)
  22. func NewBlowfishEncryptor(keyStr string) (*BlowfishEncryptor, error) {
  23.         mode := "ECB"
  24.         key := keyStr
  25.        
  26.         // Parse mode prefix
  27.         if strings.HasPrefix(keyStr, "cbc:") {
  28.                 mode = "CBC"
  29.                 key = keyStr[4:]
  30.         } else if strings.HasPrefix(keyStr, "ecb:") {
  31.                 mode = "ECB"
  32.                 key = keyStr[4:]
  33.         }
  34.        
  35.         // Create cipher
  36.         c, err := blowfish.NewCipher([]byte(key))
  37.         if err != nil {
  38.                 return nil, err
  39.         }
  40.        
  41.         return &BlowfishEncryptor{
  42.                 cipher: c,
  43.                 mode:   mode,
  44.         }, nil
  45. }
  46.  
  47. // Encrypt encrypts plaintext and returns base64 encoded ciphertext
  48. func (b *BlowfishEncryptor) Encrypt(plaintext string) string {
  49.         data := []byte(plaintext)
  50.        
  51.         if b.mode == "CBC" {
  52.                 return b.encryptCBC(data)
  53.         }
  54.         return b.encryptECB(data)
  55. }
  56.  
  57. // Decrypt decrypts base64 encoded ciphertext
  58. func (b *BlowfishEncryptor) Decrypt(ciphertext string) (string, error) {
  59.         if b.mode == "CBC" {
  60.                 return b.decryptCBC(ciphertext)
  61.         }
  62.         return b.decryptECB(ciphertext)
  63. }
  64.  
  65. // encryptECB encrypts in ECB mode (simple block by block)
  66. func (b *BlowfishEncryptor) encryptECB(data []byte) string {
  67.         // Pad to block size
  68.         blockSize := b.cipher.BlockSize()
  69.         padLen := blockSize - (len(data) % blockSize)
  70.         for i := 0; i < padLen; i++ {
  71.                 data = append(data, byte(padLen))
  72.         }
  73.        
  74.         // Encrypt blocks
  75.         for i := 0; i < len(data); i += blockSize {
  76.                 b.cipher.Encrypt(data[i:i+blockSize], data[i:i+blockSize])
  77.         }
  78.        
  79.         // Base64 encode
  80.         return base64.StdEncoding.EncodeToString(data)
  81. }
  82.  
  83. // decryptECB decrypts in ECB mode
  84. func (b *BlowfishEncryptor) decryptECB(ciphertext string) (string, error) {
  85.         // Base64 decode
  86.         data, err := base64.StdEncoding.DecodeString(ciphertext)
  87.         if err != nil {
  88.                 return "", err
  89.         }
  90.        
  91.         // Decrypt blocks
  92.         blockSize := b.cipher.BlockSize()
  93.         for i := 0; i < len(data); i += blockSize {
  94.                 b.cipher.Decrypt(data[i:i+blockSize], data[i:i+blockSize])
  95.         }
  96.        
  97.         // Remove padding
  98.         if len(data) > 0 {
  99.                 padLen := int(data[len(data)-1])
  100.                 if padLen <= blockSize && padLen > 0 {
  101.                         data = data[:len(data)-padLen]
  102.                 }
  103.         }
  104.        
  105.         return string(data), nil
  106. }
  107.  
  108. // encryptCBC encrypts in CBC mode (FiSH-compatible: random IV prepended, zero-padded)
  109. func (b *BlowfishEncryptor) encryptCBC(data []byte) string {
  110.         blockSize := b.cipher.BlockSize()
  111.         // FiSH/Mircryption use zero-padding for CBC
  112.         if rem := len(data) % blockSize; rem != 0 {
  113.                 padLen := blockSize - rem
  114.                 for i := 0; i < padLen; i++ {
  115.                         data = append(data, 0)
  116.                 }
  117.         }
  118.  
  119.         // Generate a random IV and prepend it to the ciphertext
  120.         iv := make([]byte, blockSize)
  121.         if _, err := rand.Read(iv); err != nil {
  122.                 // Fallback to sha1 of plaintext if rand fails
  123.                 h := sha1.Sum(data)
  124.                 copy(iv, h[:blockSize])
  125.         }
  126.  
  127.         mode := cipher.NewCBCEncrypter(b.cipher, iv)
  128.         mode.CryptBlocks(data, data)
  129.  
  130.         out := make([]byte, 0, len(iv)+len(data))
  131.         out = append(out, iv...)
  132.         out = append(out, data...)
  133.         return base64.StdEncoding.EncodeToString(out)
  134. }
  135.  
  136. // decryptCBC decrypts in CBC mode
  137. func (b *BlowfishEncryptor) decryptCBC(ciphertext string) (string, error) {
  138.         // Base64 decode
  139.         data, err := base64.StdEncoding.DecodeString(ciphertext)
  140.         if err != nil {
  141.                 return "", err
  142.         }
  143.        
  144.         if len(data) < b.cipher.BlockSize() {
  145.                 return "", fmt.Errorf("ciphertext too short")
  146.         }
  147.        
  148.         // Use first block as IV
  149.         blockSize := b.cipher.BlockSize()
  150.         iv := data[:blockSize]
  151.        
  152.         // Decrypt
  153.         mode := cipher.NewCBCDecrypter(b.cipher, iv)
  154.         mode.CryptBlocks(data[blockSize:], data[blockSize:])
  155.        
  156.         plain := data[blockSize:]
  157.         for len(plain) > 0 && plain[len(plain)-1] == 0 {
  158.                 plain = plain[:len(plain)-1]
  159.         }
  160.  
  161.         return string(plain), nil
  162. }

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at