update starcrypto

master v0.0.3
兔子 10 months ago
parent d6fb0b8c7f
commit 0a4c0a944b

122
aes.go

@ -0,0 +1,122 @@
package starcrypto
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io"
)
const (
PKCS5PADDING = "PKCS5"
)
func CustomEncryptAesCFB(origData []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
encrypted := make([]byte, aes.BlockSize+len(origData))
iv := encrypted[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return nil, err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted[aes.BlockSize:], origData)
return encrypted, nil
}
func CustomDecryptAesCFB(encrypted []byte, key []byte) ([]byte, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
if len(encrypted) < aes.BlockSize {
return nil, errors.New("ciphertext too short")
}
iv := encrypted[:aes.BlockSize]
encrypted = encrypted[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted, nil
}
func CustomEncryptAesCFBNoBlock(origData []byte, key []byte, iv []byte) ([]byte, error) {
if len(iv) != 16 {
return nil, errors.New("iv length must be 16")
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
encrypted := make([]byte, len(origData))
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(encrypted, origData)
return encrypted, err
}
func CustomDecryptAesCFBNoBlock(encrypted []byte, key []byte, iv []byte) ([]byte, error) {
if len(iv) != 16 {
return nil, errors.New("iv length must be 16")
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(encrypted, encrypted)
return encrypted, err
}
func EncryptAesCBC(data, key []byte, iv []byte, paddingType string) ([]byte, error) {
var content []byte
aesBlockEncrypter, err := aes.NewCipher(key)
switch paddingType {
case PKCS5PADDING:
content = PKCS5Padding(data, aesBlockEncrypter.BlockSize())
default:
return nil, errors.New("padding type not supported")
}
encrypted := make([]byte, len(content))
if err != nil {
return nil, err
}
aesEncrypter := cipher.NewCBCEncrypter(aesBlockEncrypter, iv)
aesEncrypter.CryptBlocks(encrypted, content)
return encrypted, nil
}
func PKCS5Padding(cipherText []byte, blockSize int) []byte {
padding := blockSize - len(cipherText)%blockSize
padText := bytes.Repeat([]byte{byte(padding)}, padding)
return append(cipherText, padText...)
}
func PKCS5Trimming(encrypt []byte) []byte {
padding := encrypt[len(encrypt)-1]
if len(encrypt)-int(padding) < 0 {
return nil
}
return encrypt[:len(encrypt)-int(padding)]
}
func DecryptAesCBC(src, key []byte, iv []byte, paddingType string) (data []byte, err error) {
decrypted := make([]byte, len(src))
var aesBlockDecrypter cipher.Block
aesBlockDecrypter, err = aes.NewCipher(key)
if err != nil {
println(err.Error())
return nil, err
}
aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, iv)
aesDecrypter.CryptBlocks(decrypted, src)
switch paddingType {
case PKCS5PADDING:
return PKCS5Trimming(decrypted), nil
default:
return nil, errors.New("padding type not supported")
}
}

@ -3,24 +3,38 @@ package starcrypto
import ( import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"hash/crc32"
) )
// CheckCRC32A calculates CRC32A (ITU I.363.5 algorithm, popularized by BZIP2) checksum. // CheckCRC32A calculates CRC32A (ITU I.363.5 algorithm, popularized by BZIP2) checksum.
// This function will produce the same results as following PHP code: // This function will produce the same results as following PHP code:
// hexdec(hash('crc32', $data)) //
// hexdec(hash('crc32', $data))
func CheckCRC32A(data []byte) uint32 { func CheckCRC32A(data []byte) uint32 {
b := digest(data) b := digest(data)
return binary.BigEndian.Uint32(b) return binary.BigEndian.Uint32(b)
} }
func Crc32Str(bstr []byte) string {
return String(Crc32(bstr))
}
// CRC32 输出CRC32校验值
func Crc32(bstr []byte) []byte {
crcsum := crc32.NewIEEE()
crcsum.Write(bstr)
return crcsum.Sum(nil)
}
func Crc32A(data []byte) []byte { func Crc32A(data []byte) []byte {
return digest(data) return digest(data)
} }
// Crc32AStr is a convenience function that outputs CRC32A (ITU I.363.5 algorithm, popularized by BZIP2) checksum as a hex string. // Crc32AStr is a convenience function that outputs CRC32A (ITU I.363.5 algorithm, popularized by BZIP2) checksum as a hex string.
// This function will produce the same results as following PHP code: // This function will produce the same results as following PHP code:
// hash('crc32', $data) //
// hash('crc32', $data)
func Crc32AStr(data []byte) string { func Crc32AStr(data []byte) string {
b := digest(data) b := digest(data)

@ -6,7 +6,7 @@ import (
) )
func TestRsaCrypt(t *testing.T) { func TestRsaCrypt(t *testing.T) {
privKey, pubKey, err := GenerateKey(2048) privKey, pubKey, err := GenerateRsaKey(2048)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -23,3 +23,12 @@ func TestRsaCrypt(t *testing.T) {
t.Fail() t.Fail()
} }
} }
func TestHmacSHA224(t *testing.T) {
key := []byte("hello world")
data := []byte("hello world")
code := HmacSHA224Str(key, data)
if "1414427f4b2889c3e86e637162c1add2bb888d1fc6c405d05fa5b66b" != code {
t.Fail()
}
}

@ -1,502 +1,28 @@
package starcrypto package starcrypto
import ( import (
"bufio"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand" "crypto/rand"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"errors"
"fmt"
"hash"
"hash/crc32"
"io" "io"
"io/ioutil"
rands "math/rand"
"os" "os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
) )
func String(bstr []byte) string { func String(bstr []byte) string {
return hex.EncodeToString(bstr) 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 { func VicqueEncodeV1(srcdata []byte, key string) []byte {
var keys []int var keys []int
var saku, piku uint8 var randCode1, randCode2 uint8
data := make([]byte, len(srcdata)) data := make([]byte, len(srcdata))
copy(data, srcdata) copy(data, srcdata)
binary.Read(rand.Reader, binary.LittleEndian, &saku) binary.Read(rand.Reader, binary.LittleEndian, &randCode1)
binary.Read(rand.Reader, binary.LittleEndian, &piku) binary.Read(rand.Reader, binary.LittleEndian, &randCode2)
keys = append(keys, len(key)+int(saku)) keys = append(keys, len(key)+int(randCode1))
lens := len(data) lens := len(data)
for _, v := range key { for _, v := range key {
keys = append(keys, int(byte(v))+int(saku)-int(piku)) keys = append(keys, int(byte(v))+int(randCode1)-int(randCode2))
} }
lenkey := len(keys) lenkey := len(keys)
for k, v := range data { for k, v := range data {
@ -529,22 +55,21 @@ func VicqueEncodeV1(srcdata []byte, key string) []byte {
data[k] = byte(t) data[k] = byte(t)
data[lens-1-k] = byte(nv) data[lens-1-k] = byte(nv)
} }
data = append(data, byte(saku), byte(piku)) data = append(data, byte(randCode1), byte(randCode2))
return data return data
} }
// VicqueDecodeV1 Best
func VicqueDecodeV1(srcdata []byte, key string) []byte { func VicqueDecodeV1(srcdata []byte, key string) []byte {
var keys []int var keys []int
var saku, piku int var randCode1, randCode2 int
data := make([]byte, len(srcdata)) data := make([]byte, len(srcdata))
copy(data, srcdata) copy(data, srcdata)
lens := len(data) lens := len(data)
saku = int(data[lens-2]) randCode1 = int(data[lens-2])
piku = int(data[lens-1]) randCode2 = int(data[lens-1])
keys = append(keys, len(key)+int(saku)) keys = append(keys, len(key)+int(randCode1))
for _, v := range key { for _, v := range key {
keys = append(keys, int(byte(v))+int(saku)-int(piku)) keys = append(keys, int(byte(v))+int(randCode1)-int(randCode2))
} }
lenkey := len(keys) lenkey := len(keys)
lens -= 2 lens -= 2
@ -581,7 +106,6 @@ func VicqueDecodeV1(srcdata []byte, key string) []byte {
return data[:lens] return data[:lens]
} }
// VicqueEncodeV1File best
func VicqueEncodeV1File(src, dst, pwd string, shell func(float64)) error { func VicqueEncodeV1File(src, dst, pwd string, shell func(float64)) error {
fpsrc, err := os.Open(src) fpsrc, err := os.Open(src)
if err != nil { if err != nil {
@ -614,7 +138,6 @@ func VicqueEncodeV1File(src, dst, pwd string, shell func(float64)) error {
return nil return nil
} }
// VicqueDecodeV1File best
func VicqueDecodeV1File(src, dst, pwd string, shell func(float64)) error { func VicqueDecodeV1File(src, dst, pwd string, shell func(float64)) error {
fpsrc, err := os.Open(src) fpsrc, err := os.Open(src)
if err != nil { if err != nil {
@ -646,92 +169,3 @@ func VicqueDecodeV1File(src, dst, pwd string, shell func(float64)) error {
} }
return nil 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
}

@ -0,0 +1,117 @@
package starcrypto
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/pem"
"errors"
"golang.org/x/crypto/ssh"
)
func GenerateEcdsaKey(pubkeyCurve elliptic.Curve) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) {
// 随机挑选基点,生成私钥
priv, err := ecdsa.GenerateKey(pubkeyCurve, rand.Reader)
if err != nil {
return nil, nil, err
}
return priv, &priv.PublicKey, nil
}
func EncodeEcdsaPrivateKey(private *ecdsa.PrivateKey, secret string) ([]byte, error) {
b, err := x509.MarshalECPrivateKey(private)
if err != nil {
return nil, err
}
if secret == "" {
return pem.EncodeToMemory(&pem.Block{
Bytes: b,
Type: "EC PRIVATE KEY",
}), err
}
chiper := x509.PEMCipherAES256
blk, err := x509.EncryptPEMBlock(rand.Reader, "EC PRIVATE KEY", b, []byte(secret), chiper)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(blk), err
}
func EncodeEcdsaPublicKey(public *ecdsa.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
}
func DecodeEcdsaPrivateKey(private []byte, password string) (*ecdsa.PrivateKey, error) {
var prikey *ecdsa.PrivateKey
var err error
var bytes []byte
blk, _ := pem.Decode(private)
if blk == nil {
return nil, errors.New("private key error")
}
if password != "" {
tmp, err := x509.DecryptPEMBlock(blk, []byte(password))
if err != nil {
return nil, err
}
bytes = tmp
} else {
bytes = blk.Bytes
}
prikey, err = x509.ParseECPrivateKey(bytes)
if err != nil {
tmp, err := x509.ParsePKCS8PrivateKey(bytes)
if err != nil {
return nil, err
}
prikey = tmp.(*ecdsa.PrivateKey)
}
return prikey, err
}
func DecodeEcdsaPublicKey(pubStr []byte) (*ecdsa.PublicKey, error) {
blk, _ := pem.Decode(pubStr)
if blk == nil {
return nil, errors.New("public key error")
}
pub, err := x509.ParsePKIXPublicKey(blk.Bytes)
if err != nil {
return nil, err
}
return pub.(*ecdsa.PublicKey), nil
}
func EncodeEcdsaSSHPublicKey(public *ecdsa.PublicKey) ([]byte, error) {
publicKey, err := ssh.NewPublicKey(public)
if err != nil {
return nil, err
}
return ssh.MarshalAuthorizedKey(publicKey), nil
}
func GenerateEcdsaSSHKeyPair(pubkeyCurve elliptic.Curve, secret string) (string, string, error) {
pkey, pubkey, err := GenerateEcdsaKey(pubkeyCurve)
if err != nil {
return "", "", err
}
pub, err := EncodeEcdsaSSHPublicKey(pubkey)
if err != nil {
return "", "", err
}
priv, err := EncodeEcdsaPrivateKey(pkey, secret)
if err != nil {
return "", "", err
}
return string(priv), string(pub), nil
}

@ -0,0 +1,246 @@
package starcrypto
import (
"bufio"
"errors"
"fmt"
"io"
"io/ioutil"
"math/rand"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
)
// 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
}
// 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
rand.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(rand.Intn(256)))
}
buf = append(buf, buftmp)
}
sum := 0
for {
if filesize-sum < bufcap {
writer.Write(buf[rand.Intn(bufnum)][0 : filesize-sum])
sum += filesize - sum
} else {
writer.Write(buf[rand.Intn(bufnum)])
sum += bufcap
}
go shell(float64(sum) / float64(filesize) * 100)
if sum >= filesize {
break
}
}
writer.Flush()
return nil
}

@ -2,4 +2,4 @@ module b612.me/starcrypto
go 1.16 go 1.16
require golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000 require golang.org/x/crypto v0.21.0

@ -1,11 +1,45 @@
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000 h1:SL+8VVnkqyshUSz5iNnXtrBQzvFF2SkROm6t5RczFAE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

@ -0,0 +1,204 @@
package starcrypto
import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"errors"
"hash"
"hash/crc32"
"io"
"os"
)
// 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
}

@ -0,0 +1,87 @@
package starcrypto
import (
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"golang.org/x/crypto/md4"
"golang.org/x/crypto/ripemd160"
"hash"
)
func chmac(message, key []byte, f func() hash.Hash) []byte {
h := hmac.New(f, []byte(key))
h.Write([]byte(message))
return h.Sum(nil)
}
func chmacStr(message, key []byte, f func() hash.Hash) string {
return hex.EncodeToString(chmac(message, key, f))
}
func HmacMd4(message, key []byte) []byte {
return chmac(message, key, md4.New)
}
func HmacMd4Str(message, key []byte) string {
return chmacStr(message, key, md4.New)
}
func HmacMd5(message, key []byte) []byte {
return chmac(message, key, md5.New)
}
func HmacMd5Str(message, key []byte) string {
return chmacStr(message, key, md5.New)
}
func HmacSHA1(message, key []byte) []byte {
return chmac(message, key, sha1.New)
}
func HmacSHA1Str(message, key []byte) string {
return chmacStr(message, key, sha1.New)
}
func HmacSHA256(message, key []byte) []byte {
return chmac(message, key, sha256.New)
}
func HmacSHA256Str(message, key []byte) string {
return chmacStr(message, key, sha256.New)
}
func HmacSHA384(message, key []byte) []byte {
return chmac(message, key, sha512.New384)
}
func HmacSHA384Str(message, key []byte) string {
return chmacStr(message, key, sha512.New384)
}
func HmacSHA512(message, key []byte) []byte {
return chmac(message, key, sha512.New)
}
func HmacSHA512Str(message, key []byte) string {
return chmacStr(message, key, sha512.New)
}
func HmacSHA224(message, key []byte) []byte {
return chmac(message, key, sha256.New224)
}
func HmacSHA224Str(message, key []byte) string {
return chmacStr(message, key, sha256.New224)
}
func HmacRipeMd160(message, key []byte) []byte {
return chmac(message, key, ripemd160.New)
}
func HmacRipeMd160Str(message, key []byte) string {
return chmacStr(message, key, ripemd160.New)
}

@ -0,0 +1,27 @@
package starcrypto
import (
"crypto/md5"
"golang.org/x/crypto/md4"
)
// 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))
}
func Md4(bstr []byte) []byte {
md4sum := md4.New()
md4sum.Write(bstr)
return md4sum.Sum(nil)
}
func Md4Str(bstr []byte) string {
return String(Md4(bstr))
}

@ -0,0 +1,15 @@
package starcrypto
import (
"golang.org/x/crypto/ripemd160"
)
func RipeMd160(bstr []byte) []byte {
ripe := ripemd160.New()
ripe.Write(bstr)
return ripe.Sum(nil)
}
func RipeMd160Str(bstr []byte) string {
return String(RipeMd160(bstr))
}

@ -12,7 +12,7 @@ import (
"math/big" "math/big"
) )
func GenerateKey(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) { func GenerateRsaKey(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
private, err := rsa.GenerateKey(rand.Reader, bits) private, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -21,14 +21,22 @@ func GenerateKey(bits int) (*rsa.PrivateKey, *rsa.PublicKey, error) {
} }
func EncodePrivateKey(private *rsa.PrivateKey) []byte { func EncodeRsaPrivateKey(private *rsa.PrivateKey, secret string) ([]byte, error) {
return pem.EncodeToMemory(&pem.Block{ if secret == "" {
Bytes: x509.MarshalPKCS1PrivateKey(private), return pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(private),
}) Type: "RSA PRIVATE KEY",
}), nil
}
chiper := x509.PEMCipherAES256
blk, err := x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", x509.MarshalPKCS1PrivateKey(private), []byte(secret), chiper)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(blk), err
} }
func EncodePublicKey(public *rsa.PublicKey) ([]byte, error) { func EncodeRsaPublicKey(public *rsa.PublicKey) ([]byte, error) {
publicBytes, err := x509.MarshalPKIXPublicKey(public) publicBytes, err := x509.MarshalPKIXPublicKey(public)
if err != nil { if err != nil {
return nil, err return nil, err
@ -39,7 +47,7 @@ func EncodePublicKey(public *rsa.PublicKey) ([]byte, error) {
}), nil }), nil
} }
func DecodePrivateKey(private []byte, password string) (*rsa.PrivateKey, error) { func DecodeRsaPrivateKey(private []byte, password string) (*rsa.PrivateKey, error) {
var prikey *rsa.PrivateKey var prikey *rsa.PrivateKey
var err error var err error
var bytes []byte var bytes []byte
@ -67,7 +75,7 @@ func DecodePrivateKey(private []byte, password string) (*rsa.PrivateKey, error)
return prikey, err return prikey, err
} }
func DecodePublicKey(pubStr []byte) (*rsa.PublicKey, error) { func DecodeRsaPublicKey(pubStr []byte) (*rsa.PublicKey, error) {
blk, _ := pem.Decode(pubStr) blk, _ := pem.Decode(pubStr)
if blk == nil { if blk == nil {
return nil, errors.New("public key error") return nil, errors.New("public key error")
@ -79,8 +87,7 @@ func DecodePublicKey(pubStr []byte) (*rsa.PublicKey, error) {
return pub.(*rsa.PublicKey), nil return pub.(*rsa.PublicKey), nil
} }
//EncodeSSHKey func EncodeRsaSSHPublicKey(public *rsa.PublicKey) ([]byte, error) {
func EncodeSSHKey(public *rsa.PublicKey) ([]byte, error) {
publicKey, err := ssh.NewPublicKey(public) publicKey, err := ssh.NewPublicKey(public)
if err != nil { if err != nil {
return nil, err return nil, err
@ -88,20 +95,22 @@ func EncodeSSHKey(public *rsa.PublicKey) ([]byte, error) {
return ssh.MarshalAuthorizedKey(publicKey), nil return ssh.MarshalAuthorizedKey(publicKey), nil
} }
func MakeSSHKeyPair(bits int) (string, string, error) { func GenerateRsaSSHKeyPair(bits int, secret string) (string, string, error) {
pkey, pubkey, err := GenerateRsaKey(bits)
pkey, pubkey, err := GenerateKey(bits)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
pub, err := EncodeSSHKey(pubkey) pub, err := EncodeRsaSSHPublicKey(pubkey)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
//glog.Info("privateKey=[%s]\n pubKey=[%s]",string(EncodePrivateKey(pkey)),string(pub)) priv, err := EncodeRsaPrivateKey(pkey, secret)
return string(EncodePrivateKey(pkey)), string(pub), nil if err != nil {
return "", "", err
}
return string(priv), string(pub), nil
} }
// RSAEncrypt RSA公钥加密 // RSAEncrypt RSA公钥加密

@ -0,0 +1,62 @@
package starcrypto
import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
)
// 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))
}

@ -0,0 +1,15 @@
package starcrypto
import (
"b612.me/starcrypto/sm3"
)
func SM3(bstr []byte) []byte {
sm3sum := sm3.New()
sm3sum.Write(bstr)
return sm3sum.Sum(nil)
}
func SM3Str(bstr []byte) string {
return String(SM3(bstr))
}

@ -0,0 +1,259 @@
/*
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sm3
import (
"encoding/binary"
"hash"
)
type SM3 struct {
digest [8]uint32 // digest represents the partial evaluation of V
length uint64 // length of the message
unhandleMsg []byte // uint8 //
}
func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z }
func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) }
func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z }
func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) }
func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) }
func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) }
func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return x<<(i%32) | x>>(32-i%32) }
func (sm3 *SM3) pad() []byte {
msg := sm3.unhandleMsg
msg = append(msg, 0x80) // Append '1'
blockSize := 64 // Append until the resulting message length (in bits) is congruent to 448 (mod 512)
for len(msg)%blockSize != 56 {
msg = append(msg, 0x00)
}
// append message length
msg = append(msg, uint8(sm3.length>>56&0xff))
msg = append(msg, uint8(sm3.length>>48&0xff))
msg = append(msg, uint8(sm3.length>>40&0xff))
msg = append(msg, uint8(sm3.length>>32&0xff))
msg = append(msg, uint8(sm3.length>>24&0xff))
msg = append(msg, uint8(sm3.length>>16&0xff))
msg = append(msg, uint8(sm3.length>>8&0xff))
msg = append(msg, uint8(sm3.length>>0&0xff))
if len(msg)%64 != 0 {
panic("------SM3 Pad: error msgLen =")
}
return msg
}
func (sm3 *SM3) update(msg []byte) {
var w [68]uint32
var w1 [64]uint32
a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
for len(msg) >= 64 {
for i := 0; i < 16; i++ {
w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
}
for i := 16; i < 68; i++ {
w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
}
for i := 0; i < 64; i++ {
w1[i] = w[i] ^ w[i+4]
}
A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
for i := 0; i < 16; i++ {
SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
SS2 := SS1 ^ sm3.leftRotate(A, 12)
TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
D = C
C = sm3.leftRotate(B, 9)
B = A
A = TT1
H = G
G = sm3.leftRotate(F, 19)
F = E
E = sm3.p0(TT2)
}
for i := 16; i < 64; i++ {
SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
SS2 := SS1 ^ sm3.leftRotate(A, 12)
TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
D = C
C = sm3.leftRotate(B, 9)
B = A
A = TT1
H = G
G = sm3.leftRotate(F, 19)
F = E
E = sm3.p0(TT2)
}
a ^= A
b ^= B
c ^= C
d ^= D
e ^= E
f ^= F
g ^= G
h ^= H
msg = msg[64:]
}
sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7] = a, b, c, d, e, f, g, h
}
func (sm3 *SM3) update2(msg []byte) [8]uint32 {
var w [68]uint32
var w1 [64]uint32
a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
for len(msg) >= 64 {
for i := 0; i < 16; i++ {
w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
}
for i := 16; i < 68; i++ {
w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
}
for i := 0; i < 64; i++ {
w1[i] = w[i] ^ w[i+4]
}
A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
for i := 0; i < 16; i++ {
SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
SS2 := SS1 ^ sm3.leftRotate(A, 12)
TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
D = C
C = sm3.leftRotate(B, 9)
B = A
A = TT1
H = G
G = sm3.leftRotate(F, 19)
F = E
E = sm3.p0(TT2)
}
for i := 16; i < 64; i++ {
SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
SS2 := SS1 ^ sm3.leftRotate(A, 12)
TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
D = C
C = sm3.leftRotate(B, 9)
B = A
A = TT1
H = G
G = sm3.leftRotate(F, 19)
F = E
E = sm3.p0(TT2)
}
a ^= A
b ^= B
c ^= C
d ^= D
e ^= E
f ^= F
g ^= G
h ^= H
msg = msg[64:]
}
var digest [8]uint32
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7] = a, b, c, d, e, f, g, h
return digest
}
// 创建哈希计算实例
func New() hash.Hash {
var sm3 SM3
sm3.Reset()
return &sm3
}
// BlockSize returns the hash's underlying block size.
// The Write method must be able to accept any amount
// of data, but it may operate more efficiently if all writes
// are a multiple of the block size.
func (sm3 *SM3) BlockSize() int { return 64 }
// Size returns the number of bytes Sum will return.
func (sm3 *SM3) Size() int { return 32 }
// Reset clears the internal state by zeroing bytes in the state buffer.
// This can be skipped for a newly-created hash state; the default zero-allocated state is correct.
func (sm3 *SM3) Reset() {
// Reset digest
sm3.digest[0] = 0x7380166f
sm3.digest[1] = 0x4914b2b9
sm3.digest[2] = 0x172442d7
sm3.digest[3] = 0xda8a0600
sm3.digest[4] = 0xa96f30bc
sm3.digest[5] = 0x163138aa
sm3.digest[6] = 0xe38dee4d
sm3.digest[7] = 0xb0fb0e4e
sm3.length = 0 // Reset numberic states
sm3.unhandleMsg = []byte{}
}
// Write (via the embedded io.Writer interface) adds more data to the running hash.
// It never returns an error.
func (sm3 *SM3) Write(p []byte) (int, error) {
toWrite := len(p)
sm3.length += uint64(len(p) * 8)
msg := append(sm3.unhandleMsg, p...)
nblocks := len(msg) / sm3.BlockSize()
sm3.update(msg)
// Update unhandleMsg
sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():]
return toWrite, nil
}
// 返回SM3哈希算法摘要值
// Sum appends the current hash to b and returns the resulting slice.
// It does not change the underlying hash state.
func (sm3 *SM3) Sum(in []byte) []byte {
_, _ = sm3.Write(in)
msg := sm3.pad()
//Finalize
digest := sm3.update2(msg)
// save hash to in
needed := sm3.Size()
if cap(in)-len(in) < needed {
newIn := make([]byte, len(in), len(in)+needed)
copy(newIn, in)
in = newIn
}
out := in[len(in) : len(in)+needed]
for i := 0; i < 8; i++ {
binary.BigEndian.PutUint32(out[i*4:], digest[i])
}
return out
}
func Sm3Sum(data []byte) []byte {
var sm3 SM3
sm3.Reset()
_, _ = sm3.Write(data)
return sm3.Sum(nil)
}

@ -0,0 +1,64 @@
/*
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sm3
import (
"fmt"
"io/ioutil"
"os"
"testing"
)
func byteToString(b []byte) string {
ret := ""
for i := 0; i < len(b); i++ {
ret += fmt.Sprintf("%02x", b[i])
}
fmt.Println("ret = ", ret)
return ret
}
func TestSm3(t *testing.T) {
msg := []byte("test")
err := ioutil.WriteFile("ifile", msg, os.FileMode(0644)) // 生成测试文件
if err != nil {
t.Fatal(err)
}
msg, err = ioutil.ReadFile("ifile")
if err != nil {
t.Fatal(err)
}
hw := New()
hw.Write(msg)
hash := hw.Sum(nil)
fmt.Println(hash)
fmt.Printf("hash = %d\n", len(hash))
fmt.Printf("%s\n", byteToString(hash))
hash1 := Sm3Sum(msg)
fmt.Println(hash1)
fmt.Printf("%s\n", byteToString(hash1))
}
func BenchmarkSm3(t *testing.B) {
t.ReportAllocs()
msg := []byte("test")
hw := New()
for i := 0; i < t.N; i++ {
hw.Sum(nil)
Sm3Sum(msg)
}
}
Loading…
Cancel
Save