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.
starainrt/crypto.go

830 lines
16 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 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"
)
type StarCrypto struct {
}
/*
输出格式化后的Base64字符串
*/
func (this StarCrypto) Base64Encode(bstr []byte) string {
return base64.StdEncoding.EncodeToString(bstr)
}
/*
输出解密前的Base64数据
*/
func (this StarCrypto) Base64Decode(str string) ([]byte, error) {
return base64.StdEncoding.DecodeString(str)
}
/*
输出MD5校验值
*/
func (this StarCrypto) MD5(bstr []byte) string {
md5sum := md5.New()
return hex.EncodeToString(md5sum.Sum(bstr))
}
/*
输出CRC32校验值
*/
func (this StarCrypto) CRC32(bstr []byte) string {
crcsum := crc32.NewIEEE()
return hex.EncodeToString(crcsum.Sum(bstr))
}
/*
输出SHA512校验值
*/
func (this StarCrypto) Sha512(bstr []byte) string {
shasum := sha512.New()
return hex.EncodeToString(shasum.Sum(bstr))
}
/*
输出SHA256校验值
*/
func (this StarCrypto) SHA256(bstr []byte) string {
shasum := sha256.New()
return hex.EncodeToString(shasum.Sum(bstr))
}
/*
输出SHA1校验值
*/
func (this StarCrypto) SHA1(bstr []byte) string {
shasum := sha1.New()
return hex.EncodeToString(shasum.Sum(bstr))
}
/*
多校验方法校验函数
*/
func (this 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
}
/*
输出文件内容校验值method为单个校验方法,小写
FileSum("./test.txt","md5",shell(pect float64){fmt.Sprintf("已完成 %f\r",pect)})
*/
func (this 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
}
/*
多校验方法校验文件函数
*/
func (this 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
}
func (this StarCrypto) Attach(src, dst, output string) error {
if !Exists(src) {
return errors.New("Source File Not Exists!")
}
if !Exists(dst) {
return errors.New("Dest 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
}
func (this 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
}
func (this 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
}
func (this 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
}
/*
如果bynum=true 则把文件分割成num份
如果bynum=false 则把文件按num字节分成多份
*/
func (this 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
}
func (this 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 = 0
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
}
func (this 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)
}
func (this StarCrypto) RSADecrypt(data, private []byte, password string) ([]byte, error) {
var prikey *rsa.PrivateKey
var err error
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
}
prikey, err = x509.ParsePKCS1PrivateKey(tmp)
if err != nil {
return []byte{}, err
}
} else {
prikey, err = x509.ParsePKCS1PrivateKey(blk.Bytes)
if err != nil {
return []byte{}, err
}
}
return rsa.DecryptPKCS1v15(rand.Reader, prikey, data)
}
func (this StarCrypto) RSASign(hash256, private []byte, password string) ([]byte, error) {
var prikey *rsa.PrivateKey
var err error
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
}
prikey, err = x509.ParsePKCS1PrivateKey(tmp)
if err != nil {
return []byte{}, err
}
} else {
prikey, err = x509.ParsePKCS1PrivateKey(blk.Bytes)
if err != nil {
return []byte{}, err
}
}
return rsa.SignPKCS1v15(rand.Reader, prikey, crypto.SHA256, hash256)
}
func (this StarCrypto) RSAVerify(data, hash256, public []byte) 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), crypto.SHA256, hash256, data)
}
func (this 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
}
func (this 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]
}
func (this 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 := this.VicqueEncodeV1(buf[0:n], pwd)
fpdst.Write(data)
}
return nil
}
func (this 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 := this.VicqueDecodeV1(buf[0:n], pwd)
fpdst.Write(data)
}
return nil
}
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(255)))
}
buf = append(buf, buftmp)
}
sum := 0
for {
if filesize-sum < bufcap {
writer.Write(buf[rands.Intn(bufnum-1)][0 : filesize-sum])
sum += filesize - sum
} else {
writer.Write(buf[rands.Intn(bufnum-1)])
sum += bufcap
}
go shell(float64(sum) / float64(filesize) * 100)
if sum >= filesize {
break
}
}
writer.Flush()
return nil
}