From 85958ee5df3be94dba36192a4425188273e60344 Mon Sep 17 00:00:00 2001 From: 兔子 Date: Mon, 20 Jul 2020 11:16:23 +0800 Subject: [PATCH] init --- crypto.go | 936 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 936 insertions(+) create mode 100644 crypto.go diff --git a/crypto.go b/crypto.go new file mode 100644 index 0000000..2d68c0d --- /dev/null +++ b/crypto.go @@ -0,0 +1,936 @@ +package starcrypto + +import ( + "bufio" + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/md5" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "crypto/x509" + "encoding/base64" + "encoding/binary" + "encoding/hex" + "encoding/pem" + "errors" + "fmt" + "hash" + "hash/crc32" + "io" + "io/ioutil" + rands "math/rand" + "os" + "path/filepath" + "regexp" + "strconv" + "strings" + "time" + + "golang.org/x/crypto/ssh" +) + +// Base64Encode 输出格式化后的Base64字符串 +func Base64Encode(bstr []byte) string { + return base64.StdEncoding.EncodeToString(bstr) +} + +// Base64Decode 输出解密前的Base64数据 +func Base64Decode(str string) ([]byte, error) { + return base64.StdEncoding.DecodeString(str) +} + +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)) +} + +func GenerateKey(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) { + private, err := rsa.GenerateKey(rand.Reader, bits) + if err != nil { + return nil, nil, err + } + return private, &private.PublicKey, nil + +} + +func EncodePrivateKey(private *rsa.PrivateKey) []byte { + return pem.EncodeToMemory(&pem.Block{ + Bytes: x509.MarshalPKCS1PrivateKey(private), + Type: "RSA PRIVATE KEY", + }) +} + +func EncodePublicKey(public *rsa.PublicKey) ([]byte, error) { + publicBytes, err := x509.MarshalPKIXPublicKey(public) + if err != nil { + return nil, err + } + return pem.EncodeToMemory(&pem.Block{ + Bytes: publicBytes, + Type: "PUBLIC KEY", + }), nil +} + +//EncodeSSHKey +func EncodeSSHKey(public *rsa.PublicKey) ([]byte, error) { + publicKey, err := ssh.NewPublicKey(public) + if err != nil { + return nil, err + } + return ssh.MarshalAuthorizedKey(publicKey), nil +} + +func MakeSSHKeyPair() (string, string, error) { + + pkey, pubkey, err := GenerateKey(2048) + if err != nil { + return "", "", err + } + + pub, err := EncodeSSHKey(pubkey) + if err != nil { + return "", "", err + } + + //glog.Info("privateKey=[%s]\n pubKey=[%s]",string(EncodePrivateKey(pkey)),string(pub)) + return string(EncodePrivateKey(pkey)), string(pub), nil +} + +// 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 +} + +// Base64EncodeFile 用base64方法编码src文件到dst文件中去,shell传入当前进度 +func Base64EncodeFile(src, dst 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()) + sum := 0 + fpdst, err := os.Create(dst) + if err != nil { + return err + } + defer fpdst.Close() + b64 := base64.NewEncoder(base64.StdEncoding, fpdst) + for { + buf := make([]byte, 1048575) + n, err := fpsrc.Read(buf) + if err != nil { + if err == io.EOF { + break + } + return err + } + sum += n + go shell(float64(sum) / filebig * 100) + b64.Write(buf[0:n]) + } + return nil +} + +// Base64DecodeFile 用base64方法解码src文件到dst文件中去,shell传入当前进度 +func Base64DecodeFile(src, dst 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()) + sum := 0 + defer fpsrc.Close() + fpdst, err := os.Create(dst) + if err != nil { + return err + } + defer fpdst.Close() + b64 := base64.NewDecoder(base64.StdEncoding, fpsrc) + for { + buf := make([]byte, 1048576) + n, err := b64.Read(buf) + if err != nil { + if err == io.EOF { + break + } + return err + } + sum += n + go shell(float64(sum) / filebig * 100) + fpdst.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 + } + sum := 0 + 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 += n + go shell(float64(sum) / filebig * 100) + fpdst.Write(buf[0:n]) + } + fpsrc.Close() + } + return nil +} + +// RSAEncrypt RSA公钥加密 +func RSAEncrypt(data, public []byte) ([]byte, error) { + blk, _ := pem.Decode(public) + if blk == nil { + return []byte{}, errors.New("public key error") + } + pubkey, err := x509.ParsePKIXPublicKey(blk.Bytes) + if err != nil { + return []byte{}, err + } + return rsa.EncryptPKCS1v15(rand.Reader, pubkey.(*rsa.PublicKey), data) +} + +// RSADecrypt RSA私钥解密 +func RSADecrypt(data, private []byte, password string) ([]byte, error) { + var prikey *rsa.PrivateKey + var err error + var bytes []byte + blk, _ := pem.Decode(private) + if blk == nil { + return []byte{}, errors.New("private key error!") + } + if password != "" { + tmp, err := x509.DecryptPEMBlock(blk, []byte(password)) + if err != nil { + return []byte{}, err + } + bytes = tmp + } else { + bytes = blk.Bytes + } + prikey, err = x509.ParsePKCS1PrivateKey(bytes) + if err != nil { + tmp, err := x509.ParsePKCS8PrivateKey(bytes) + if err != nil { + return []byte{}, err + } + prikey = tmp.(*rsa.PrivateKey) + } + return rsa.DecryptPKCS1v15(rand.Reader, prikey, data) +} + +// RSASign RSA私钥签名加密 +func RSASign(hashdata, private []byte, password string, hashtype crypto.Hash) ([]byte, error) { + var prikey *rsa.PrivateKey + var err error + var bytes []byte + blk, _ := pem.Decode(private) + if blk == nil { + return []byte{}, errors.New("private key error!") + } + if password != "" { + tmp, err := x509.DecryptPEMBlock(blk, []byte(password)) + if err != nil { + return []byte{}, err + } + bytes = tmp + } else { + bytes = blk.Bytes + } + prikey, err = x509.ParsePKCS1PrivateKey(bytes) + if err != nil { + tmp, err := x509.ParsePKCS8PrivateKey(bytes) + if err != nil { + return []byte{}, err + } + prikey = tmp.(*rsa.PrivateKey) + } + return rsa.SignPKCS1v15(rand.Reader, prikey, hashtype, hashdata) +} + +// RSAVerify RSA公钥签名验证 +func RSAVerify(data, hashdata, public []byte, hashtype crypto.Hash) error { + blk, _ := pem.Decode(public) + if blk == nil { + return errors.New("public key error!") + } + pubkey, err := x509.ParsePKIXPublicKey(blk.Bytes) + if err != nil { + return err + } + return rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), hashtype, hashdata, data) +} + +// 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()) + sum := 0 + 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 += 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()) + sum := 0 + 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 += 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 +}