Files
rootandClaude Opus 4.7 79ac89b458 Initial commit
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-11-07 10:47:18 +08:00

75 lines
1.7 KiB
Go

package imgutil
import "bytes"
// 与管理后台 ShowImg / imgCode.js 保持一致。
var (
encryptMagicNumber = []byte{0x88, 0xA8, 0x30, 0xCB, 0x10, 0x76}
decryptKey = []byte{50, 48, 49, 57, 121, 115, 97, 112, 112, 55, 53, 50, 55} // 2019ysapp7527
plainImageHeaders = [][]byte{
{0xFF, 0xD8, 0xFF}, // jpeg
{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}, // png
{0x47, 0x49, 0x46}, // gif
}
)
const (
encryptedPrefixLen = 100
encryptXORAllKey = 0xA3
)
// DecryptImage 按后台 handleVerAutoImg 的规则解密图床图片。
// 已是 jpg/png/gif 则原样返回。
func DecryptImage(data []byte) []byte {
if len(data) == 0 {
return data
}
out := append([]byte(nil), data...)
if hasEncryptMagic(out) {
return xorAllLength(out)
}
if !isPlainImage(out) {
xorPrefix(out, decryptKey, encryptedPrefixLen)
}
return out
}
func hasEncryptMagic(data []byte) bool {
return len(data) >= len(encryptMagicNumber) && bytes.Equal(data[:len(encryptMagicNumber)], encryptMagicNumber)
}
func isPlainImage(data []byte) bool {
for _, header := range plainImageHeaders {
if len(data) >= len(header) && bytes.Equal(data[:len(header)], header) {
return true
}
}
return false
}
func xorPrefix(src, key []byte, length int) {
if len(key) == 0 || len(src) == 0 {
return
}
if length <= 0 || length > len(src) {
length = len(src)
}
for i := 0; i < length; {
for j := 0; j < len(key) && i < length; j++ {
src[i] ^= key[j]
i++
}
}
}
func xorAllLength(src []byte) []byte {
out := make([]byte, 0, len(src))
for i, b := range src {
if i < len(encryptMagicNumber) && b == encryptMagicNumber[i] {
continue
}
out = append(out, b^encryptXORAllKey)
}
return out
}