package starainrt import ( "bufio" "crypto" "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" ) // StarCrypto 存储了单个校验方法的非编码元数据 type StarCrypto struct { Sha1 []byte Sha224 []byte Sha256 []byte Sha386 []byte Sha512 []byte Crc32 []byte Md5 []byte } // Base64Encode 输出格式化后的Base64字符串 func (starcpto StarCrypto) Base64Encode(bstr []byte) string { return base64.StdEncoding.EncodeToString(bstr) } // Base64Decode 输出解密前的Base64数据 func (starcpto StarCrypto) Base64Decode(str string) ([]byte, error) { return base64.StdEncoding.DecodeString(str) } // MD5 输出MD5校验值 func (starcpto *StarCrypto) MD5(bstr []byte) string { md5sum := md5.New() md5sum.Write(bstr) starcpto.Md5 = md5sum.Sum(nil) return hex.EncodeToString(starcpto.Md5) } // CRC32 输出CRC32校验值 func (starcpto *StarCrypto) CRC32(bstr []byte) string { crcsum := crc32.NewIEEE() crcsum.Write(bstr) starcpto.Crc32 = crcsum.Sum(nil) return hex.EncodeToString(starcpto.Crc32) } // SHA512 输出SHA512校验值 func (starcpto *StarCrypto) SHA512(bstr []byte) string { shasum := sha512.New() shasum.Write(bstr) starcpto.Sha512 = shasum.Sum(nil) return hex.EncodeToString(starcpto.Sha512) } // SHA256 输出SHA256校验值 func (starcpto *StarCrypto) SHA256(bstr []byte) string { shasum := sha256.New() shasum.Write(bstr) starcpto.Sha256 = shasum.Sum(nil) return hex.EncodeToString(starcpto.Sha256) } // SHA1 输出SHA1校验值 func (starcpto *StarCrypto) SHA1(bstr []byte) string { shasum := sha1.New() shasum.Write(bstr) starcpto.Sha1 = shasum.Sum(nil) return hex.EncodeToString(starcpto.Sha1) } // SumAll 可以对同一数据进行多种校验 func (starcpto StarCrypto) SumAll(data []byte, method []string) (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"} } 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] = hex.EncodeToString(v.Sum(nil)) } if iscrc { result["crc32"] = hex.EncodeToString(crcsum.Sum(nil)) } return result, nil } // FileSum 输出文件内容校验值,method为单个校验方法,小写 //例:FileSum("./test.txt","md5",shell(pect float64){fmt.Sprintf("已完成 %f\r",pect)}) func (starcpto StarCrypto) FileSum(filepath, method string, shell func(float64)) (string, error) { var sum hash.Hash var sum32 hash.Hash32 var issum32 bool var result string if !Exists(filepath) { return "", errors.New("file not exists") } 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 (starcpto StarCrypto) 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"} } if !Exists(filepath) { return result, errors.New("file not exists") } 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 (starcpto StarCrypto) Attach(src, dst, output string) error { if !Exists(src) { return errors.New("source file not exists") } if !Exists(dst) { return errors.New("dst file not exists") } 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 (starcpto StarCrypto) Detach(src string, bytenum int, dst1, dst2 string) error { if !Exists(src) { return errors.New("source file not exists") } 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 (starcpto StarCrypto) Base64EncodeFile(src, dst string, shell func(float64)) error { if !Exists(src) { return errors.New("source file not exists") } 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 (starcpto StarCrypto) Base64DecodeFile(src, dst string, shell func(float64)) error { if !Exists(src) { return errors.New("source file not exists") } 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 (starcpto StarCrypto) SplitFile(src, dst string, num int, bynum bool, shell func(float64)) error { if !Exists(src) { return errors.New("source file not exists") } 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 (starcpto StarCrypto) 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 := starcpto.VicqueEncodeV1(buf[0:n], pwd) fpdst.Write(data) } return nil } // VicqueDecodeV1File best func (starcpto StarCrypto) 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 := starcpto.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 }