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 }