mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-23 13:52:26 +08:00
Compare commits
2 Commits
27667f8b3a
...
9e813d236b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e813d236b | ||
|
|
72a23d2cb9 |
@@ -2,7 +2,6 @@
|
||||
// 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
|
||||
|
||||
import (
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package cryptor
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
@@ -66,34 +65,37 @@ func Md5ByteWithBase64(data []byte) string {
|
||||
|
||||
// Md5File return the md5 value of file.
|
||||
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)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
hash := md5.New()
|
||||
|
||||
chunkSize := 65536
|
||||
for buf, reader := make([]byte, chunkSize), bufio.NewReader(file); ; {
|
||||
n, err := reader.Read(buf)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
hash.Write(buf[:n])
|
||||
stat, err := file.Stat()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if stat.IsDir() {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
checksum := fmt.Sprintf("%x", hash.Sum(nil))
|
||||
return checksum, nil
|
||||
hash := md5.New()
|
||||
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.
|
||||
|
||||
@@ -15,39 +15,40 @@ import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AesEcbEncrypt encrypt data with key use AES ECB algorithm
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/jT5irszHx-j
|
||||
func AesEcbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
if !isAesKeyLengthValid(len(key)) {
|
||||
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
|
||||
}
|
||||
|
||||
length := (len(data) + aes.BlockSize) / aes.BlockSize
|
||||
plain := make([]byte, length*aes.BlockSize)
|
||||
blockSize := 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 := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
for i := dataLen; i < paddedLen; i++ {
|
||||
paddedData[i] = byte(padding)
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
cipher, _ := aes.NewCipher(generateAesKey(key, size))
|
||||
cipher, err := aes.NewCipher(generateAesKey(key, len(key)))
|
||||
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() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
encrypted := make([]byte, paddedLen)
|
||||
for bs := 0; bs < paddedLen; bs += blockSize {
|
||||
cipher.Encrypt(encrypted[bs:], paddedData[bs:])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
@@ -57,77 +58,107 @@ func AesEcbEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/jT5irszHx-j
|
||||
func AesEcbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
if !isAesKeyLengthValid(len(key)) {
|
||||
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
|
||||
}
|
||||
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))
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
for i := 0; i < len(encrypted); i += blockSize {
|
||||
cipher.Decrypt(decrypted[i:], encrypted[i:])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
if len(decrypted) == 0 {
|
||||
return nil
|
||||
}
|
||||
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
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/IOq_g8_lKZD
|
||||
func AesCbcEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
if !isAesKeyLengthValid(len(key)) {
|
||||
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
|
||||
}
|
||||
|
||||
block, _ := aes.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic("aes: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
padding := aes.BlockSize - len(data)%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 {
|
||||
panic(err)
|
||||
panic("aes: failed to generate IV: " + err.Error())
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(padded))
|
||||
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
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/IOq_g8_lKZD
|
||||
func AesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
if !isAesKeyLengthValid(len(key)) {
|
||||
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
|
||||
}
|
||||
|
||||
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]
|
||||
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.CryptBlocks(encrypted, encrypted)
|
||||
mode.CryptBlocks(decrypted, ciphertext)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
return pkcs7UnPadding(decrypted)
|
||||
}
|
||||
|
||||
// AesCtrCrypt encrypt data with key use AES CTR algorithm
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/SpaZO0-5Nsp
|
||||
// deprecated: use AesCtrEncrypt and AesCtrDecrypt instead.
|
||||
func AesCtrCrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
if !isAesKeyLengthValid(len(key)) {
|
||||
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
|
||||
}
|
||||
|
||||
block, _ := aes.NewCipher(key)
|
||||
@@ -141,158 +172,214 @@ func AesCtrCrypt(data, key []byte) []byte {
|
||||
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.
|
||||
// Play: https://go.dev/play/p/tfkF10B13kH
|
||||
func AesCfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
// Play: todo
|
||||
func AesCtrEncrypt(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(err)
|
||||
panic("aes: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
|
||||
iv := make([]byte, aes.BlockSize)
|
||||
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.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||
stream := cipher.NewCTR(block, iv)
|
||||
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
|
||||
// len(encrypted) should be great than 16, len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/tfkF10B13kH
|
||||
func AesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
if !isAesKeyLengthValid(len(key)) {
|
||||
panic("aes: invalid key length (must be 16, 24, or 32 bytes)")
|
||||
}
|
||||
|
||||
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]
|
||||
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.XORKeyStream(plaintext, ciphertext)
|
||||
|
||||
stream.XORKeyStream(encrypted, encrypted)
|
||||
|
||||
return encrypted
|
||||
return plaintext
|
||||
}
|
||||
|
||||
// AesOfbEncrypt encrypt data with key use AES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/VtHxtkUj-3F
|
||||
func AesOfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
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(err)
|
||||
panic("aes: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
data = pkcs7Padding(data, aes.BlockSize)
|
||||
encrypted := make([]byte, aes.BlockSize+len(data))
|
||||
iv := encrypted[:aes.BlockSize]
|
||||
iv := make([]byte, aes.BlockSize)
|
||||
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.XORKeyStream(encrypted[aes.BlockSize:], data)
|
||||
stream.XORKeyStream(ciphertext, data)
|
||||
|
||||
return encrypted
|
||||
return append(iv, ciphertext...)
|
||||
}
|
||||
|
||||
// AesOfbDecrypt decrypt data with key use AES OFB algorithm
|
||||
// len(key) should be 16, 24 or 32.
|
||||
// Play: https://go.dev/play/p/VtHxtkUj-3F
|
||||
func AesOfbDecrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 16 && size != 24 && size != 32 {
|
||||
panic("key length shoud be 16 or 24 or 32")
|
||||
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(err)
|
||||
if len(data) < aes.BlockSize {
|
||||
panic("aes: encrypted data too short")
|
||||
}
|
||||
|
||||
iv := data[:aes.BlockSize]
|
||||
data = data[aes.BlockSize:]
|
||||
if len(data)%aes.BlockSize != 0 {
|
||||
return nil
|
||||
ciphertext := data[aes.BlockSize:]
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
panic("aes: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
decrypted := make([]byte, len(data))
|
||||
mode := cipher.NewOFB(block, iv)
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
stream.XORKeyStream(plaintext, ciphertext)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
|
||||
return decrypted
|
||||
return plaintext
|
||||
}
|
||||
|
||||
// AesGcmEncrypt encrypt data with key use AES GCM algorithm
|
||||
// Play: https://go.dev/play/p/rUt0-DmsPCs
|
||||
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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
panic("aes: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
panic("aes: failed to create GCM: " + err.Error())
|
||||
}
|
||||
|
||||
nonce := make([]byte, gcm.NonceSize())
|
||||
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
panic(err)
|
||||
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||
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
|
||||
// Play: https://go.dev/play/p/rUt0-DmsPCs
|
||||
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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
panic("aes: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
panic("aes: failed to create GCM: " + err.Error())
|
||||
}
|
||||
|
||||
nonceSize := gcm.NonceSize()
|
||||
if len(data) < nonceSize {
|
||||
panic("ciphertext too short")
|
||||
panic("aes: ciphertext too short")
|
||||
}
|
||||
|
||||
nonce, ciphertext := data[:nonceSize], data[nonceSize:]
|
||||
plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
panic("aes: decryption failed: " + err.Error())
|
||||
}
|
||||
|
||||
return plaintext
|
||||
@@ -302,20 +389,17 @@ func AesGcmDecrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/8qivmPeZy4P
|
||||
func DesEcbEncrypt(data, key []byte) []byte {
|
||||
length := (len(data) + des.BlockSize) / des.BlockSize
|
||||
plain := make([]byte, length*des.BlockSize)
|
||||
copy(plain, data)
|
||||
|
||||
pad := byte(len(plain) - len(data))
|
||||
for i := len(data); i < len(plain); i++ {
|
||||
plain[i] = pad
|
||||
cipher, err := des.NewCipher(generateDesKey(key))
|
||||
if err != nil {
|
||||
panic("des: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
encrypted := make([]byte, len(plain))
|
||||
cipher, _ := des.NewCipher(generateDesKey(key))
|
||||
blockSize := cipher.BlockSize()
|
||||
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() {
|
||||
cipher.Encrypt(encrypted[bs:be], plain[bs:be])
|
||||
for i := 0; i < len(padded); i += blockSize {
|
||||
cipher.Encrypt(encrypted[i:], padded[i:])
|
||||
}
|
||||
|
||||
return encrypted
|
||||
@@ -325,42 +409,50 @@ func DesEcbEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/8qivmPeZy4P
|
||||
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))
|
||||
|
||||
for bs, be := 0, cipher.BlockSize(); bs < len(encrypted); bs, be = bs+cipher.BlockSize(), be+cipher.BlockSize() {
|
||||
cipher.Decrypt(decrypted[bs:be], encrypted[bs:be])
|
||||
for i := 0; i < len(encrypted); i += blockSize {
|
||||
cipher.Decrypt(decrypted[i:], encrypted[i:])
|
||||
}
|
||||
|
||||
trim := 0
|
||||
if len(decrypted) > 0 {
|
||||
trim = len(decrypted) - int(decrypted[len(decrypted)-1])
|
||||
}
|
||||
|
||||
return decrypted[:trim]
|
||||
// Remove padding
|
||||
return pkcs5UnPadding(decrypted)
|
||||
}
|
||||
|
||||
// DesCbcEncrypt encrypt data with key use DES CBC algorithm
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/4cC4QvWfe3_1
|
||||
func DesCbcEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
if len(key) != 8 {
|
||||
panic("des: key length must be 8 bytes")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
data = pkcs7Padding(data, block.BlockSize())
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic("des: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
encrypted := make([]byte, des.BlockSize+len(data))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
blockSize := block.BlockSize()
|
||||
data = pkcs7Padding(data, blockSize)
|
||||
|
||||
encrypted := make([]byte, blockSize+len(data))
|
||||
iv := encrypted[:blockSize]
|
||||
|
||||
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.CryptBlocks(encrypted[des.BlockSize:], data)
|
||||
mode.CryptBlocks(encrypted[blockSize:], data)
|
||||
|
||||
return encrypted
|
||||
}
|
||||
@@ -369,26 +461,33 @@ func DesCbcEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/4cC4QvWfe3_1
|
||||
func DesCbcDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
if len(key) != 8 {
|
||||
panic("des: key length must be 8 bytes")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic("des: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
blockSize := block.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.CryptBlocks(encrypted, encrypted)
|
||||
mode.CryptBlocks(ciphertext, ciphertext)
|
||||
|
||||
decrypted := pkcs7UnPadding(encrypted)
|
||||
return decrypted
|
||||
return pkcs7UnPadding(ciphertext)
|
||||
}
|
||||
|
||||
// DesCtrCrypt encrypt data with key use DES CTR algorithm
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/9-T6OjKpcdw
|
||||
// deprecated: use DesCtrEncrypt and DesCtrDecrypt instead.
|
||||
func DesCtrCrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
@@ -406,25 +505,83 @@ func DesCtrCrypt(data, key []byte) []byte {
|
||||
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.
|
||||
// Play: https://go.dev/play/p/y-eNxcFBlxL
|
||||
func DesCfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
// Play: todo
|
||||
func DesCtrEncrypt(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(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))
|
||||
iv := encrypted[:des.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
copy(encrypted[:des.BlockSize], iv)
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
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.
|
||||
// Play: https://go.dev/play/p/y-eNxcFBlxL
|
||||
func DesCfbDecrypt(encrypted, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
if len(key) != 8 {
|
||||
panic("des: key length must be 8 bytes")
|
||||
}
|
||||
|
||||
block, _ := des.NewCipher(key)
|
||||
if len(encrypted) < des.BlockSize {
|
||||
panic("encrypted data is too short")
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic("des: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
if len(encrypted) < des.BlockSize {
|
||||
panic("des: encrypted data too short")
|
||||
}
|
||||
|
||||
iv := encrypted[:des.BlockSize]
|
||||
encrypted = encrypted[des.BlockSize:]
|
||||
ciphertext := encrypted[des.BlockSize:]
|
||||
|
||||
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
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/74KmNadjN1J
|
||||
func DesOfbEncrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
if len(key) != 8 {
|
||||
panic("des: key length must be 8 bytes")
|
||||
}
|
||||
|
||||
block, err := des.NewCipher(key)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
panic("des: failed to create cipher: " + err.Error())
|
||||
}
|
||||
|
||||
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 {
|
||||
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.XORKeyStream(encrypted[des.BlockSize:], data)
|
||||
|
||||
@@ -484,25 +648,25 @@ func DesOfbEncrypt(data, key []byte) []byte {
|
||||
// len(key) should be 8.
|
||||
// Play: https://go.dev/play/p/74KmNadjN1J
|
||||
func DesOfbDecrypt(data, key []byte) []byte {
|
||||
size := len(key)
|
||||
if size != 8 {
|
||||
panic("key length shoud be 8")
|
||||
if len(key) != 8 {
|
||||
panic("des: key length must be 8 bytes")
|
||||
}
|
||||
|
||||
block, err := des.NewCipher(key)
|
||||
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]
|
||||
data = data[des.BlockSize:]
|
||||
if len(data)%des.BlockSize != 0 {
|
||||
return nil
|
||||
}
|
||||
ciphertext := data[des.BlockSize:]
|
||||
|
||||
decrypted := make([]byte, len(data))
|
||||
mode := cipher.NewOFB(block, iv)
|
||||
mode.XORKeyStream(decrypted, data)
|
||||
stream := cipher.NewOFB(block, iv)
|
||||
decrypted := make([]byte, len(ciphertext))
|
||||
stream.XORKeyStream(decrypted, ciphertext)
|
||||
|
||||
decrypted = pkcs7UnPadding(decrypted)
|
||||
|
||||
@@ -693,117 +857,3 @@ func RsaVerifySign(hash crypto.Hash, data, signature []byte, pubKeyFileName stri
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
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 {
|
||||
genKey := make([]byte, size)
|
||||
@@ -35,3 +46,139 @@ func pkcs7UnPadding(src []byte) []byte {
|
||||
unPadding := int(src[length-1])
|
||||
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
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"github.com/duke-git/lancet/v2/internal"
|
||||
)
|
||||
|
||||
func TestAesEcbEncrypt(t *testing.T) {
|
||||
func TestAesEcbCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -16,11 +16,11 @@ func TestAesEcbEncrypt(t *testing.T) {
|
||||
aesEcbEncrypt := AesEcbEncrypt([]byte(data), []byte(key))
|
||||
aesEcbDecrypt := AesEcbDecrypt(aesEcbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesEcbEncrypt")
|
||||
assert := internal.NewAssert(t, "TestAesEcbCrypt")
|
||||
assert.Equal(data, string(aesEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesCbcEncrypt(t *testing.T) {
|
||||
func TestAesCbcCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -29,7 +29,7 @@ func TestAesCbcEncrypt(t *testing.T) {
|
||||
aesCbcEncrypt := AesCbcEncrypt([]byte(data), []byte(key))
|
||||
aesCbcDecrypt := AesCbcDecrypt(aesCbcEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCbcEncrypt")
|
||||
assert := internal.NewAssert(t, "TestAesCbcCrypt")
|
||||
assert.Equal(data, string(aesCbcDecrypt))
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ func TestAesCtrCrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefghijklmnop"
|
||||
|
||||
aesCtrCrypt := AesCtrCrypt([]byte(data), []byte(key))
|
||||
aesCtrDeCrypt := AesCtrCrypt(aesCtrCrypt, []byte(key))
|
||||
aesCtrCrypt := AesCtrEncrypt([]byte(data), []byte(key))
|
||||
aesCtrDeCrypt := AesCtrDecrypt(aesCtrCrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCtrCrypt")
|
||||
assert.Equal(data, string(aesCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestAesCfbEncrypt(t *testing.T) {
|
||||
func TestAesCfbCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -55,11 +55,11 @@ func TestAesCfbEncrypt(t *testing.T) {
|
||||
aesCfbEncrypt := AesCfbEncrypt([]byte(data), []byte(key))
|
||||
aesCfbDecrypt := AesCfbDecrypt(aesCfbEncrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestAesCfbEncrypt")
|
||||
assert := internal.NewAssert(t, "TestAesCfbCrypt")
|
||||
assert.Equal(data, string(aesCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestAesOfbEncrypt(t *testing.T) {
|
||||
func TestAesOfbCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -72,7 +72,7 @@ func TestAesOfbEncrypt(t *testing.T) {
|
||||
assert.Equal(data, string(aesOfbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesEcbEncrypt(t *testing.T) {
|
||||
func TestDesEcbCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -85,7 +85,7 @@ func TestDesEcbEncrypt(t *testing.T) {
|
||||
assert.Equal(data, string(desEcbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesCbcEncrypt(t *testing.T) {
|
||||
func TestDesCbcCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -104,14 +104,14 @@ func TestDesCtrCrypt(t *testing.T) {
|
||||
data := "hello world"
|
||||
key := "abcdefgh"
|
||||
|
||||
desCtrCrypt := DesCtrCrypt([]byte(data), []byte(key))
|
||||
desCtrDeCrypt := DesCtrCrypt(desCtrCrypt, []byte(key))
|
||||
desCtrCrypt := DesCtrEncrypt([]byte(data), []byte(key))
|
||||
desCtrDeCrypt := DesCtrDecrypt(desCtrCrypt, []byte(key))
|
||||
|
||||
assert := internal.NewAssert(t, "TestDesCtrCrypt")
|
||||
assert.Equal(data, string(desCtrDeCrypt))
|
||||
}
|
||||
|
||||
func TestDesCfbEncrypt(t *testing.T) {
|
||||
func TestDesCfbCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
@@ -124,7 +124,7 @@ func TestDesCfbEncrypt(t *testing.T) {
|
||||
assert.Equal(data, string(desCfbDecrypt))
|
||||
}
|
||||
|
||||
func TestDesOfbEncrypt(t *testing.T) {
|
||||
func TestDesOfbCrypt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
data := "hello world"
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
-----BEGIN rsa private key-----
|
||||
MIIJKQIBAAKCAgEAtXr+2FbR6Prdf9U0gfq2OJbTD82m84bbdeyfsakabYp8Haw6
|
||||
mZW6ebRNPJvQ87H6DbA55hK1E7y6m+wjvbUopnkGh75Cp04CoQvaU8Rs7MrQcJ2Z
|
||||
z1VRRgugmqwJMWE/FC5eGXvvpDjF2h2lqThKZTKcvhqfZ3dNX+6v4EQ4BbjSGKdz
|
||||
pyexzR1WSV9IzZYRHMk8jCoEHOx9ItEzoToBf9yAq0DhufylqSRbjKLhR7A3IiRS
|
||||
LVNfu0Sz5cfNlS7eUA060QS8AV9BgGNTkl75aj8BCOmoHIW85SsSZvdQWYwmlM76
|
||||
Jn+tfNNnY7Uuqtz2gI1odcy1nXembXWJryxuYCkSAwpU8UNIQpZeKwBnBxaf0pj3
|
||||
W1m3UzEqhGkkCrKq8LkNSGZSkhT+bI65fNx2LZ7lS165szkeyqS8aikxcBpdx7Z/
|
||||
bqbFFuI42KX+IpXAJCAtvsQ0XXinr83MLcY/I2Ic/5Sgz7txfZsKKwKt48ETS9Bj
|
||||
xGPWo1Dd5YjM8ZJWJv2Rf0mwVjUMClFSNBm8x+aWGVIKjpocN/plpEZmFrWdPcWM
|
||||
4ZH3qGCEnVVkqPvqClahNSQXsM4W7msYts1IUq31tjBSV5bL6l2K8jFJa4PRYdzh
|
||||
1vHhDOAYTpgDkQbNaoDlDS2o/0TkAGUfXWJtR3D35wRJzoa7bCMt5BuFE3sCAwEA
|
||||
AQKCAgEAm/OsGEDTdcBOo9GVo7TM7mg9y7DQLSnQYdALk2JcAZImAmHEocLXUkqs
|
||||
rM7BiwmAdk7gEmQ1E1b1jZQpSpbo7dXG1NOc96TEAZzr61w6tmm7IWtth4wroWPQ
|
||||
idoYtER7Ll6CIqgsURUwgLVFbNugosIRjBPYs9MDvNKidLhq5A/lC6aqbhRgaIEz
|
||||
ay3kpDa3UeNkkpZwnmJjTo40LfJo43WbZI8G6wq/WVCTE5HMwgwd9Mr9i1HATG9H
|
||||
oMhIVFDIXkZgKspEvXEcGrZAVOIktzaZLw2Ll6cdolmXIMCaXblgVjRfJsJFVaVd
|
||||
jYNfLRlhAyuBfumBkGYHsLx2qwAlgC1gCY/72RAtpQWTsefNp9Athztj7iAbwW67
|
||||
AgWlz44TOxtp2JTZOQZs9Douunp+DNFzA30bJasyWD+EZcUdyxMWhW27b2EQFfjP
|
||||
XefmjJKkfTuG4f/Oti+Qqy6qnd/L22iph6WuAzSBCUAdkyHwvFwK32H971aNLqlA
|
||||
nBUn9/CYZ9m4oiR2bqide4B2P3/3wzFyLTHZqwaJDBnHV4nVUy+CxGsbhIyXLyCq
|
||||
csmWaP9VUKCgIlI1B7MY5puHaYULKWnVye8+ges363ndvGEtdvke/9qkyNgc2Kxi
|
||||
ZNKIzZWihoBa1pPqqsSEm99L70TpXfdca6M3+2teLm63dk0cPpECggEBAOm52TD2
|
||||
l3waYVyh85IJZo9fgtemlOJ7vSzEWivscYzqwzY+xfQuvj4lFOxHno/wu0lORD3a
|
||||
1xzC9v+OBvIKpX5PQ9bbS+Oe94kZMZmtF4oyPpvmPbSIhZvASWq/oaMSpq9RIINW
|
||||
13o91q37leXCj3XhEmqWbStbMwJ7aRU45K7qKbMMM9EmsageBykoyy3PfHFZvsAh
|
||||
joQWRCFSmso94YBrpT0rZj9t57y3j9zrCTc+5T0OXkA69yhKrkwL6JQowMHbisx9
|
||||
p+c4467vdwAaDx14/EYERkqiNjxWS1zCfenTvBs7Gu+/C+/4gZnt2I8vbsTf9wyP
|
||||
g2Hg/V/txAGreF8CggEBAMbGhtowf7TgFvn3T9fmFEBaCIe+m888hkTamiGLUrDh
|
||||
HCTO34vHMo/5Tds3Fy1c/BPvECV3wv/Nln046MuMuLIkIbk3uhVmVEFKGKMlqq6H
|
||||
KRd+PErAf59FQ3Yfkqm7/JnBPgdvgzPmc09SAafHgiogMuu4FFDob+LSENuZl0zA
|
||||
U6Xr9nQphB4IxG15dVSEDKQhlhcTGQy0VBx6sskg6897MuJduDJiNPjQpWmGDuji
|
||||
9xuNURVy4FuHYr9yUEDBwWkL8VjKwzASDgK0b38knUpThP33W/TZgQWewFfSD6Nq
|
||||
fBBmct7JYfLNEwItlr/NOF9Q+KIeB9E3Ok+xO99BKmUCggEAbBWg5e6zQRXl/nN6
|
||||
cwdb4WOW22lSoqX8Zs5qsLNIE5WhLt26p2BSY+S8F0RLhF8cDRtfnYctQUS7+pRQ
|
||||
i+/2dkHrqlmBb8Lc0A7RjDKqlyMDJw9Da9BSkSNMEEyMUCBY6uxGb9ZiEUq1k4Gr
|
||||
4TOnKikqXhYwaANlxHkTsFe+EVGCdSVodQlC0O8J+rO9ufKgpr6M4sbh5B1z5kEQ
|
||||
CgSx2rRtFquSPjTyHKh6o/whJ+YzFpglZ+ic0YovrkU3igSKl1uShVx6oAgD6qsc
|
||||
yfRDFysS5sIlS3BWSnLRqRTcK5zZ+XHM1B/yQkgWjvuZ0SVrQSodUjav2Dy2j30h
|
||||
zm/gWwKCAQBXUun1Oq8vz+5oG/zIlTw6VRNARz192lIGN57Us7c9G3fYt8U/S+Br
|
||||
nZNVhas584qOW0zVmPpilHfTRUgH/Cc7o2HpU5D9S7oiAKI4Mhj8mUY1GvDzygOG
|
||||
/c+4OgCdbod3KIzOiW+zQj9QDm/JvHzzcrfMFE9gh+x3Ud+0CZKNVkSpNLNNrttq
|
||||
smFQ0rX3zhcbl+Gu+2XazfHRnRmkAEF4IeBlz9RW1gv9bvPsGse8CdGTGg8QBCqK
|
||||
Kzz3bAnTmQsV0fhSEKmVGalsCMaerYAoIe7f/2Y3d8IVrPtE2XSjTul37vnx47iT
|
||||
CQKbx1ldo5NrVFAWMGkwwTltvyfVWXR9AoIBAQC6lS+ptioI/jUX7L+OQQJvrspW
|
||||
jjxzW+JsCVdm6FvVGgWHMkcdUg5JIUvBj+ifBkIgqReiHr9AtNX5NooxR449B7zK
|
||||
HNsaNqCs2V0gT9vgGaPvakC4ThKQf8vSUF04ECMdFmxJTvlCM3mGbxn/M4bE4OPc
|
||||
ypMb1qh4AhJyt4PMP1Ds8TAjmNRQ9LhoITXcuzlgZIbvOyA6Nz7dz5w3iUoOMyTl
|
||||
SvZ1jMvHGiKHJJD0oYsf1q2YcNvBGT7lvOxJF1LR0AKgfTuqckJOVX4SdiWjgnEI
|
||||
oEPbjc5sl4Vq+DDNstIQC4/vGbAkeFDozaU+rySXTS2QESyNj9EtbW/uOkLr
|
||||
MIIJKQIBAAKCAgEAwUdYQvqsym2r86Xlcu8CzK6MAjtZH3aW/BsfZ852dra1nYGq
|
||||
UoJMe31eiurN9BK/OXmo7D3zm3OCCl/uGUCiNgWKYAfaW2o4rFE7tHwHf5E4/bLm
|
||||
p2c6+xwP5bSo6r0pXonszPpMK4sTHNxgaXLhHYdx1dKXWt5SvHXo012fWsXTC7MQ
|
||||
rpTeQIOZViC3ldQpXO026nKzwzgr7WW9kZakHYPz0IdwQGkl6/EY3LpnP3ADsop9
|
||||
HWZmTIcZUfaztdwnC9JS4zJg1gGMioQXgavlPOVEDmXk8Oi+1ORB6CphlovSeuT9
|
||||
IxIoSlv77ARazKZcTfnxzXgpPT2wBdiGiTvq2/vON1IvjDPd4MkBYEx3k5tbdL//
|
||||
HjzkKlg/zElELvrXEQFpdvzCdrqrTDQ56ej1A5AH1q6eIJULh5hhq5jLIxkSYiiC
|
||||
rXYlTSPX7D9t7PLHj5AVv2PkHhuU1pwv7HnLsPfTwxYcxjygLP8lJPPE+y8UJLFC
|
||||
OUKkPr9dGLqA8G6ZvWhYHTyiwVEENwb+RdV2lakg7YNgRfEymvY3HqiiZiH8T7eO
|
||||
c1tt/eF3gDbG2jjlD83cxYetYFNgtSk/+0gydBQKRR+w8PUTdLb1ZZhzk/7yZCrr
|
||||
sh043967ECjNI5hyvSYdR+sj3W9i39Jj/4JSX05C9FKEAehvubw9V/AMXcMCAwEA
|
||||
AQKCAgEAk0BRxCXLQyYvHR/FIb1qupo43PJuQgRNn6DiWmn34xXsZCWHp/jRYDvx
|
||||
rZCafFtUCOvhgKrqUAK+jjzr351YeCPcerFA8OiKaO4yuJzN8aiobNDB3cROMUX9
|
||||
7pmnH8AiJn6aRMhlA7+fPhu/8Favn5mzZp5c5cP/8Mk8KtxnLfcNhRpVmUydzzTz
|
||||
u6SNeb78DGpFrnTY8+B1xxX+SU8llb8UIEkvgkMZuxoiQPha9P/YMUxFagK76Y38
|
||||
AnAcFm+159HDiIi3MhRYCKf+aLKXob9iDD4hIFGSIgwNEl5HnzTDlRGksfWBcLWH
|
||||
xxbCPqx4IohMaqgjcx7uXmXKif92O/QlDw2JGSZX87jdcJTkqc420yGxSOd4xW0j
|
||||
vw1f4dRzQ9pr9S8k9RyXgNLT4a1eXYCjLNRZ9/NZqC16FgbG9kl4/AaBqSEhKURa
|
||||
ZG2uk8zBmej8FJeHUV8KFSnuaaiHwY5weN+afyWt2oqvydM444B0XG/IdAdgYUDY
|
||||
0CHs9wFcLYs+MfJWk3D+U0/zmcNfLC1e7qJOTheJIWJ2oCLDP3s7+7Bo+7anLRCK
|
||||
1vXVOmTeWgJ2cLSPi7y9UKjjvm7/Fi3zZclTodZjEKxsDpQ+aE9ihqxjsWjYvJ7E
|
||||
EeUhu9UhMfYbjVRavxWO0CKnJA+ZPLM1y57iarQkBslvHkBM6gECggEBANmzuYwP
|
||||
PoWw61sbsRmXsOmGoJJ0RGbB5i3xH0E2Us/+dLMseUi+Z17jccFa9cpYBQEh0PYJ
|
||||
bmU8r69yqjzOLmvCVJb5wRiXof4yGmsXwSWQD/wA0gTka/+iFSiUZtS+0t0qUxce
|
||||
UXM1KQF8tJNPgvivY5jhbaoUgb6TNe0/vX3bRXSnIf3CqRBdpO3jZKwXU8VOFwjZ
|
||||
nwoIv0Fki+FWAHHINz8gMmaCDypgzQOOqFd8g7uQLD1tGZhroo479r1+bQU6KBPD
|
||||
T/9CZwk9g7KVo9boYWH9UaQfi56mUxY1N3MexySecNdORWuqNWut0/H3M88lhM34
|
||||
qe0Wiw9F2B/nSIECggEBAONHtPW3Q7nr5PzD44umf6IRMxbt7Op667tuZELECwHv
|
||||
lspWYgFyHmIqfjLmj0rXD3ElrIKzSyJLdO3VdtlssSj75ehB7yvMOnRFBld0MtGr
|
||||
laHveGGSt9RLKu2GEnFEzf5ZdP/zay10U0426Q4c26RfS1095pN2hQSst7BNDvoJ
|
||||
5RzNaSDo0oPOwYXmJzGh3zrgnAB+jIozlbuR4sP/60JSEHhTHr1jxC57CprRfG3e
|
||||
ZV4Lu+dTde3847tYeeDsoCZrrwN97A2CgoeUHs6oAfLi8QUHsiVu0okG5uy8fApv
|
||||
j2JCEMI60+Nej+q9elWFLjOO79O3zwWUFr6n8pUyZEMCggEARYdsFDpuKn6lvHRs
|
||||
rJLQ8tSHhh7SFcuJu1SOOeKiskE/flYO6le9ZgXYN/vYEmboOkNVnK7IblbieXNy
|
||||
wXbMRqhLIejkbflHyIqx+1Ab5OZM5JxSdzOI9p0KiupSqVHEwNQas4CAXP42eX4d
|
||||
ogq79rb1ZUdiIfbotTgI+hvoZkDYvvf+GDDKlCqEWWHNrlTI8XQOUUpHzAmdI8J8
|
||||
FlzESZK7alLbJfgV5eACukcepspivE3Ag2HL0e1WfnzSQhUVtpyrXhx7+Td49u+J
|
||||
l0jJigKvz377SyK0EdhnIumeKwtCaQSdX3ZlH4y+AQUEcvwTtO3zq2DmzIztntQc
|
||||
wZu5gQKCAQEAgZESb3WvbWE2ZIaDxMwBPPITLwIqKq4yjuJq08kRAWSFkQnXyz00
|
||||
ZwAUe44GqEKb8gPpKYVu0rkzipZDr8WP5W5c7aAQ6eX+eOQUrmx2wCLSJcPv26gZ
|
||||
ljPX4BqrjtkLmfGDippJQltrVk5lY/89k6Ijw58TQIOzZyvTd/UmEZLsgxPy16kC
|
||||
wdNvbZb8RwYhzV3YcUuzcOHhfVG4dcYCZweDjiTMhGlIoLrSG9pK1hOPtCJ6V3Cz
|
||||
7R1a8iWJLZmX3u9KkXIKzNTW9tWRDnymx8FqZ1Sw0TgxW56MrO7yw7w/gGNrTF7f
|
||||
BmKVJtwnznMjGI9m10qVAXgf00bJOxbEIwKCAQBjylF+1MU629WE+1CIfLtc8v5W
|
||||
FRjDYq1lfdbZxqXOKtDkk0cpeRNLNBqdltfl37whi/kTA1ZsYdY+tf2xAewvLlGQ
|
||||
v0YRslw7/KeZQJiCgG7S3CSoV16EJBNsc/wsQukaoM943kgLHGjb6Prie40TPWSZ
|
||||
x5XJk3bJLNF/24qXbeFpPdHptZympiE8/jrSUUMmum8IZeeRXghsi3S/gwFwlXb0
|
||||
mrSuZGmcb7za9pK050CYbSQ2/HoVpBGe9E6B1Ad0jSFfbVCd5vZz+4f4/tB/AEY9
|
||||
7XwzpkGrEyWiys2o0XhRv8rMlTDJfU3E8aVwJwEGJOMA5aU1ZJcFAcvIsGlv
|
||||
-----END rsa private key-----
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
-----BEGIN rsa public key-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtXr+2FbR6Prdf9U0gfq2
|
||||
OJbTD82m84bbdeyfsakabYp8Haw6mZW6ebRNPJvQ87H6DbA55hK1E7y6m+wjvbUo
|
||||
pnkGh75Cp04CoQvaU8Rs7MrQcJ2Zz1VRRgugmqwJMWE/FC5eGXvvpDjF2h2lqThK
|
||||
ZTKcvhqfZ3dNX+6v4EQ4BbjSGKdzpyexzR1WSV9IzZYRHMk8jCoEHOx9ItEzoToB
|
||||
f9yAq0DhufylqSRbjKLhR7A3IiRSLVNfu0Sz5cfNlS7eUA060QS8AV9BgGNTkl75
|
||||
aj8BCOmoHIW85SsSZvdQWYwmlM76Jn+tfNNnY7Uuqtz2gI1odcy1nXembXWJryxu
|
||||
YCkSAwpU8UNIQpZeKwBnBxaf0pj3W1m3UzEqhGkkCrKq8LkNSGZSkhT+bI65fNx2
|
||||
LZ7lS165szkeyqS8aikxcBpdx7Z/bqbFFuI42KX+IpXAJCAtvsQ0XXinr83MLcY/
|
||||
I2Ic/5Sgz7txfZsKKwKt48ETS9BjxGPWo1Dd5YjM8ZJWJv2Rf0mwVjUMClFSNBm8
|
||||
x+aWGVIKjpocN/plpEZmFrWdPcWM4ZH3qGCEnVVkqPvqClahNSQXsM4W7msYts1I
|
||||
Uq31tjBSV5bL6l2K8jFJa4PRYdzh1vHhDOAYTpgDkQbNaoDlDS2o/0TkAGUfXWJt
|
||||
R3D35wRJzoa7bCMt5BuFE3sCAwEAAQ==
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwUdYQvqsym2r86Xlcu8C
|
||||
zK6MAjtZH3aW/BsfZ852dra1nYGqUoJMe31eiurN9BK/OXmo7D3zm3OCCl/uGUCi
|
||||
NgWKYAfaW2o4rFE7tHwHf5E4/bLmp2c6+xwP5bSo6r0pXonszPpMK4sTHNxgaXLh
|
||||
HYdx1dKXWt5SvHXo012fWsXTC7MQrpTeQIOZViC3ldQpXO026nKzwzgr7WW9kZak
|
||||
HYPz0IdwQGkl6/EY3LpnP3ADsop9HWZmTIcZUfaztdwnC9JS4zJg1gGMioQXgavl
|
||||
POVEDmXk8Oi+1ORB6CphlovSeuT9IxIoSlv77ARazKZcTfnxzXgpPT2wBdiGiTvq
|
||||
2/vON1IvjDPd4MkBYEx3k5tbdL//HjzkKlg/zElELvrXEQFpdvzCdrqrTDQ56ej1
|
||||
A5AH1q6eIJULh5hhq5jLIxkSYiiCrXYlTSPX7D9t7PLHj5AVv2PkHhuU1pwv7HnL
|
||||
sPfTwxYcxjygLP8lJPPE+y8UJLFCOUKkPr9dGLqA8G6ZvWhYHTyiwVEENwb+RdV2
|
||||
lakg7YNgRfEymvY3HqiiZiH8T7eOc1tt/eF3gDbG2jjlD83cxYetYFNgtSk/+0gy
|
||||
dBQKRR+w8PUTdLb1ZZhzk/7yZCrrsh043967ECjNI5hyvSYdR+sj3W9i39Jj/4JS
|
||||
X05C9FKEAehvubw9V/AMXcMCAwEAAQ==
|
||||
-----END rsa public key-----
|
||||
|
||||
@@ -662,15 +662,22 @@ func IntSlice(slice any) []int {
|
||||
// DeleteAt delete the element of slice at index.
|
||||
// Play: https://go.dev/play/p/800B1dPBYyd
|
||||
func DeleteAt[T any](slice []T, index int) []T {
|
||||
if index >= len(slice) {
|
||||
index = len(slice) - 1
|
||||
if index < 0 || index >= len(slice) {
|
||||
return slice[:len(slice)-1]
|
||||
}
|
||||
|
||||
result := make([]T, len(slice)-1)
|
||||
copy(result, slice[:index])
|
||||
copy(result[index:], slice[index+1:])
|
||||
result := append([]T(nil), slice...)
|
||||
copy(result[index:], result[index+1:])
|
||||
|
||||
return result
|
||||
// Set the last element to zero value, clean up the memory.
|
||||
result[len(result)-1] = zeroValue[T]()
|
||||
|
||||
return result[:len(result)-1]
|
||||
}
|
||||
|
||||
func zeroValue[T any]() T {
|
||||
var zero T
|
||||
return zero
|
||||
}
|
||||
|
||||
// DeleteRange delete the element of slice from start index to end index(exclude).
|
||||
|
||||
Reference in New Issue
Block a user