75 lines
1.7 KiB
Go
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
|
|
}
|