You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
starcrypto/crypto.go

738 lines
15 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package starcrypto
import (
"bufio"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"hash"
"hash/crc32"
"io"
"io/ioutil"
rands "math/rand"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
)
func String(bstr []byte) string {
return hex.EncodeToString(bstr)
}
// MD5 输出MD5校验值
func Md5(bstr []byte) []byte {
md5sum := md5.New()
md5sum.Write(bstr)
return md5sum.Sum(nil)
}
func Md5Str(bstr []byte) string {
return String(Md5(bstr))
}
// CRC32 输出CRC32校验值
func Crc32(bstr []byte) []byte {
crcsum := crc32.NewIEEE()
crcsum.Write(bstr)
return crcsum.Sum(nil)
}
func Crc32Str(bstr []byte) string {
return String(Crc32(bstr))
}
// SHA512 输出SHA512校验值
func Sha512(bstr []byte) []byte {
shasum := sha512.New()
shasum.Write(bstr)
return shasum.Sum(nil)
}
func Sha512Str(bstr []byte) string {
return String(Sha512(bstr))
}
// SHA384 输出SHA384校验值
func Sha384(bstr []byte) []byte {
shasum := sha512.New384()
shasum.Write(bstr)
return shasum.Sum(nil)
}
func Sha384Str(bstr []byte) string {
return String(Sha384(bstr))
}
// SHA256 输出SHA256校验值
func Sha256(bstr []byte) []byte {
shasum := sha256.New()
shasum.Write(bstr)
return shasum.Sum(nil)
}
func Sha256Str(bstr []byte) string {
return String(Sha256(bstr))
}
// SHA224 输出SHA224校验值
func Sha224(bstr []byte) []byte {
shasum := sha256.New224()
shasum.Write(bstr)
return shasum.Sum(nil)
}
func Sha224Str(bstr []byte) string {
return String(Sha224(bstr))
}
// SHA1 输出SHA1校验值
func Sha1(bstr []byte) []byte {
shasum := sha1.New()
shasum.Write(bstr)
return shasum.Sum(nil)
}
func Sha1Str(bstr []byte) string {
return String(Sha512(bstr))
}
// SumAll 可以对同一数据进行多种校验
func SumAll(data []byte, method []string) (map[string][]byte, error) {
result := make(map[string][]byte)
methods := make(map[string]hash.Hash)
var iscrc bool
if len(method) == 0 {
method = []string{"sha512", "sha256", "sha384", "sha224", "sha1", "crc32", "md5"}
}
sum512 := sha512.New()
sum384 := sha512.New384()
sum256 := sha256.New()
sum224 := sha256.New224()
sum1 := sha1.New()
crcsum := crc32.NewIEEE()
md5sum := md5.New()
for _, v := range method {
switch v {
case "md5":
methods["md5"] = md5sum
case "crc32":
iscrc = true
case "sha1":
methods["sha1"] = sum1
case "sha224":
methods["sha224"] = sum224
case "sha256":
methods["sha256"] = sum256
case "sha384":
methods["sha384"] = sum384
case "sha512":
methods["sha512"] = sum512
}
}
for _, v := range methods {
v.Write(data)
}
if iscrc {
crcsum.Write(data)
}
for k, v := range methods {
result[k] = v.Sum(nil)
}
if iscrc {
result["crc32"] = crcsum.Sum(nil)
}
return result, nil
}
// FileSum 输出文件内容校验值method为单个校验方法,小写
//例FileSum("./test.txt","md5",shell(pect float64){fmt.Sprintf("已完成 %f\r",pect)})
func FileSum(filepath, method string, shell func(float64)) (string, error) {
var sum hash.Hash
var sum32 hash.Hash32
var issum32 bool
var result string
fp, err := os.Open(filepath)
if err != nil {
return "", err
}
switch method {
case "sha512":
sum = sha512.New()
case "sha384":
sum = sha512.New384()
case "sha256":
sum = sha256.New()
case "sha224":
sum = sha256.New224()
case "sha1":
sum = sha1.New()
case "crc32":
sum32 = crc32.NewIEEE()
issum32 = true
case "md5":
sum = md5.New()
default:
return "", errors.New("Cannot Recognize The Method:" + method)
}
writer := 0
stat, _ := os.Stat(filepath)
filebig := float64(stat.Size())
if !issum32 {
// if _, err := io.Copy(sum, fp); err != nil {
for {
buf := make([]byte, 1048574)
n, err := fp.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return result, err
}
writer += n
pect := (float64(writer) / filebig) * 100
go shell(pect)
sum.Write(buf[0:n])
}
result = hex.EncodeToString(sum.Sum(nil))
} else {
for {
buf := make([]byte, 1048574)
n, err := fp.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return result, err
}
writer += n
pect := (float64(writer) / filebig) * 100
go shell(pect)
sum32.Write(buf[0:n])
}
result = hex.EncodeToString(sum32.Sum(nil))
}
return result, nil
}
// FileSumAll 可以对同一文件进行多种校验
func FileSumAll(filepath string, method []string, shell func(float64)) (map[string]string, error) {
result := make(map[string]string)
methods := make(map[string]hash.Hash)
var iscrc bool
if len(method) == 0 {
method = []string{"sha512", "sha256", "sha384", "sha224", "sha1", "crc32", "md5"}
}
fp, err := os.Open(filepath)
defer fp.Close()
if err != nil {
return result, err
}
stat, _ := os.Stat(filepath)
filebig := float64(stat.Size())
sum512 := sha512.New()
sum384 := sha512.New384()
sum256 := sha256.New()
sum224 := sha256.New224()
sum1 := sha1.New()
crcsum := crc32.NewIEEE()
md5sum := md5.New()
for _, v := range method {
switch v {
case "md5":
methods["md5"] = md5sum
case "crc32":
iscrc = true
case "sha1":
methods["sha1"] = sum1
case "sha224":
methods["sha224"] = sum224
case "sha256":
methods["sha256"] = sum256
case "sha384":
methods["sha384"] = sum384
case "sha512":
methods["sha512"] = sum512
}
}
writer := 0
for {
buf := make([]byte, 1048574)
n, err := fp.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return result, err
}
writer += n
pect := (float64(writer) / filebig) * 100
go shell(pect)
for _, v := range methods {
v.Write(buf[0:n])
}
if iscrc {
crcsum.Write(buf[0:n])
}
}
for k, v := range methods {
result[k] = hex.EncodeToString(v.Sum(nil))
}
if iscrc {
result["crc32"] = hex.EncodeToString(crcsum.Sum(nil))
}
return result, nil
}
// Attach 合并src与dst文件并输出到output中
func Attach(src, dst, output string) error {
fpsrc, err := os.Open(src)
if err != nil {
return err
}
defer fpsrc.Close()
fpdst, err := os.Open(dst)
if err != nil {
return err
}
defer fpdst.Close()
fpout, err := os.Create(output)
if err != nil {
return err
}
defer fpout.Close()
if _, err := io.Copy(fpout, fpsrc); err != nil {
return err
}
for {
buf := make([]byte, 1048574)
n, err := fpdst.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
fpout.Write(buf[0:n])
}
return nil
}
// Detach 按bytenum字节大小分割src文件到dst1与dst2两个新文件中去
func Detach(src string, bytenum int, dst1, dst2 string) error {
fpsrc, err := os.Open(src)
if err != nil {
return err
}
defer fpsrc.Close()
fpdst1, err := os.Create(dst1)
if err != nil {
return err
}
defer fpdst1.Close()
fpdst2, err := os.Create(dst2)
if err != nil {
return err
}
defer fpdst2.Close()
sumall := 0
var buf []byte
for {
if bytenum-sumall < 1048576 {
buf = make([]byte, bytenum-sumall)
} else {
buf = make([]byte, 1048576)
}
n, err := fpsrc.Read(buf)
if err != nil {
return err
}
sumall += n
fpdst1.Write(buf[0:n])
if sumall == bytenum {
break
}
}
for {
buf = make([]byte, 1048576)
n, err := fpsrc.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
fpdst2.Write(buf[0:n])
}
return nil
}
// SplitFile 把src文件按要求分割到dst中去,dst应传入带*号字符串
// 如果bynum=true 则把文件分割成num份
// 如果bynum=false 则把文件按num字节分成多份
func SplitFile(src, dst string, num int, bynum bool, shell func(float64)) error {
fpsrc, err := os.Open(src)
if err != nil {
return err
}
defer fpsrc.Close()
stat, _ := os.Stat(src)
filebig := float64(stat.Size())
if bynum {
if int(filebig) < num {
return errors.New("file is too small to split")
}
}
balance := int(filebig/float64(num)) + 1
if !bynum {
balance = num
}
nownum := 0
fpdst, err := os.Create(strings.Replace(dst, "*", fmt.Sprint(nownum), -1))
if err != nil {
return err
}
defer fpdst.Close()
var sum, tsum int = 0, 0
var buf []byte
for {
if balance-sum < 1048576 {
buf = make([]byte, balance-sum)
} else {
buf = make([]byte, 1048576)
}
n, err := fpsrc.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
sum += n
tsum += n
fpdst.Write(buf[0:n])
go shell(float64(tsum) / filebig * 100)
if sum == balance {
fpdst.Close()
nownum++
fpdst, err = os.Create(strings.Replace(dst, "*", fmt.Sprint(nownum), -1))
if err != nil {
return err
}
sum = 0
}
}
return nil
}
// MergeFile 合并src文件到dst文件中去src文件应传入带*号字符串
func MergeFile(src, dst string, shell func(float64)) error {
tmp := strings.Replace(src, "*", "0", -1)
dir, err := ioutil.ReadDir(filepath.Dir(tmp))
if err != nil {
return err
}
base := filepath.Base(src)
tmp = strings.Replace(base, "*", "(\\d+)", -1)
reg := regexp.MustCompile(tmp)
count := 0
var filebig float64
for _, v := range dir {
if reg.MatchString(v.Name()) {
count++
filebig += float64(v.Size())
}
}
fpdst, err := os.Create(dst)
defer fpdst.Close()
if err != nil {
return err
}
var sum int64
for i := 0; i < count; i++ {
fpsrc, err := os.Open(strings.Replace(src, "*", strconv.Itoa(i), -1))
if err != nil {
return err
}
for {
buf := make([]byte, 1048576)
n, err := fpsrc.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
sum += int64(n)
go shell(float64(sum) / filebig * 100)
fpdst.Write(buf[0:n])
}
fpsrc.Close()
}
return nil
}
// VicqueEncodeV1 Best
func VicqueEncodeV1(srcdata []byte, key string) []byte {
var keys []int
var saku, piku uint8
data := make([]byte, len(srcdata))
copy(data, srcdata)
binary.Read(rand.Reader, binary.LittleEndian, &saku)
binary.Read(rand.Reader, binary.LittleEndian, &piku)
keys = append(keys, len(key)+int(saku))
lens := len(data)
for _, v := range key {
keys = append(keys, int(byte(v))+int(saku)-int(piku))
}
lenkey := len(keys)
for k, v := range data {
if k == lens/2 {
break
}
nv := int(v)
t := 0
if k%2 == 0 {
nv += keys[k%lenkey]
if nv > 255 {
nv -= 256
}
t = int(data[lens-1-k])
t += keys[k%lenkey]
if t > 255 {
t -= 256
}
} else {
nv -= keys[k%lenkey]
if nv < 0 {
nv += 256
}
t = int(data[lens-1-k])
t -= keys[k%lenkey]
if t > 255 {
t += 256
}
}
data[k] = byte(t)
data[lens-1-k] = byte(nv)
}
data = append(data, byte(saku), byte(piku))
return data
}
// VicqueDecodeV1 Best
func VicqueDecodeV1(srcdata []byte, key string) []byte {
var keys []int
var saku, piku int
data := make([]byte, len(srcdata))
copy(data, srcdata)
lens := len(data)
saku = int(data[lens-2])
piku = int(data[lens-1])
keys = append(keys, len(key)+int(saku))
for _, v := range key {
keys = append(keys, int(byte(v))+int(saku)-int(piku))
}
lenkey := len(keys)
lens -= 2
for k, v := range data {
if k == lens/2 {
break
}
nv := int(v)
t := 0
if k%2 == 0 {
nv -= keys[k%lenkey]
if nv < 0 {
nv += 256
}
t = int(data[lens-1-k])
t -= keys[k%lenkey]
if t > 255 {
t += 256
}
} else {
nv += keys[k%lenkey]
if nv > 255 {
nv -= 256
}
t = int(data[lens-1-k])
t += keys[k%lenkey]
if t > 255 {
t -= 256
}
}
data[k] = byte(t)
data[lens-1-k] = byte(nv)
}
return data[:lens]
}
// VicqueEncodeV1File best
func VicqueEncodeV1File(src, dst, pwd string, shell func(float64)) error {
fpsrc, err := os.Open(src)
if err != nil {
return err
}
defer fpsrc.Close()
stat, _ := os.Stat(src)
filebig := float64(stat.Size())
var sum int64
defer fpsrc.Close()
fpdst, err := os.Create(dst)
if err != nil {
return err
}
defer fpdst.Close()
for {
buf := make([]byte, 1048576)
n, err := fpsrc.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
sum += int64(n)
go shell(float64(sum) / filebig * 100)
data := VicqueEncodeV1(buf[0:n], pwd)
fpdst.Write(data)
}
return nil
}
// VicqueDecodeV1File best
func VicqueDecodeV1File(src, dst, pwd string, shell func(float64)) error {
fpsrc, err := os.Open(src)
if err != nil {
return err
}
defer fpsrc.Close()
stat, _ := os.Stat(src)
filebig := float64(stat.Size())
var sum int64
defer fpsrc.Close()
fpdst, err := os.Create(dst)
if err != nil {
return err
}
defer fpdst.Close()
for {
buf := make([]byte, 1048578)
n, err := fpsrc.Read(buf)
if err != nil {
if err == io.EOF {
break
}
return err
}
sum += int64(n)
go shell(float64(sum) / filebig * 100)
data := VicqueDecodeV1(buf[0:n], pwd)
fpdst.Write(data)
}
return nil
}
// FillWithRandom 随机写filesize大小的文件每次buf大小为bufcap随机bufnum个字符
func FillWithRandom(filepath string, filesize int, bufcap int, bufnum int, shell func(float64)) error {
var buf [][]byte
var buftmp []byte
rands.Seed(time.Now().Unix())
if bufnum <= 0 {
bufnum = 1
}
if bufcap > filesize {
bufcap = filesize
}
myfile, err := os.Create(filepath)
if err != nil {
return err
}
defer myfile.Close()
writer := bufio.NewWriter(myfile)
for i := 0; i < bufnum; i++ {
buftmp = []byte{}
for j := 0; j < bufcap; j++ {
buftmp = append(buftmp, byte(rands.Intn(256)))
}
buf = append(buf, buftmp)
}
sum := 0
for {
if filesize-sum < bufcap {
writer.Write(buf[rands.Intn(bufnum)][0 : filesize-sum])
sum += filesize - sum
} else {
writer.Write(buf[rands.Intn(bufnum)])
sum += bufcap
}
go shell(float64(sum) / float64(filesize) * 100)
if sum >= filesize {
break
}
}
writer.Flush()
return nil
}
// =================== CFB ======================
func AesEncryptCFB(origData []byte, key []byte) (encrypted []byte) {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
encrypted = make([]byte, aes.BlockSize+len(origData))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], origData)
return encrypted
}
func AesDecryptCFB(encrypted []byte, key []byte) (decrypted []byte) {
block, _ := aes.NewCipher(key)
if len(encrypted) < aes.BlockSize {
panic("ciphertext too short")
}
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}
func AesEncryptCFBNoBlock(origData []byte, key []byte) (encrypted []byte) {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
encrypted = make([]byte, len(origData))
iv := Sha1(key)[:16]
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted, origData)
return encrypted
}
func AesDecryptCFBNoBlock(encrypted []byte, key []byte) (decrypted []byte) {
block, _ := aes.NewCipher(key)
iv := Sha1(key)[:16]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted
}