1
0
mirror of https://github.com/duke-git/lancet.git synced 2026-02-04 12:52:28 +08:00

fix: fix issue #159 and refact crypto function

This commit is contained in:
dudaodong
2025-04-22 14:22:01 +08:00
parent 27667f8b3a
commit 72a23d2cb9
7 changed files with 594 additions and 396 deletions

View File

@@ -2,7 +2,6 @@
// Use of this source code is governed by MIT license // Use of this source code is governed by MIT license
// Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel, locker. // Package concurrency contain some functions to support concurrent programming. eg, goroutine, channel, locker.
package concurrency package concurrency
import ( import (

View File

@@ -6,7 +6,6 @@
package cryptor package cryptor
import ( import (
"bufio"
"crypto/hmac" "crypto/hmac"
"crypto/md5" "crypto/md5"
"crypto/sha1" "crypto/sha1"
@@ -66,34 +65,37 @@ func Md5ByteWithBase64(data []byte) string {
// Md5File return the md5 value of file. // Md5File return the md5 value of file.
func Md5File(filename string) (string, error) { func Md5File(filename string) (string, error) {
if fileInfo, err := os.Stat(filename); err != nil {
return "", err
} else if fileInfo.IsDir() {
return "", nil
}
file, err := os.Open(filename) file, err := os.Open(filename)
if err != nil { if err != nil {
return "", err return "", err
} }
defer file.Close() defer file.Close()
hash := md5.New() stat, err := file.Stat()
if err != nil {
chunkSize := 65536 return "", err
for buf, reader := make([]byte, chunkSize), bufio.NewReader(file); ; { }
n, err := reader.Read(buf) if stat.IsDir() {
if err != nil { return "", nil
if err == io.EOF {
break
}
return "", err
}
hash.Write(buf[:n])
} }
checksum := fmt.Sprintf("%x", hash.Sum(nil)) hash := md5.New()
return checksum, nil buf := make([]byte, 65536) // 64KB
for {
n, err := file.Read(buf)
if err != nil && err != io.EOF {
return "", err
}
if n > 0 {
hash.Write(buf[:n])
}
if err == io.EOF {
break
}
}
return fmt.Sprintf("%x", hash.Sum(nil)), nil
} }
// HmacMd5 return the hmac hash of string use md5. // HmacMd5 return the hmac hash of string use md5.

View File

@@ -15,39 +15,40 @@ import (
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/sha256" "crypto/sha256"
"crypto/sha512"
"crypto/x509" "crypto/x509"
"encoding/pem" "encoding/pem"
"errors"
"io" "io"
"os" "os"
"strings"
) )
// AesEcbEncrypt encrypt data with key use AES ECB algorithm // AesEcbEncrypt encrypt data with key use AES ECB algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j // Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbEncrypt(data, key []byte) []byte { func AesEcbEncrypt(data, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
length := (len(data) + aes.BlockSize) / aes.BlockSize blockSize := aes.BlockSize
plain := make([]byte, length*aes.BlockSize) dataLen := len(data)
padding := blockSize - (dataLen % blockSize)
paddedLen := dataLen + padding
copy(plain, data) paddedData := make([]byte, paddedLen)
copy(paddedData, data)
pad := byte(len(plain) - len(data)) for i := dataLen; i < paddedLen; i++ {
for i := len(data); i < len(plain); i++ { paddedData[i] = byte(padding)
plain[i] = pad
} }
encrypted := make([]byte, len(plain)) cipher, err := aes.NewCipher(generateAesKey(key, len(key)))
cipher, _ := aes.NewCipher(generateAesKey(key, size)) if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { encrypted := make([]byte, paddedLen)
cipher.Encrypt(encrypted[bs:be], plain[bs:be]) for bs := 0; bs < paddedLen; bs += blockSize {
cipher.Encrypt(encrypted[bs:], paddedData[bs:])
} }
return encrypted return encrypted
@@ -57,77 +58,107 @@ func AesEcbEncrypt(data, key []byte) []byte {
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/jT5irszHx-j // Play: https://go.dev/play/p/jT5irszHx-j
func AesEcbDecrypt(encrypted, key []byte) []byte { func AesEcbDecrypt(encrypted, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
cipher, _ := aes.NewCipher(generateAesKey(key, size))
blockSize := aes.BlockSize
if len(encrypted)%blockSize != 0 {
panic("aes: encrypted data length is not a multiple of block size")
}
cipher, err := aes.NewCipher(generateAesKey(key, len(key)))
if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
decrypted := make([]byte, len(encrypted)) decrypted := make([]byte, len(encrypted))
for i := 0; i < len(encrypted); i += blockSize {
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { cipher.Decrypt(decrypted[i:], encrypted[i:])
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
} }
trim := 0 if len(decrypted) == 0 {
if len(decrypted) > 0 { return nil
trim = len(decrypted) - int(decrypted[len(decrypted)-1]) }
padding := int(decrypted[len(decrypted)-1])
if padding == 0 || padding > blockSize {
panic("aes: invalid PKCS#7 padding")
}
for i := len(decrypted) - padding; i < len(decrypted); i++ {
if decrypted[i] != byte(padding) {
panic("aes: invalid PKCS#7 padding content")
}
} }
return decrypted[:trim] return decrypted[:len(decrypted)-padding]
} }
// AesCbcEncrypt encrypt data with key use AES CBC algorithm // AesCbcEncrypt encrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD // Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcEncrypt(data, key []byte) []byte { func AesCbcEncrypt(data, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
block, _ := aes.NewCipher(key) block, err := aes.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize()) if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
encrypted := make([]byte, aes.BlockSize+len(data)) padding := aes.BlockSize - len(data)%aes.BlockSize
iv := encrypted[:aes.BlockSize] padded := append(data, bytes.Repeat([]byte{byte(padding)}, padding)...)
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil { if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err) panic("aes: failed to generate IV: " + err.Error())
} }
encrypted := make([]byte, len(padded))
mode := cipher.NewCBCEncrypter(block, iv) mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[aes.BlockSize:], data) mode.CryptBlocks(encrypted, padded)
return encrypted return append(iv, encrypted...)
} }
// AesCbcDecrypt decrypt data with key use AES CBC algorithm // AesCbcDecrypt decrypt data with key use AES CBC algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/IOq_g8_lKZD // Play: https://go.dev/play/p/IOq_g8_lKZD
func AesCbcDecrypt(encrypted, key []byte) []byte { func AesCbcDecrypt(encrypted, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
block, _ := aes.NewCipher(key) if len(encrypted) < aes.BlockSize {
panic("aes: ciphertext too short")
}
if len(encrypted)%aes.BlockSize != 0 {
panic("aes: ciphertext is not a multiple of the block size")
}
iv := encrypted[:aes.BlockSize] iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:] ciphertext := encrypted[aes.BlockSize:]
block, err := aes.NewCipher(key)
if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
decrypted := make([]byte, len(ciphertext))
mode := cipher.NewCBCDecrypter(block, iv) mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted) mode.CryptBlocks(decrypted, ciphertext)
decrypted := pkcs7UnPadding(encrypted) return pkcs7UnPadding(decrypted)
return decrypted
} }
// AesCtrCrypt encrypt data with key use AES CTR algorithm // AesCtrCrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/SpaZO0-5Nsp // Play: https://go.dev/play/p/SpaZO0-5Nsp
// deprecated: use AesCtrEncrypt and AesCtrDecrypt instead.
func AesCtrCrypt(data, key []byte) []byte { func AesCtrCrypt(data, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
block, _ := aes.NewCipher(key) block, _ := aes.NewCipher(key)
@@ -141,158 +172,214 @@ func AesCtrCrypt(data, key []byte) []byte {
return dst return dst
} }
// AesCfbEncrypt encrypt data with key use AES CFB algorithm // AesCtrEncrypt encrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH // Play: todo
func AesCfbEncrypt(data, key []byte) []byte { func AesCtrEncrypt(data, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("aes: failed to create cipher: " + err.Error())
} }
encrypted := make([]byte, aes.BlockSize+len(data)) iv := make([]byte, aes.BlockSize)
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil { if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err) panic("aes: failed to generate IV: " + err.Error())
} }
stream := cipher.NewCFBEncrypter(block, iv) stream := cipher.NewCTR(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data) ciphertext := make([]byte, len(data))
stream.XORKeyStream(ciphertext, data)
return encrypted return append(iv, ciphertext...)
}
// AesCtrDecrypt decrypt data with key use AES CTR algorithm
// len(key) should be 16, 24 or 32.
// Play: todo
func AesCtrDecrypt(encrypted, key []byte) []byte {
if !isAesKeyLengthValid(len(key)) {
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
}
if len(encrypted) < aes.BlockSize {
panic("aes: invalid ciphertext length")
}
iv := encrypted[:aes.BlockSize]
ciphertext := encrypted[aes.BlockSize:]
block, err := aes.NewCipher(key)
if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
stream := cipher.NewCTR(block, iv)
plaintext := make([]byte, len(ciphertext))
stream.XORKeyStream(plaintext, ciphertext)
return plaintext
}
// AesCfbEncrypt encrypt data with key use AES CFB algorithm
// len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbEncrypt(data, key []byte) []byte {
if !isAesKeyLengthValid(len(key)) {
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
}
block, err := aes.NewCipher(key)
if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic("aes: failed to generate IV: " + err.Error())
}
ciphertext := make([]byte, len(data))
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext, data)
return append(iv, ciphertext...)
} }
// AesCfbDecrypt decrypt data with key use AES CFB algorithm // AesCfbDecrypt decrypt data with key use AES CFB algorithm
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32. // len(encrypted) should be great than 16, len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/tfkF10B13kH // Play: https://go.dev/play/p/tfkF10B13kH
func AesCfbDecrypt(encrypted, key []byte) []byte { func AesCfbDecrypt(encrypted, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
if len(encrypted) < aes.BlockSize { if len(encrypted) < aes.BlockSize {
panic("encrypted data is too short") panic("aes: encrypted data too short")
} }
block, _ := aes.NewCipher(key)
iv := encrypted[:aes.BlockSize] iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:] ciphertext := encrypted[aes.BlockSize:]
block, err := aes.NewCipher(key)
if err != nil {
panic("aes: failed to create cipher: " + err.Error())
}
plaintext := make([]byte, len(ciphertext))
stream := cipher.NewCFBDecrypter(block, iv) stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(plaintext, ciphertext)
stream.XORKeyStream(encrypted, encrypted) return plaintext
return encrypted
} }
// AesOfbEncrypt encrypt data with key use AES OFB algorithm // AesOfbEncrypt encrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F // Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbEncrypt(data, key []byte) []byte { func AesOfbEncrypt(data, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("aes: failed to create cipher: " + err.Error())
} }
data = pkcs7Padding(data, aes.BlockSize) iv := make([]byte, aes.BlockSize)
encrypted := make([]byte, aes.BlockSize+len(data))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil { if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err) panic("aes: failed to generate IV: " + err.Error())
} }
ciphertext := make([]byte, len(data))
stream := cipher.NewOFB(block, iv) stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], data) stream.XORKeyStream(ciphertext, data)
return encrypted return append(iv, ciphertext...)
} }
// AesOfbDecrypt decrypt data with key use AES OFB algorithm // AesOfbDecrypt decrypt data with key use AES OFB algorithm
// len(key) should be 16, 24 or 32. // len(key) should be 16, 24 or 32.
// Play: https://go.dev/play/p/VtHxtkUj-3F // Play: https://go.dev/play/p/VtHxtkUj-3F
func AesOfbDecrypt(data, key []byte) []byte { func AesOfbDecrypt(data, key []byte) []byte {
size := len(key) if !isAesKeyLengthValid(len(key)) {
if size != 16 && size != 24 && size != 32 { panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
panic("key length shoud be 16 or 24 or 32")
} }
block, err := aes.NewCipher(key) if len(data) < aes.BlockSize {
if err != nil { panic("aes: encrypted data too short")
panic(err)
} }
iv := data[:aes.BlockSize] iv := data[:aes.BlockSize]
data = data[aes.BlockSize:] ciphertext := data[aes.BlockSize:]
if len(data)%aes.BlockSize != 0 {
return nil block, err := aes.NewCipher(key)
if err != nil {
panic("aes: failed to create cipher: " + err.Error())
} }
decrypted := make([]byte, len(data)) plaintext := make([]byte, len(ciphertext))
mode := cipher.NewOFB(block, iv) stream := cipher.NewOFB(block, iv)
mode.XORKeyStream(decrypted, data) stream.XORKeyStream(plaintext, ciphertext)
decrypted = pkcs7UnPadding(decrypted) return plaintext
return decrypted
} }
// AesGcmEncrypt encrypt data with key use AES GCM algorithm // AesGcmEncrypt encrypt data with key use AES GCM algorithm
// Play: https://go.dev/play/p/rUt0-DmsPCs // Play: https://go.dev/play/p/rUt0-DmsPCs
func AesGcmEncrypt(data, key []byte) []byte { func AesGcmEncrypt(data, key []byte) []byte {
if !isAesKeyLengthValid(len(key)) {
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
}
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("aes: failed to create cipher: " + err.Error())
} }
gcm, err := cipher.NewGCM(block) gcm, err := cipher.NewGCM(block)
if err != nil { if err != nil {
panic(err) panic("aes: failed to create GCM: " + err.Error())
} }
nonce := make([]byte, gcm.NonceSize()) nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil { if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
panic(err) panic("aes: failed to generate nonce: " + err.Error())
} }
ciphertext := gcm.Seal(nonce, nonce, data, nil) ciphertext := gcm.Seal(nil, nonce, data, nil)
return ciphertext return append(nonce, ciphertext...)
} }
// AesGcmDecrypt decrypt data with key use AES GCM algorithm // AesGcmDecrypt decrypt data with key use AES GCM algorithm
// Play: https://go.dev/play/p/rUt0-DmsPCs // Play: https://go.dev/play/p/rUt0-DmsPCs
func AesGcmDecrypt(data, key []byte) []byte { func AesGcmDecrypt(data, key []byte) []byte {
if !isAesKeyLengthValid(len(key)) {
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
}
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("aes: failed to create cipher: " + err.Error())
} }
gcm, err := cipher.NewGCM(block) gcm, err := cipher.NewGCM(block)
if err != nil { if err != nil {
panic(err) panic("aes: failed to create GCM: " + err.Error())
} }
nonceSize := gcm.NonceSize() nonceSize := gcm.NonceSize()
if len(data) < nonceSize { if len(data) < nonceSize {
panic("ciphertext too short") panic("aes: ciphertext too short")
} }
nonce, ciphertext := data[:nonceSize], data[nonceSize:] nonce, ciphertext := data[:nonceSize], data[nonceSize:]
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil) plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
if err != nil { if err != nil {
panic(err) panic("aes: decryption failed: " + err.Error())
} }
return plaintext return plaintext
@@ -302,20 +389,17 @@ func AesGcmDecrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/8qivmPeZy4P // Play: https://go.dev/play/p/8qivmPeZy4P
func DesEcbEncrypt(data, key []byte) []byte { func DesEcbEncrypt(data, key []byte) []byte {
length := (len(data) + des.BlockSize) / des.BlockSize cipher, err := des.NewCipher(generateDesKey(key))
plain := make([]byte, length*des.BlockSize) if err != nil {
copy(plain, data) panic("des: failed to create cipher: " + err.Error())
pad := byte(len(plain) - len(data))
for i := len(data); i < len(plain); i++ {
plain[i] = pad
} }
encrypted := make([]byte, len(plain)) blockSize := cipher.BlockSize()
cipher, _ := des.NewCipher(generateDesKey(key)) padded := pkcs5Padding(data, blockSize)
encrypted := make([]byte, len(padded))
for bs, be := 0, cipher.BlockSize(); bs <= len(data); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { for i := 0; i < len(padded); i += blockSize {
cipher.Encrypt(encrypted[bs:be], plain[bs:be]) cipher.Encrypt(encrypted[i:], padded[i:])
} }
return encrypted return encrypted
@@ -325,42 +409,50 @@ func DesEcbEncrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/8qivmPeZy4P // Play: https://go.dev/play/p/8qivmPeZy4P
func DesEcbDecrypt(encrypted, key []byte) []byte { func DesEcbDecrypt(encrypted, key []byte) []byte {
cipher, _ := des.NewCipher(generateDesKey(key)) cipher, err := des.NewCipher(generateDesKey(key))
if err != nil {
panic("des: failed to create cipher: " + err.Error())
}
blockSize := cipher.BlockSize()
if len(encrypted)%blockSize != 0 {
panic("des: invalid encrypted data length")
}
decrypted := make([]byte, len(encrypted)) decrypted := make([]byte, len(encrypted))
for i := 0; i < len(encrypted); i += blockSize {
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() { cipher.Decrypt(decrypted[i:], encrypted[i:])
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
} }
trim := 0 // Remove padding
if len(decrypted) > 0 { return pkcs5UnPadding(decrypted)
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
}
return decrypted[:trim]
} }
// DesCbcEncrypt encrypt data with key use DES CBC algorithm // DesCbcEncrypt encrypt data with key use DES CBC algorithm
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1 // Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcEncrypt(data, key []byte) []byte { func DesCbcEncrypt(data, key []byte) []byte {
size := len(key) if len(key) != 8 {
if size != 8 { panic("des: key length must be 8 bytes")
panic("key length shoud be 8")
} }
block, _ := des.NewCipher(key) block, err := des.NewCipher(key)
data = pkcs7Padding(data, block.BlockSize()) if err != nil {
panic("des: failed to create cipher: " + err.Error())
}
encrypted := make([]byte, des.BlockSize+len(data)) blockSize := block.BlockSize()
iv := encrypted[:des.BlockSize] data = pkcs7Padding(data, blockSize)
encrypted := make([]byte, blockSize+len(data))
iv := encrypted[:blockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil { if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err) panic("des: failed to generate IV: " + err.Error())
} }
mode := cipher.NewCBCEncrypter(block, iv) mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(encrypted[des.BlockSize:], data) mode.CryptBlocks(encrypted[blockSize:], data)
return encrypted return encrypted
} }
@@ -369,26 +461,33 @@ func DesCbcEncrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/4cC4QvWfe3_1 // Play: https://go.dev/play/p/4cC4QvWfe3_1
func DesCbcDecrypt(encrypted, key []byte) []byte { func DesCbcDecrypt(encrypted, key []byte) []byte {
size := len(key) if len(key) != 8 {
if size != 8 { panic("des: key length must be 8 bytes")
panic("key length shoud be 8")
} }
block, _ := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil {
panic("des: failed to create cipher: " + err.Error())
}
iv := encrypted[:des.BlockSize] blockSize := block.BlockSize()
encrypted = encrypted[des.BlockSize:] if len(encrypted) < blockSize || len(encrypted)%blockSize != 0 {
panic("des: invalid encrypted data length")
}
iv := encrypted[:blockSize]
ciphertext := encrypted[blockSize:]
mode := cipher.NewCBCDecrypter(block, iv) mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(encrypted, encrypted) mode.CryptBlocks(ciphertext, ciphertext)
decrypted := pkcs7UnPadding(encrypted) return pkcs7UnPadding(ciphertext)
return decrypted
} }
// DesCtrCrypt encrypt data with key use DES CTR algorithm // DesCtrCrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/9-T6OjKpcdw // Play: https://go.dev/play/p/9-T6OjKpcdw
// deprecated: use DesCtrEncrypt and DesCtrDecrypt instead.
func DesCtrCrypt(data, key []byte) []byte { func DesCtrCrypt(data, key []byte) []byte {
size := len(key) size := len(key)
if size != 8 { if size != 8 {
@@ -406,25 +505,83 @@ func DesCtrCrypt(data, key []byte) []byte {
return dst return dst
} }
// DesCfbEncrypt encrypt data with key use DES CFB algorithm // DesCtrEncrypt encrypt data with key use DES CTR algorithm
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL // Play: todo
func DesCfbEncrypt(data, key []byte) []byte { func DesCtrEncrypt(data, key []byte) []byte {
size := len(key) if len(key) != 8 {
if size != 8 { panic("des: key length must be 8 bytes")
panic("key length shoud be 8")
} }
block, err := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("des: failed to create cipher: " + err.Error())
}
iv := make([]byte, block.BlockSize())
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic("des: failed to generate IV: " + err.Error())
}
stream := cipher.NewCTR(block, iv)
encrypted := make([]byte, len(data))
stream.XORKeyStream(encrypted, data)
// 返回前缀包含 IV便于解密
return append(iv, encrypted...)
}
// DesCtrDecrypt decrypt data with key use DES CTR algorithm
// len(key) should be 8.
// Play: todo
func DesCtrDecrypt(encrypted, key []byte) []byte {
if len(key) != 8 {
panic("des: key length must be 8 bytes")
}
block, err := des.NewCipher(key)
if err != nil {
panic("des: failed to create cipher: " + err.Error())
}
blockSize := block.BlockSize()
if len(encrypted) < blockSize {
panic("des: ciphertext too short")
}
iv := encrypted[:blockSize]
ciphertext := encrypted[blockSize:]
stream := cipher.NewCTR(block, iv)
decrypted := make([]byte, len(ciphertext))
stream.XORKeyStream(decrypted, ciphertext)
return decrypted
}
// DesCfbEncrypt encrypt data with key use DES CFB algorithm
// len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbEncrypt(data, key []byte) []byte {
if len(key) != 8 {
panic("des: key length must be 8 bytes")
}
block, err := des.NewCipher(key)
if err != nil {
panic("des: failed to create cipher: " + err.Error())
}
iv := make([]byte, des.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic("des: failed to generate IV: " + err.Error())
} }
encrypted := make([]byte, des.BlockSize+len(data)) encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil { copy(encrypted[:des.BlockSize], iv)
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv) stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data) stream.XORKeyStream(encrypted[des.BlockSize:], data)
@@ -436,44 +593,51 @@ func DesCfbEncrypt(data, key []byte) []byte {
// len(encrypted) should be great than 16, len(key) should be 8. // len(encrypted) should be great than 16, len(key) should be 8.
// Play: https://go.dev/play/p/y-eNxcFBlxL // Play: https://go.dev/play/p/y-eNxcFBlxL
func DesCfbDecrypt(encrypted, key []byte) []byte { func DesCfbDecrypt(encrypted, key []byte) []byte {
size := len(key) if len(key) != 8 {
if size != 8 { panic("des: key length must be 8 bytes")
panic("key length shoud be 8")
} }
block, _ := des.NewCipher(key) block, err := des.NewCipher(key)
if len(encrypted) < des.BlockSize { if err != nil {
panic("encrypted data is too short") panic("des: failed to create cipher: " + err.Error())
} }
if len(encrypted) < des.BlockSize {
panic("des: encrypted data too short")
}
iv := encrypted[:des.BlockSize] iv := encrypted[:des.BlockSize]
encrypted = encrypted[des.BlockSize:] ciphertext := encrypted[des.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv) stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted) stream.XORKeyStream(ciphertext, ciphertext)
return encrypted return ciphertext
} }
// DesOfbEncrypt encrypt data with key use DES OFB algorithm // DesOfbEncrypt encrypt data with key use DES OFB algorithm
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/74KmNadjN1J // Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbEncrypt(data, key []byte) []byte { func DesOfbEncrypt(data, key []byte) []byte {
size := len(key) if len(key) != 8 {
if size != 8 { panic("des: key length must be 8 bytes")
panic("key length shoud be 8")
} }
block, err := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("des: failed to create cipher: " + err.Error())
} }
data = pkcs7Padding(data, des.BlockSize) data = pkcs7Padding(data, des.BlockSize)
encrypted := make([]byte, des.BlockSize+len(data))
iv := encrypted[:des.BlockSize] iv := make([]byte, des.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil { if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err) panic("des: failed to generate IV: " + err.Error())
} }
encrypted := make([]byte, des.BlockSize+len(data))
copy(encrypted[:des.BlockSize], iv)
stream := cipher.NewOFB(block, iv) stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(encrypted[des.BlockSize:], data) stream.XORKeyStream(encrypted[des.BlockSize:], data)
@@ -484,25 +648,25 @@ func DesOfbEncrypt(data, key []byte) []byte {
// len(key) should be 8. // len(key) should be 8.
// Play: https://go.dev/play/p/74KmNadjN1J // Play: https://go.dev/play/p/74KmNadjN1J
func DesOfbDecrypt(data, key []byte) []byte { func DesOfbDecrypt(data, key []byte) []byte {
size := len(key) if len(key) != 8 {
if size != 8 { panic("des: key length must be 8 bytes")
panic("key length shoud be 8")
} }
block, err := des.NewCipher(key) block, err := des.NewCipher(key)
if err != nil { if err != nil {
panic(err) panic("des: failed to create cipher: " + err.Error())
}
if len(data) < des.BlockSize {
panic("des: encrypted data too short")
} }
iv := data[:des.BlockSize] iv := data[:des.BlockSize]
data = data[des.BlockSize:] ciphertext := data[des.BlockSize:]
if len(data)%des.BlockSize != 0 {
return nil
}
decrypted := make([]byte, len(data)) stream := cipher.NewOFB(block, iv)
mode := cipher.NewOFB(block, iv) decrypted := make([]byte, len(ciphertext))
mode.XORKeyStream(decrypted, data) stream.XORKeyStream(decrypted, ciphertext)
decrypted = pkcs7UnPadding(decrypted) decrypted = pkcs7UnPadding(decrypted)
@@ -693,117 +857,3 @@ func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName stri
return rsa.VerifyPKCS1v15(publicKey, hash, hashed, signature) return rsa.VerifyPKCS1v15(publicKey, hash, hashed, signature)
} }
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
func loadRsaPublicKey(filename string) (*rsa.PublicKey, error) {
pubKeyData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(pubKeyData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing the public key")
}
var pubKey *rsa.PublicKey
blockType := strings.ToUpper(block.Type)
if blockType == "RSA PUBLIC KEY" {
pubKey, err = x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil {
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
pubKey, ok = key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
}
} else if blockType == "PUBLIC KEY" {
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
pubKey, ok = key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
} else {
return nil, errors.New("unsupported key type")
}
return pubKey, nil
}
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
func loadRasPrivateKey(filename string) (*rsa.PrivateKey, error) {
priKeyData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(priKeyData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing the private key")
}
var privateKey *rsa.PrivateKey
blockType := strings.ToUpper(block.Type)
// PKCS#1 format
if blockType == "RSA PRIVATE KEY" {
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
} else if blockType == "PRIVATE KEY" { // PKCS#8 format
priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
privateKey, ok = priKey.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
} else {
return nil, errors.New("unsupported key type")
}
return privateKey, nil
}
// hashData returns the hash value of the data, using the specified hash function
func hashData(hash crypto.Hash, data []byte) ([]byte, error) {
if !hash.Available() {
return nil, errors.New("unsupported hash algorithm")
}
var hashed []byte
switch hash {
case crypto.SHA224:
h := sha256.Sum224(data)
hashed = h[:]
case crypto.SHA256:
h := sha256.Sum256(data)
hashed = h[:]
case crypto.SHA384:
h := sha512.Sum384(data)
hashed = h[:]
case crypto.SHA512:
h := sha512.Sum512(data)
hashed = h[:]
default:
return nil, errors.New("unsupported hash algorithm")
}
return hashed, nil
}

View File

@@ -1,6 +1,17 @@
package cryptor package cryptor
import "bytes" import (
"bytes"
"crypto"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/pem"
"errors"
"os"
"strings"
)
func generateAesKey(key []byte, size int) []byte { func generateAesKey(key []byte, size int) []byte {
genKey := make([]byte, size) genKey := make([]byte, size)
@@ -35,3 +46,139 @@ func pkcs7UnPadding(src []byte) []byte {
unPadding := int(src[length-1]) unPadding := int(src[length-1])
return src[:(length - unPadding)] return src[:(length - unPadding)]
} }
func pkcs5Padding(data []byte, blockSize int) []byte {
padding := blockSize - len(data)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(data, padText...)
}
func pkcs5UnPadding(data []byte) []byte {
length := len(data)
if length == 0 {
return nil
}
padLen := int(data[length-1])
if padLen == 0 || padLen > length {
return nil
}
return data[:length-padLen]
}
func isAesKeyLengthValid(n int) bool {
return n == 16 || n == 24 || n == 32
}
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
func loadRsaPublicKey(filename string) (*rsa.PublicKey, error) {
pubKeyData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(pubKeyData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing the public key")
}
var pubKey *rsa.PublicKey
blockType := strings.ToUpper(block.Type)
if blockType == "RSA PUBLIC KEY" {
pubKey, err = x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil {
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
pubKey, ok = key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
}
} else if blockType == "PUBLIC KEY" {
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
pubKey, ok = key.(*rsa.PublicKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
} else {
return nil, errors.New("unsupported key type")
}
return pubKey, nil
}
// loadRsaPrivateKey loads and parses a PEM encoded private key file.
func loadRasPrivateKey(filename string) (*rsa.PrivateKey, error) {
priKeyData, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
block, _ := pem.Decode(priKeyData)
if block == nil {
return nil, errors.New("failed to decode PEM block containing the private key")
}
var privateKey *rsa.PrivateKey
blockType := strings.ToUpper(block.Type)
// PKCS#1 format
if blockType == "RSA PRIVATE KEY" {
privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
} else if blockType == "PRIVATE KEY" { // PKCS#8 format
priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
var ok bool
privateKey, ok = priKey.(*rsa.PrivateKey)
if !ok {
return nil, errors.New("failed to parse RSA private key")
}
} else {
return nil, errors.New("unsupported key type")
}
return privateKey, nil
}
// hashData returns the hash value of the data, using the specified hash function
func hashData(hash crypto.Hash, data []byte) ([]byte, error) {
if !hash.Available() {
return nil, errors.New("unsupported hash algorithm")
}
var hashed []byte
switch hash {
case crypto.SHA224:
h := sha256.Sum224(data)
hashed = h[:]
case crypto.SHA256:
h := sha256.Sum256(data)
hashed = h[:]
case crypto.SHA384:
h := sha512.Sum384(data)
hashed = h[:]
case crypto.SHA512:
h := sha512.Sum512(data)
hashed = h[:]
default:
return nil, errors.New("unsupported hash algorithm")
}
return hashed, nil
}

View File

@@ -7,7 +7,7 @@ import (
"github.com/duke-git/lancet/v2/internal" "github.com/duke-git/lancet/v2/internal"
) )
func TestAesEcbEncrypt(t *testing.T) { func TestAesEcbCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -16,11 +16,11 @@ func TestAesEcbEncrypt(t *testing.T) {
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key)) aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key)) aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesEcbEncrypt") assert := internal.NewAssert(t, "TestAesEcbCrypt")
assert.Equal(data, string(aesEcbDecrypt)) assert.Equal(data, string(aesEcbDecrypt))
} }
func TestAesCbcEncrypt(t *testing.T) { func TestAesCbcCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -29,7 +29,7 @@ func TestAesCbcEncrypt(t *testing.T) {
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key)) aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key)) aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCbcEncrypt") assert := internal.NewAssert(t, "TestAesCbcCrypt")
assert.Equal(data, string(aesCbcDecrypt)) assert.Equal(data, string(aesCbcDecrypt))
} }
@@ -39,14 +39,14 @@ func TestAesCtrCrypt(t *testing.T) {
data := "hello world" data := "hello world"
key := "abcdefghijklmnop" key := "abcdefghijklmnop"
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key)) aesCtrCrypt := AesCtrEncrypt([]byte(data), []byte(key))
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key)) aesCtrDeCrypt := AesCtrDecrypt(aesCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCtrCrypt") assert := internal.NewAssert(t, "TestAesCtrCrypt")
assert.Equal(data, string(aesCtrDeCrypt)) assert.Equal(data, string(aesCtrDeCrypt))
} }
func TestAesCfbEncrypt(t *testing.T) { func TestAesCfbCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -55,11 +55,11 @@ func TestAesCfbEncrypt(t *testing.T) {
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key)) aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key)) aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
assert := internal.NewAssert(t, "TestAesCfbEncrypt") assert := internal.NewAssert(t, "TestAesCfbCrypt")
assert.Equal(data, string(aesCfbDecrypt)) assert.Equal(data, string(aesCfbDecrypt))
} }
func TestAesOfbEncrypt(t *testing.T) { func TestAesOfbCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -72,7 +72,7 @@ func TestAesOfbEncrypt(t *testing.T) {
assert.Equal(data, string(aesOfbDecrypt)) assert.Equal(data, string(aesOfbDecrypt))
} }
func TestDesEcbEncrypt(t *testing.T) { func TestDesEcbCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -85,7 +85,7 @@ func TestDesEcbEncrypt(t *testing.T) {
assert.Equal(data, string(desEcbDecrypt)) assert.Equal(data, string(desEcbDecrypt))
} }
func TestDesCbcEncrypt(t *testing.T) { func TestDesCbcCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -104,14 +104,14 @@ func TestDesCtrCrypt(t *testing.T) {
data := "hello world" data := "hello world"
key := "abcdefgh" key := "abcdefgh"
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key)) desCtrCrypt := DesCtrEncrypt([]byte(data), []byte(key))
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key)) desCtrDeCrypt := DesCtrDecrypt(desCtrCrypt, []byte(key))
assert := internal.NewAssert(t, "TestDesCtrCrypt") assert := internal.NewAssert(t, "TestDesCtrCrypt")
assert.Equal(data, string(desCtrDeCrypt)) assert.Equal(data, string(desCtrDeCrypt))
} }
func TestDesCfbEncrypt(t *testing.T) { func TestDesCfbCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"
@@ -124,7 +124,7 @@ func TestDesCfbEncrypt(t *testing.T) {
assert.Equal(data, string(desCfbDecrypt)) assert.Equal(data, string(desCfbDecrypt))
} }
func TestDesOfbEncrypt(t *testing.T) { func TestDesOfbCrypt(t *testing.T) {
t.Parallel() t.Parallel()
data := "hello world" data := "hello world"

View File

@@ -1,51 +1,51 @@
-----BEGIN rsa private key----- -----BEGIN rsa private key-----
MIIJKQIBAAKCAgEAtXr+2FbR6Prdf9U0gfq2OJbTD82m84bbdeyfsakabYp8Haw6 MIIJKAIBAAKCAgEAvEyrhW9xP2vi2ONaQqILGOpqk3UJZRnT9ItEpefUvsjYeL3Q
mZW6ebRNPJvQ87H6DbA55hK1E7y6m+wjvbUopnkGh75Cp04CoQvaU8Rs7MrQcJ2Z dR9VMngVV8MtmhwqAut7h+aDGL4ZWIj4vh9ezIHNPkIUZwm3qA/Q0IZ1+/8tZN3U
z1VRRgugmqwJMWE/FC5eGXvvpDjF2h2lqThKZTKcvhqfZ3dNX+6v4EQ4BbjSGKdz 7pBfIYvM0kW6Ko9U9LRMha/2WhG0NWHeZKYnt2dPg/FhoRSvh2fswW+TXK4KbEK0
pyexzR1WSV9IzZYRHMk8jCoEHOx9ItEzoToBf9yAq0DhufylqSRbjKLhR7A3IiRS FcBC9hjAlQsz/CHqeZSF+EEZdvFwenvvr8vvQRNGaTAgqkqQKcek5CaJAKw0N926
LVNfu0Sz5cfNlS7eUA060QS8AV9BgGNTkl75aj8BCOmoHIW85SsSZvdQWYwmlM76 mwb9k3aHXN0XuK94vkmS1RKrsQSiSOpkioLI2DUPryayddokjmszkdHggv2uVR6s
Jn+tfNNnY7Uuqtz2gI1odcy1nXembXWJryxuYCkSAwpU8UNIQpZeKwBnBxaf0pj3 a/RTwtU0nZjD02+F+3vYYoo+dx4hpCV8Ln8IthtABCohEGW+M3IU+0vMRFgtRtLS
W1m3UzEqhGkkCrKq8LkNSGZSkhT+bI65fNx2LZ7lS165szkeyqS8aikxcBpdx7Z/ GqGZ3vYGCt12tUsPNHFrPE1i8YPJDF4e8V7AqdKrPgoKHyn8mb7Ho0uZ0GItzrPU
bqbFFuI42KX+IpXAJCAtvsQ0XXinr83MLcY/I2Ic/5Sgz7txfZsKKwKt48ETS9Bj uPROBmoAcwwYR9AOTLDR+ZFmZ+bfUXO03nLWXF+MbnLDvKLE5bNdyjgEf4hzuHCw
xGPWo1Dd5YjM8ZJWJv2Rf0mwVjUMClFSNBm8x+aWGVIKjpocN/plpEZmFrWdPcWM X5UfQgpHt3c+nbm54ds82bWHrWFwW3/x8FGQZtlPYYMYYX/js+g/frYHGmjhYbby
4ZH3qGCEnVVkqPvqClahNSQXsM4W7msYts1IUq31tjBSV5bL6l2K8jFJa4PRYdzh vfoK15GKDM+YwzBkZqA2yU50ytjfkFjcRp/Pp8v2AolbnjVqYS2oUgNJUG80wunU
1vHhDOAYTpgDkQbNaoDlDS2o/0TkAGUfXWJtR3D35wRJzoa7bCMt5BuFE3sCAwEA QjO1FaJNAk239Y3cZ71A698eKWMDkdkiMnv2CXyMfSc/bBL/dtP2/nMzmhcCAwEA
AQKCAgEAm/OsGEDTdcBOo9GVo7TM7mg9y7DQLSnQYdALk2JcAZImAmHEocLXUkqs AQKCAgAw3HxNncN3P5mXyjcrvzy99GY/aUlM0MztUg44NtY/w4JYonirS7wh4oM3
rM7BiwmAdk7gEmQ1E1b1jZQpSpbo7dXG1NOc96TEAZzr61w6tmm7IWtth4wroWPQ SNBWgyRrqYteknRGQV32WWSigSVqT+xgUWlV63GazK/UzG9lOqwe1mlglln5LHuz
idoYtER7Ll6CIqgsURUwgLVFbNugosIRjBPYs9MDvNKidLhq5A/lC6aqbhRgaIEz vKA4VwUmknqg3i5A5QMsLv80guEfeFFr3YEF+YYqzs7iyv8kN41A1nZAhqlZjsa6
ay3kpDa3UeNkkpZwnmJjTo40LfJo43WbZI8G6wq/WVCTE5HMwgwd9Mr9i1HATG9H ZjPRI0Pi1KWG6+2drb0QK4TgyzyEWGoW9YQkbEDIdqPVCCLY59aNAJ5hiAjY8RLj
oMhIVFDIXkZgKspEvXEcGrZAVOIktzaZLw2Ll6cdolmXIMCaXblgVjRfJsJFVaVd CAQVyoK8bf8KB1RCFP+/iAMa5iET6YDuZE4+wqJlym+RUTK/CvDn6ZO4V6g8kHKc
jYNfLRlhAyuBfumBkGYHsLx2qwAlgC1gCY/72RAtpQWTsefNp9Athztj7iAbwW67 yn1WKkRMI7DcsR7QbiMwowF8Vz58/+b3QND/fRIy2f2oedijKpZuZgJH7URISDsj
AgWlz44TOxtp2JTZOQZs9Douunp+DNFzA30bJasyWD+EZcUdyxMWhW27b2EQFfjP oj4HydQicQoFTagHWMzlRnU+RcG7cj3FD0jcXETetlia5fGSRNrilUPnSlb6ulXQ
XefmjJKkfTuG4f/Oti+Qqy6qnd/L22iph6WuAzSBCUAdkyHwvFwK32H971aNLqlA eir0iB3SZC+PLVhSO4A2ny9VqwavE9IBh6JVJfGvThtuGNLs122b9VlALx8jLdz2
nBUn9/CYZ9m4oiR2bqide4B2P3/3wzFyLTHZqwaJDBnHV4nVUy+CxGsbhIyXLyCq sNGli3kvwMvJ94NGalnUIGOds1ogWALR21WXn2uL8LGkm7O2lsCl4NO9TDPzhmfg
csmWaP9VUKCgIlI1B7MY5puHaYULKWnVye8+ges363ndvGEtdvke/9qkyNgc2Kxi IRl03bFwrvtJ834uCuF0Q7iS4+wuVWWv6vztKB+cL5Lpd9+328OxMsqnpAMbNFx9
ZNKIzZWihoBa1pPqqsSEm99L70TpXfdca6M3+2teLm63dk0cPpECggEBAOm52TD2 kFrdyLKuSdgoXDeqKy1b3MyZRdyksBysxbFhCASgfYOOSJ3Y8QKCAQEAwSDfBkhR
l3waYVyh85IJZo9fgtemlOJ7vSzEWivscYzqwzY+xfQuvj4lFOxHno/wu0lORD3a k4KZ9Z00Hy1dCQFbywTGxHAEhaXE8iFyszlotTDYgxddtoLuc35a75dJ4TXVoFmG
1xzC9v+OBvIKpX5PQ9bbS+Oe94kZMZmtF4oyPpvmPbSIhZvASWq/oaMSpq9RIINW tjmJp2Pso7txjRd9EzNxsDbZhWuDc3U5N8EMYYSeiGGyvvhCCJS6XN6u+HrffkeJ
13o91q37leXCj3XhEmqWbStbMwJ7aRU45K7qKbMMM9EmsageBykoyy3PfHFZvsAh Pb5ZDZJNhjpZy6l9x59lEANYAOEa3SVh1GxV20DNvMzOm35xXwtwNh3kXmF9B1RS
joQWRCFSmso94YBrpT0rZj9t57y3j9zrCTc+5T0OXkA69yhKrkwL6JQowMHbisx9 x6HdYsDYlRaW3REhXfxH/r2p3AZrji5Ffz1IXkhnEYlBoOtYi3mhXxiqz/du2pU+
p+c4467vdwAaDx14/EYERkqiNjxWS1zCfenTvBs7Gu+/C+/4gZnt2I8vbsTf9wyP IsIdoKmvDFVRB+ZM1pnqlXpIwYpaEypaP6HqOKZjxuFCnmUjKIy3L699rvHTFkzv
g2Hg/V/txAGreF8CggEBAMbGhtowf7TgFvn3T9fmFEBaCIe+m888hkTamiGLUrDh P8S6S0+cZq7cmwKCAQEA+ZlcuIqc8yT9h2tOg0g1z1fcB9JqqWgH8/uJfR3Fvc0e
HCTO34vHMo/5Tds3Fy1c/BPvECV3wv/Nln046MuMuLIkIbk3uhVmVEFKGKMlqq6H 9qiqqsDMioXh5JFnF0d2tFppkjcPDo3CN1+Zp4fHicWrrOBQajOzZCrL47t+TlLQ
KRd+PErAf59FQ3Yfkqm7/JnBPgdvgzPmc09SAafHgiogMuu4FFDob+LSENuZl0zA OKHgJ6UQYgCehrRI5rlqGxeepW0a+UKQYlBgXCZeyPJH3OwqLHvzearyQntoURrr
U6Xr9nQphB4IxG15dVSEDKQhlhcTGQy0VBx6sskg6897MuJduDJiNPjQpWmGDuji I21rFxbZJhpmvPqkAqRH+u1DIzq5l4sZFZ+RAN7lmQMIS8/NM9qQsg+W4lBrOBZ+
9xuNURVy4FuHYr9yUEDBwWkL8VjKwzASDgK0b38knUpThP33W/TZgQWewFfSD6Nq UpxjZn7ybTiLLljxHXF/UvF15Y6VtTGMF0J7bBydtsu42F7yJbrq32FKyz2zVmkc
fBBmct7JYfLNEwItlr/NOF9Q+KIeB9E3Ok+xO99BKmUCggEAbBWg5e6zQRXl/nN6 eaNR3cUKIZD9LxYwJNYtrV5/R1F233z22VcHyROqNQKCAQBaRi052JAZLZEd2A/H
cwdb4WOW22lSoqX8Zs5qsLNIE5WhLt26p2BSY+S8F0RLhF8cDRtfnYctQUS7+pRQ CwNT9EieC2uF4v6aIjR/Iddlo04oc96g2Ek7yNQBNGz5VXR5SxrCS1bG0vpfPjwd
i+/2dkHrqlmBb8Lc0A7RjDKqlyMDJw9Da9BSkSNMEEyMUCBY6uxGb9ZiEUq1k4Gr BL89Pl9+nCtmPR1MWkclrwPB5gENjFo2UcSls5HaRPsf8g9DotvZQUMLk3A5Acwv
4TOnKikqXhYwaANlxHkTsFe+EVGCdSVodQlC0O8J+rO9ufKgpr6M4sbh5B1z5kEQ FBNpOZ7Lstwgsg9uycou2QxzqPgw9oe02t8wm9gOn2AiS7K100gIJwhSvHypbo9O
CgSx2rRtFquSPjTyHKh6o/whJ+YzFpglZ+ic0YovrkU3igSKl1uShVx6oAgD6qsc kTKPvzQjpItarfk6Gd4opcRih5jOSXW0Ir6Eo73N5FrkArnFYFl23xAeWzJSKT7j
yfRDFysS5sIlS3BWSnLRqRTcK5zZ+XHM1B/yQkgWjvuZ0SVrQSodUjav2Dy2j30h uvWXhbUhEu0uVeywWyVjlAZ/fAXp2Q0Gp8DmHUxj5fKy3YsYPX14DRpAaorSLTJk
zm/gWwKCAQBXUun1Oq8vz+5oG/zIlTw6VRNARz192lIGN57Us7c9G3fYt8U/S+Br ZRRFAoIBAQC5fX+qpVh+Wb8QJG70oXVb4a9jILyjqOxAJW7HzJhntUiNhktPGnjn
nZNVhas584qOW0zVmPpilHfTRUgH/Cc7o2HpU5D9S7oiAKI4Mhj8mUY1GvDzygOG eRenBWfXpQRSg95xCvnllvP+ss0982oWuRAcKZeZVVK73hIn6+6xxll3vNUYoVLL
/c+4OgCdbod3KIzOiW+zQj9QDm/JvHzzcrfMFE9gh+x3Ud+0CZKNVkSpNLNNrttq gipNcS28SY7RE3yS88JX+1/RsGnsEZffPi6pv9iXtoX6pU/kmFGt9JNKgMZVImW+
smFQ0rX3zhcbl+Gu+2XazfHRnRmkAEF4IeBlz9RW1gv9bvPsGse8CdGTGg8QBCqK K2CukJXSYMQddrWuOLY0KOs7ZpocS4nVbKt9q7CUGJnvuiYnihwkUpMOUaqNQUpo
Kzz3bAnTmQsV0fhSEKmVGalsCMaerYAoIe7f/2Y3d8IVrPtE2XSjTul37vnx47iT YN0OVIrblr1Ipqk3L/+R6IBzyLRwY9PRRRTZt7W81Gw4FdW/tNrSHMtMmlL8vLIK
CQKbx1ldo5NrVFAWMGkwwTltvyfVWXR9AoIBAQC6lS+ptioI/jUX7L+OQQJvrspW v/VoSNT+iyzm6pMsLR5qeDP60PK4PCUBAoIBAG2XBjQuRR0tMmUT1l5y02s1KZhc
jjxzW+JsCVdm6FvVGgWHMkcdUg5JIUvBj+ifBkIgqReiHr9AtNX5NooxR449B7zK jAt89aeqEj1olOZCfUiBprnfgYn9kb5+IpgIKtn0MTF10YudCeV/AI151MffBvfd
HNsaNqCs2V0gT9vgGaPvakC4ThKQf8vSUF04ECMdFmxJTvlCM3mGbxn/M4bE4OPc xdKk2xBwBZSFkZHVqka3bxbPKOcW76FyO4gneCBAAkKvM9UpTZHQcK0pK+v7GI8S
ypMb1qh4AhJyt4PMP1Ds8TAjmNRQ9LhoITXcuzlgZIbvOyA6Nz7dz5w3iUoOMyTl Hxu9OvvYnAlipEFOTZAXoezP5GTyAZevRJB12HoeuvLa1HNSMr8Aa+7dIlq9Ac4u
SvZ1jMvHGiKHJJD0oYsf1q2YcNvBGT7lvOxJF1LR0AKgfTuqckJOVX4SdiWjgnEI MSmaUOdenzzOb+d84rhbT1YS+skZcddQoO2j/clG0jHE9dq64pUsZpbyZ+EulOs2
oEPbjc5sl4Vq+DDNstIQC4/vGbAkeFDozaU+rySXTS2QESyNj9EtbW/uOkLr ML1uuGFkNFF+/sEcabHR1wHyNsdeQIebxFX6q5HWh0P3D/IqoPvQ7X3ODCs=
-----END rsa private key----- -----END rsa private key-----

View File

@@ -1,14 +1,14 @@
-----BEGIN rsa public key----- -----BEGIN rsa public key-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtXr+2FbR6Prdf9U0gfq2 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEyrhW9xP2vi2ONaQqIL
OJbTD82m84bbdeyfsakabYp8Haw6mZW6ebRNPJvQ87H6DbA55hK1E7y6m+wjvbUo GOpqk3UJZRnT9ItEpefUvsjYeL3QdR9VMngVV8MtmhwqAut7h+aDGL4ZWIj4vh9e
pnkGh75Cp04CoQvaU8Rs7MrQcJ2Zz1VRRgugmqwJMWE/FC5eGXvvpDjF2h2lqThK zIHNPkIUZwm3qA/Q0IZ1+/8tZN3U7pBfIYvM0kW6Ko9U9LRMha/2WhG0NWHeZKYn
ZTKcvhqfZ3dNX+6v4EQ4BbjSGKdzpyexzR1WSV9IzZYRHMk8jCoEHOx9ItEzoToB t2dPg/FhoRSvh2fswW+TXK4KbEK0FcBC9hjAlQsz/CHqeZSF+EEZdvFwenvvr8vv
f9yAq0DhufylqSRbjKLhR7A3IiRSLVNfu0Sz5cfNlS7eUA060QS8AV9BgGNTkl75 QRNGaTAgqkqQKcek5CaJAKw0N926mwb9k3aHXN0XuK94vkmS1RKrsQSiSOpkioLI
aj8BCOmoHIW85SsSZvdQWYwmlM76Jn+tfNNnY7Uuqtz2gI1odcy1nXembXWJryxu 2DUPryayddokjmszkdHggv2uVR6sa/RTwtU0nZjD02+F+3vYYoo+dx4hpCV8Ln8I
YCkSAwpU8UNIQpZeKwBnBxaf0pj3W1m3UzEqhGkkCrKq8LkNSGZSkhT+bI65fNx2 thtABCohEGW+M3IU+0vMRFgtRtLSGqGZ3vYGCt12tUsPNHFrPE1i8YPJDF4e8V7A
LZ7lS165szkeyqS8aikxcBpdx7Z/bqbFFuI42KX+IpXAJCAtvsQ0XXinr83MLcY/ qdKrPgoKHyn8mb7Ho0uZ0GItzrPUuPROBmoAcwwYR9AOTLDR+ZFmZ+bfUXO03nLW
I2Ic/5Sgz7txfZsKKwKt48ETS9BjxGPWo1Dd5YjM8ZJWJv2Rf0mwVjUMClFSNBm8 XF+MbnLDvKLE5bNdyjgEf4hzuHCwX5UfQgpHt3c+nbm54ds82bWHrWFwW3/x8FGQ
x+aWGVIKjpocN/plpEZmFrWdPcWM4ZH3qGCEnVVkqPvqClahNSQXsM4W7msYts1I ZtlPYYMYYX/js+g/frYHGmjhYbbyvfoK15GKDM+YwzBkZqA2yU50ytjfkFjcRp/P
Uq31tjBSV5bL6l2K8jFJa4PRYdzh1vHhDOAYTpgDkQbNaoDlDS2o/0TkAGUfXWJt p8v2AolbnjVqYS2oUgNJUG80wunUQjO1FaJNAk239Y3cZ71A698eKWMDkdkiMnv2
R3D35wRJzoa7bCMt5BuFE3sCAwEAAQ== CXyMfSc/bBL/dtP2/nMzmhcCAwEAAQ==
-----END rsa public key----- -----END rsa public key-----