From d6fb0b8c7f6244d6177218f1d88da36e60e96262 Mon Sep 17 00:00:00 2001 From: starainrt Date: Fri, 22 Apr 2022 16:53:40 +0800 Subject: [PATCH] add rsaencode by private key and rsadecode by publickey functions --- basehash.go | 368 ++++++++++++++++++++++++++++++++++++ crypt_test.go | 25 +++ crypto.go | 513 -------------------------------------------------- rsa.go | 271 ++++++++++++++++++++++++++ 4 files changed, 664 insertions(+), 513 deletions(-) create mode 100644 basehash.go create mode 100644 crypt_test.go create mode 100644 rsa.go diff --git a/basehash.go b/basehash.go new file mode 100644 index 0000000..a10f168 --- /dev/null +++ b/basehash.go @@ -0,0 +1,368 @@ +package starcrypto + +import ( + "encoding/ascii85" + "encoding/base64" + "errors" + "io" + "os" +) + +var ( + // ErrLength is returned from the Decode* methods if the input has an + // impossible length. + ErrLength = errors.New("base128: invalid length base128 string") + // ErrBit is returned from the Decode* methods if the input has a byte with + // the high-bit set (e.g. 0x80). This will never be the case for strings + // produced from the Encode* methods in this package. + ErrBit = errors.New("base128: high bit set in base128 string") +) + +// Encoding table holds all the characters for base91 encoding +var enctab = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~'") + +// Decoding table maps all the characters back to their integer values +var dectab = map[byte]byte{ + 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, + 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, + 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, + 'Y': 24, 'Z': 25, 'a': 26, 'b': 27, 'c': 28, 'd': 29, 'e': 30, 'f': 31, + 'g': 32, 'h': 33, 'i': 34, 'j': 35, 'k': 36, 'l': 37, 'm': 38, 'n': 39, + 'o': 40, 'p': 41, 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 'v': 47, + 'w': 48, 'x': 49, 'y': 50, 'z': 51, '0': 52, '1': 53, '2': 54, '3': 55, + '4': 56, '5': 57, '6': 58, '7': 59, '8': 60, '9': 61, '!': 62, '#': 63, + '$': 64, '%': 65, '&': 66, '(': 67, ')': 68, '*': 69, '+': 70, ',': 71, + '.': 72, '/': 73, ':': 74, ';': 75, '<': 76, '=': 77, '>': 78, '?': 79, + '@': 80, '[': 81, ']': 82, '^': 83, '_': 84, '`': 85, '{': 86, '|': 87, + '}': 88, '~': 89, '\'': 90, +} + +// Base91EncodeToString encodes the given byte array and returns a string +func Base91EncodeToString(d []byte) string { + return string(Base91Encode(d)) +} + +// Base91Encode returns the base91 encoded string +func Base91Encode(d []byte) []byte { + var n, b uint + var o []byte + + for i := 0; i < len(d); i++ { + b |= uint(d[i]) << n + n += 8 + if n > 13 { + v := b & 8191 + if v > 88 { + b >>= 13 + n -= 13 + } else { + v = b & 16383 + b >>= 14 + n -= 14 + } + o = append(o, enctab[v%91], enctab[v/91]) + } + } + if n > 0 { + o = append(o, enctab[b%91]) + if n > 7 || b > 90 { + o = append(o, enctab[b/91]) + } + } + return o +} + +// Base91DecodeToString decodes a given byte array are returns a string +func Base91DecodeString(d string) []byte { + return Base91Decode([]byte(d)) +} + +// Base91Decode decodes a base91 encoded string and returns the result +func Base91Decode(d []byte) []byte { + var b, n uint + var o []byte + v := -1 + + for i := 0; i < len(d); i++ { + c, ok := dectab[d[i]] + if !ok { + continue + } + if v < 0 { + v = int(c) + } else { + v += int(c) * 91 + b |= uint(v) << n + if v&8191 > 88 { + n += 13 + } else { + n += 14 + } + o = append(o, byte(b&255)) + b >>= 8 + n -= 8 + for n > 7 { + o = append(o, byte(b&255)) + b >>= 8 + n -= 8 + } + v = -1 + } + } + if v+1 > 0 { + o = append(o, byte((b|uint(v)<>whichByte)) + bufByte = (v&(1< 1 { + dst = append(dst, bufByte|(v>>(8-whichByte))) + } + bufByte = v << whichByte + if whichByte == 8 { + whichByte = 0 + } + whichByte++ + } + return len(dst), nil +} + +// Base128DecodeString returns the bytes represented by the base128 string s. +func Base128DecodeString(s string) ([]byte, error) { + src := []byte(s) + dst := make([]byte, Base128DecodedLen(len(src))) + if _, err := Base128Decode(dst, src); err != nil { + return nil, err + } + return dst, nil +} + +// Base128DecodedLen returns the number of bytes `encLen` encoded bytes decodes to. +func Base128DecodedLen(encLen int) int { + return (encLen * 7 / 8) +} + +// Base128EncodedLen returns the number of bytes that `dataLen` bytes will encode to. +func Base128EncodedLen(dataLen int) int { + return (((dataLen * 8) + 6) / 7) +} + +// Base128EncodeToString returns the base128 encoding of src. +func Base128EncodeToString(src []byte) string { + dst := make([]byte, Base128EncodedLen(len(src))) + Base128Encode(dst, src) + return string(dst) +} + +// 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) +} + +// Base85Encode 输出格式化后的Base85字符串 +func Base85Encode(bstr []byte) string { + var rtn []byte + rtn = make([]byte, ascii85.MaxEncodedLen(len(bstr))) + ascii85.Encode(rtn, bstr) + return string(rtn) +} + +// Base85Decode 输出解密前的Base85数据 +func Base85Decode(str string) ([]byte, error) { + var rtn []byte + rtn = make([]byte, len(str)) + _, _, err := ascii85.Decode(rtn, []byte(str), true) + return rtn, err +} + +// Base85EncodeFile 用base85方法编码src文件到dst文件中去,shell传入当前进度 +func Base85EncodeFile(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()) + var sum int64 + fpdst, err := os.Create(dst) + if err != nil { + return err + } + defer fpdst.Close() + b85 := ascii85.NewEncoder(fpdst) + defer b85.Close() + for { + buf := make([]byte, 1024000) + n, err := fpsrc.Read(buf) + if err != nil { + if err == io.EOF { + break + } + return err + } + sum += int64(n) + go shell(float64(sum) / filebig * 100) + b85.Write(buf[0:n]) + } + return nil +} + +// Base85DecodeFile 用base85方法解码src文件到dst文件中去,shell传入当前进度 +func Base85DecodeFile(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()) + var sum int64 + defer fpsrc.Close() + fpdst, err := os.Create(dst) + if err != nil { + return err + } + defer fpdst.Close() + b85 := ascii85.NewDecoder(fpsrc) + for { + buf := make([]byte, 1280000) + n, err := b85.Read(buf) + if err != nil { + if err == io.EOF { + break + } + return err + } + sum += int64(n) + per := float64(sum) / filebig * 100 / 4.0 * 5.0 + if per >= 100 { + per = 100 + } + go shell(per) + fpdst.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()) + var sum int64 = 0 + fpdst, err := os.Create(dst) + if err != nil { + return err + } + defer fpdst.Close() + b64 := base64.NewEncoder(base64.StdEncoding, fpdst) + defer b64.Close() + for { + buf := make([]byte, 1048575) + n, err := fpsrc.Read(buf) + if err != nil { + if err == io.EOF { + break + } + return err + } + sum += int64(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()) + var sum int64 = 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 += int64(n) + per := float64(sum) / filebig * 100 / 3.0 * 4.0 + if per >= 100 { + per = 100 + } + go shell(per) + fpdst.Write(buf[0:n]) + } + return nil +} diff --git a/crypt_test.go b/crypt_test.go new file mode 100644 index 0000000..1c360b0 --- /dev/null +++ b/crypt_test.go @@ -0,0 +1,25 @@ +package starcrypto + +import ( + "fmt" + "testing" +) + +func TestRsaCrypt(t *testing.T) { + privKey, pubKey, err := GenerateKey(2048) + if err != nil { + panic(err) + } + data, err := RSAEncryptByPrivkey(privKey, []byte("hello world")) + if err != nil { + t.Fatal(err) + } + code, err := RSADecryptByPubkey(pubKey, data) + if err != nil { + t.Fatal(err) + } + fmt.Println(string(code)) + if string(code) != "hello world" { + t.Fail() + } +} diff --git a/crypto.go b/crypto.go index 92e60b0..7fb93c8 100644 --- a/crypto.go +++ b/crypto.go @@ -2,21 +2,15 @@ package starcrypto import ( "bufio" - "crypto" "crypto/aes" "crypto/cipher" "crypto/md5" "crypto/rand" - "crypto/rsa" "crypto/sha1" "crypto/sha256" "crypto/sha512" - "crypto/x509" - "encoding/ascii85" - "encoding/base64" "encoding/binary" "encoding/hex" - "encoding/pem" "errors" "fmt" "hash" @@ -30,229 +24,8 @@ import ( "strconv" "strings" "time" - - "golang.org/x/crypto/ssh" -) - -var ( - // ErrLength is returned from the Decode* methods if the input has an - // impossible length. - ErrLength = errors.New("base128: invalid length base128 string") - // ErrBit is returned from the Decode* methods if the input has a byte with - // the high-bit set (e.g. 0x80). This will never be the case for strings - // produced from the Encode* methods in this package. - ErrBit = errors.New("base128: high bit set in base128 string") ) -// Encoding table holds all the characters for base91 encoding -var enctab = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~'") - -// Decoding table maps all the characters back to their integer values -var dectab = map[byte]byte{ - 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, - 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, - 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, - 'Y': 24, 'Z': 25, 'a': 26, 'b': 27, 'c': 28, 'd': 29, 'e': 30, 'f': 31, - 'g': 32, 'h': 33, 'i': 34, 'j': 35, 'k': 36, 'l': 37, 'm': 38, 'n': 39, - 'o': 40, 'p': 41, 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 'v': 47, - 'w': 48, 'x': 49, 'y': 50, 'z': 51, '0': 52, '1': 53, '2': 54, '3': 55, - '4': 56, '5': 57, '6': 58, '7': 59, '8': 60, '9': 61, '!': 62, '#': 63, - '$': 64, '%': 65, '&': 66, '(': 67, ')': 68, '*': 69, '+': 70, ',': 71, - '.': 72, '/': 73, ':': 74, ';': 75, '<': 76, '=': 77, '>': 78, '?': 79, - '@': 80, '[': 81, ']': 82, '^': 83, '_': 84, '`': 85, '{': 86, '|': 87, - '}': 88, '~': 89, '\'': 90, -} - -// Base91EncodeToString encodes the given byte array and returns a string -func Base91EncodeToString(d []byte) string { - return string(Base91Encode(d)) -} - -// Base91Encode returns the base91 encoded string -func Base91Encode(d []byte) []byte { - var n, b uint - var o []byte - - for i := 0; i < len(d); i++ { - b |= uint(d[i]) << n - n += 8 - if n > 13 { - v := b & 8191 - if v > 88 { - b >>= 13 - n -= 13 - } else { - v = b & 16383 - b >>= 14 - n -= 14 - } - o = append(o, enctab[v%91], enctab[v/91]) - } - } - if n > 0 { - o = append(o, enctab[b%91]) - if n > 7 || b > 90 { - o = append(o, enctab[b/91]) - } - } - return o -} - -// Base91DecodeToString decodes a given byte array are returns a string -func Base91DecodeString(d string) []byte { - return Base91Decode([]byte(d)) -} - -// Base91Decode decodes a base91 encoded string and returns the result -func Base91Decode(d []byte) []byte { - var b, n uint - var o []byte - v := -1 - - for i := 0; i < len(d); i++ { - c, ok := dectab[d[i]] - if !ok { - continue - } - if v < 0 { - v = int(c) - } else { - v += int(c) * 91 - b |= uint(v) << n - if v&8191 > 88 { - n += 13 - } else { - n += 14 - } - o = append(o, byte(b&255)) - b >>= 8 - n -= 8 - for n > 7 { - o = append(o, byte(b&255)) - b >>= 8 - n -= 8 - } - v = -1 - } - } - if v+1 > 0 { - o = append(o, byte((b|uint(v)<>whichByte)) - bufByte = (v&(1< 1 { - dst = append(dst, bufByte|(v>>(8-whichByte))) - } - bufByte = v << whichByte - if whichByte == 8 { - whichByte = 0 - } - whichByte++ - } - return len(dst), nil -} - -// Base128DecodeString returns the bytes represented by the base128 string s. -func Base128DecodeString(s string) ([]byte, error) { - src := []byte(s) - dst := make([]byte, Base128DecodedLen(len(src))) - if _, err := Base128Decode(dst, src); err != nil { - return nil, err - } - return dst, nil -} - -// Base128DecodedLen returns the number of bytes `encLen` encoded bytes decodes to. -func Base128DecodedLen(encLen int) int { - return (encLen * 7 / 8) -} - -// Base128EncodedLen returns the number of bytes that `dataLen` bytes will encode to. -func Base128EncodedLen(dataLen int) int { - return (((dataLen * 8) + 6) / 7) -} - -// Base128EncodeToString returns the base128 encoding of src. -func Base128EncodeToString(src []byte) string { - dst := make([]byte, Base128EncodedLen(len(src))) - Base128Encode(dst, src) - return string(dst) -} - -// 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) -} - -// Base85Encode 输出格式化后的Base85字符串 -func Base85Encode(bstr []byte) string { - var rtn []byte - rtn = make([]byte, ascii85.MaxEncodedLen(len(bstr))) - ascii85.Encode(rtn, bstr) - return string(rtn) -} - -// Base85Decode 输出解密前的Base85数据 -func Base85Decode(str string) ([]byte, error) { - var rtn []byte - rtn = make([]byte, len(str)) - _, _, err := ascii85.Decode(rtn, []byte(str), true) - return rtn, err -} - func String(bstr []byte) string { return hex.EncodeToString(bstr) } @@ -334,58 +107,6 @@ 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) @@ -659,146 +380,6 @@ func Detach(src string, bytenum int, dst1, dst2 string) error { return nil } -// Base85EncodeFile 用base85方法编码src文件到dst文件中去,shell传入当前进度 -func Base85EncodeFile(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()) - var sum int64 - fpdst, err := os.Create(dst) - if err != nil { - return err - } - defer fpdst.Close() - b85 := ascii85.NewEncoder(fpdst) - defer b85.Close() - for { - buf := make([]byte, 1024000) - n, err := fpsrc.Read(buf) - if err != nil { - if err == io.EOF { - break - } - return err - } - sum += int64(n) - go shell(float64(sum) / filebig * 100) - b85.Write(buf[0:n]) - } - return nil -} - -// Base85DecodeFile 用base85方法解码src文件到dst文件中去,shell传入当前进度 -func Base85DecodeFile(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()) - var sum int64 - defer fpsrc.Close() - fpdst, err := os.Create(dst) - if err != nil { - return err - } - defer fpdst.Close() - b85 := ascii85.NewDecoder(fpsrc) - for { - buf := make([]byte, 1280000) - n, err := b85.Read(buf) - if err != nil { - if err == io.EOF { - break - } - return err - } - sum += int64(n) - per := float64(sum) / filebig * 100 / 4.0 * 5.0 - if per >= 100 { - per = 100 - } - go shell(per) - fpdst.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()) - var sum int64 = 0 - fpdst, err := os.Create(dst) - if err != nil { - return err - } - defer fpdst.Close() - b64 := base64.NewEncoder(base64.StdEncoding, fpdst) - defer b64.Close() - for { - buf := make([]byte, 1048575) - n, err := fpsrc.Read(buf) - if err != nil { - if err == io.EOF { - break - } - return err - } - sum += int64(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()) - var sum int64 = 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 += int64(n) - per := float64(sum) / filebig * 100 / 3.0 * 4.0 - if per >= 100 { - per = 100 - } - go shell(per) - fpdst.Write(buf[0:n]) - } - return nil -} - // SplitFile 把src文件按要求分割到dst中去,dst应传入带*号字符串 // 如果bynum=true 则把文件分割成num份 // 如果bynum=false 则把文件按num字节分成多份 @@ -904,100 +485,6 @@ func MergeFile(src, dst string, shell func(float64)) error { 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(msg, priKey []byte, password string, hashType crypto.Hash) ([]byte, error) { - var prikey *rsa.PrivateKey - var err error - var bytes []byte - blk, _ := pem.Decode(priKey) - 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) - } - hashMethod := hashType.New() - _, err = hashMethod.Write(msg) - if err != nil { - return nil, err - } - return rsa.SignPKCS1v15(rand.Reader, prikey, hashType, hashMethod.Sum(nil)) -} - -// RSAVerify RSA公钥签名验证 -func RSAVerify(data, msg, pubKey []byte, hashType crypto.Hash) error { - blk, _ := pem.Decode(pubKey) - if blk == nil { - return errors.New("public key error!") - } - pubkey, err := x509.ParsePKIXPublicKey(blk.Bytes) - if err != nil { - return err - } - hashMethod := hashType.New() - _, err = hashMethod.Write(msg) - if err != nil { - return err - } - return rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), hashType, hashMethod.Sum(nil), data) -} - // VicqueEncodeV1 Best! func VicqueEncodeV1(srcdata []byte, key string) []byte { var keys []int diff --git a/rsa.go b/rsa.go new file mode 100644 index 0000000..988ff47 --- /dev/null +++ b/rsa.go @@ -0,0 +1,271 @@ +package starcrypto + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + "golang.org/x/crypto/ssh" + "math/big" +) + +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 +} + +func DecodePrivateKey(private []byte, password string) (*rsa.PrivateKey, error) { + var prikey *rsa.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.ParsePKCS1PrivateKey(bytes) + if err != nil { + tmp, err := x509.ParsePKCS8PrivateKey(bytes) + if err != nil { + return nil, err + } + prikey = tmp.(*rsa.PrivateKey) + } + return prikey, err +} + +func DecodePublicKey(pubStr []byte) (*rsa.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.(*rsa.PublicKey), 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(bits int) (string, string, error) { + + pkey, pubkey, err := GenerateKey(bits) + 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 +} + +// RSAEncrypt RSA公钥加密 +func RSAEncrypt(pub *rsa.PublicKey, data []byte) ([]byte, error) { + return rsa.EncryptPKCS1v15(rand.Reader, pub, data) +} + +// RSADecrypt RSA私钥解密 +func RSADecrypt(prikey *rsa.PrivateKey, data []byte) ([]byte, error) { + return rsa.DecryptPKCS1v15(rand.Reader, prikey, data) +} + +// RSASign RSA私钥签名加密 +func RSASign(msg, priKey []byte, password string, hashType crypto.Hash) ([]byte, error) { + var prikey *rsa.PrivateKey + var err error + var bytes []byte + blk, _ := pem.Decode(priKey) + 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) + } + hashMethod := hashType.New() + _, err = hashMethod.Write(msg) + if err != nil { + return nil, err + } + return rsa.SignPKCS1v15(rand.Reader, prikey, hashType, hashMethod.Sum(nil)) +} + +// RSAVerify RSA公钥签名验证 +func RSAVerify(data, msg, pubKey []byte, hashType crypto.Hash) error { + blk, _ := pem.Decode(pubKey) + if blk == nil { + return errors.New("public key error!") + } + pubkey, err := x509.ParsePKIXPublicKey(blk.Bytes) + if err != nil { + return err + } + hashMethod := hashType.New() + _, err = hashMethod.Write(msg) + if err != nil { + return err + } + return rsa.VerifyPKCS1v15(pubkey.(*rsa.PublicKey), hashType, hashMethod.Sum(nil), data) +} + +// copy from crypt/rsa/pkcs1v5.go +var hashPrefixes = map[crypto.Hash][]byte{ + crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, + crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, + crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, + crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, + crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, + crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, + crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix. + crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, +} + +// copy from crypt/rsa/pkcs1v5.go +func encrypt(c *big.Int, pub *rsa.PublicKey, m *big.Int) *big.Int { + e := big.NewInt(int64(pub.E)) + c.Exp(m, e, pub.N) + return c +} + +// copy from crypt/rsa/pkcs1v5.go +func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { + // Special case: crypto.Hash(0) is used to indicate that the data is + // signed directly. + if hash == 0 { + return inLen, nil, nil + } + + hashLen = hash.Size() + if inLen != hashLen { + return 0, nil, errors.New("crypto/rsa: input must be hashed message") + } + prefix, ok := hashPrefixes[hash] + if !ok { + return 0, nil, errors.New("crypto/rsa: unsupported hash function") + } + return +} + +// copy from crypt/rsa/pkcs1v5.go +func leftPad(input []byte, size int) (out []byte) { + n := len(input) + if n > size { + n = size + } + out = make([]byte, size) + copy(out[len(out)-n:], input) + return +} +func unLeftPad(input []byte) (out []byte) { + n := len(input) + t := 2 + for i := 2; i < n; i++ { + if input[i] == 0xff { + t = t + 1 + } else { + if input[i] == input[0] { + t = t + int(input[1]) + } + break + } + } + out = make([]byte, n-t) + copy(out, input[t:]) + return +} + +// copy&modified from crypt/rsa/pkcs1v5.go +func publicDecrypt(pub *rsa.PublicKey, hash crypto.Hash, hashed []byte, sig []byte) (out []byte, err error) { + hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) + if err != nil { + return nil, err + } + + tLen := len(prefix) + hashLen + k := (pub.N.BitLen() + 7) / 8 + if k < tLen+11 { + return nil, fmt.Errorf("length illegal") + } + + c := new(big.Int).SetBytes(sig) + m := encrypt(new(big.Int), pub, c) + em := leftPad(m.Bytes(), k) + out = unLeftPad(em) + + err = nil + return +} + +func RSAEncryptByPrivkey(privt *rsa.PrivateKey, data []byte) ([]byte, error) { + signData, err := rsa.SignPKCS1v15(nil, privt, crypto.Hash(0), data) + if err != nil { + return nil, err + } + return signData, nil +} + +func RSADecryptByPubkey(pub *rsa.PublicKey, data []byte) ([]byte, error) { + decData, err := publicDecrypt(pub, crypto.Hash(0), nil, data) + if err != nil { + return nil, err + } + return decData, nil +}