Golang 中的 XOR 密码,带有自定义 base64 编码/解码,关于填充的小问题

XOR Cipher in Golang with custom base64encoding/decoding, small question regarding padding

提问人:Crimson 提问时间:11/17/2023 最后编辑:egleaseCrimson 更新时间:11/17/2023 访问量:64

问:

然而,我的代码的预期输出是"IA0aB1QMAFQVRQARFxcWAFQIFgcHBBQRWg=="<<<<<<<<<<<<<<<<<<<<<<<<<<"IA0aB1QMAFQVRQARFxcWAFQIFgcHBBQRWgAA"

问题很可能发生在 func 中,但我无法理解它,填充不正确吗?customBase64Encode

欣赏任何想法

package main

import (
    "fmt"
)

const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

func customBase64Encode(input []byte) string {
    var result string

    for i := 0; i < len(input); i += 3 {
        // Create a 24-bit value from three 8-bit values
        var bits uint32
        for j := 0; j < 3 && i+j < len(input); j++ {
            bits |= uint32(input[i+j]) << (8 * (2 - j))
        }

        // Break it into four 6-bit values
        for j := 0; j < 4; j++ {
            index := (bits >> ((3 - j) * 6)) & 0x3F
            result += string(base64Chars[index])
        }
    }

    // Add padding if necessary
    padding := (4 - len(result)%4) % 4
    for i := 0; i < padding; i++ {
        result += "="
    }

    return result
}

func customBase64Decode(input string) []byte {
    var result []byte

    for i := 0; i < len(input); i += 4 {
        var val uint32

        // Create a 24-bit value from four 6-bit values
        for j := 0; j < 4; j++ {
            char := input[i+j]
            index := byteIndex(char, base64Chars)
            val = val<<6 | uint32(index)
        }

        // Break it into three 8-bit values
        for j := 0; j < 3; j++ {
            result = append(result, byte((val>>(8*(2-j)))&0xFF))
        }
    }

    return result
}

func byteIndex(char byte, chars string) int {
    for i := 0; i < len(chars); i++ {
        if chars[i] == char {
            return i
        }
    }
    return -1
}

func XOR(text string, encrypt bool, key string) string {
    // Convert the key to a byte array
    keyBytes := []byte(key)

    // If decrypting, decode the input text using custom Base64 decoding
    if !encrypt {
        decodedText := customBase64Decode(text)
        text = string(decodedText)
    }

    // Convert the text to a byte array
    textBytes := []byte(text)

    // Initialize result array
    resultBytes := make([]byte, len(textBytes))

    // Perform XOR operation
    for i := 0; i < len(textBytes); i++ {
        // Get the corresponding byte from the key, using modulo to repeat the key if necessary
        keyByte := keyBytes[i%len(keyBytes)]

        // Perform XOR
        if encrypt {
            resultBytes[i] = textBytes[i] ^ keyByte
        } else {
            // For decryption, XOR operation is the same as encryption
            resultBytes[i] = textBytes[i] ^ keyByte
        }
    }

    // If encrypting, encode the result using custom Base64 encoding
    if encrypt {
        resultText := customBase64Encode(resultBytes)
        return resultText
    }

    // If decrypting, return the result as a string
    return string(resultBytes)
}

func main() {
    // Example usage
    encryptedText := XOR("This is a secret message.", true, "test")
    fmt.Println(encryptedText) // should be "IA0aB1QMAFQVRQARFxcWAFQIFgcHBBQRWg==" but is "IA0aB1QMAFQVRQARFxcWAFQIFgcHBBQRWgAA" 

    decryptedText := XOR(encryptedText, false, "test")
    fmt.Println(decryptedText) // should be "This is a secret message." but is "This is a secret message.es"
}
GO 加密 Base64 XOR

评论

2赞 icza 11/17/2023
在内部,第一个内部循环正确地进行到 ,但第二个内部循环总是添加(附加)4 个字符,即使他之前的循环没有 3 次迭代。这就是为什么你在末尾添加 s(alpabet 中的第一个字母)的原因,这就是为什么在那之后不会添加填充的原因。customBase64Encode()j < 3 && i+j < len(input)A
1赞 Maarten Bodewes 11/17/2023
发生的情况是,您对整个最后 32 位整数进行编码,然后将填充添加到 4 个字符的分隔符。您应该记住最终的 32 位整数中使用了多少位,并及时停止添加字符。然后,您应该执行填充。目前,“AA”仅表示不在原始字节数组中的位。它们尚未设置,并且在整数中保留为零。
1赞 Maarten Bodewes 11/17/2023
提示:您还可以在整数中添加字符。使编码更简单、更便宜。我肯定会使用流式处理或预先调整大小的缓冲区而不是字符串连接。=

答:

1赞 Crimson 11/17/2023 #1

如果不导入“encode/base64”,就无法使代码正常工作

package main

import (
    "encoding/base64"
    "fmt"
)

func XOR(text string, encrypt bool, key string) string {
    // Convert the key to a byte array
    keyBytes := []byte(key)

    // If decrypting, decode the input text from base64
    if !encrypt {
        decodedText, err := base64.StdEncoding.DecodeString(text)
        if err != nil {
            fmt.Println("Error decoding base64:", err)
            return ""
        }
        text = string(decodedText)
    }

    // Convert the text to a byte array
    textBytes := []byte(text)

    // Initialize result array
    resultBytes := make([]byte, len(textBytes))

    // Perform XOR operation
    for i := 0; i < len(textBytes); i++ {
        // Get the corresponding byte from the key, using modulo to repeat the key if necessary
        keyByte := keyBytes[i%len(keyBytes)]

        // Perform XOR
        if encrypt {
            resultBytes[i] = textBytes[i] ^ keyByte
        } else {
            // For decryption, XOR operation is the same as encryption
            resultBytes[i] = textBytes[i] ^ keyByte
        }
    }

    // If encrypting, encode the result as base64
    if encrypt {
        resultText := base64.StdEncoding.EncodeToString(resultBytes)
        return resultText
    }

    // If decrypting, return the result as a string
    return string(resultBytes)
}