145 lines
2.9 KiB
Go
145 lines
2.9 KiB
Go
package shttp
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/hex"
|
|
"encoding/pem"
|
|
"fmt"
|
|
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
type RSA struct {
|
|
bits int
|
|
key *rsa.PrivateKey
|
|
Comment string
|
|
}
|
|
|
|
func (r *RSA) SetBits(b int) {
|
|
r.bits = b
|
|
}
|
|
|
|
func (r *RSA) New() (err error) {
|
|
if r.bits < 1024 || r.bits > 4096 {
|
|
r.bits = 2048
|
|
}
|
|
r.key, err = rsa.GenerateKey(rand.Reader, r.bits)
|
|
return
|
|
}
|
|
|
|
func (r *RSA) Key() *rsa.PrivateKey {
|
|
return r.key
|
|
}
|
|
|
|
func (r *RSA) PublicKey() string {
|
|
if r.key == nil {
|
|
return ""
|
|
}
|
|
return string(pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: x509.MarshalPKCS1PublicKey(&r.key.PublicKey)}))
|
|
}
|
|
|
|
func (r *RSA) PrivateKey() string {
|
|
if r.key == nil {
|
|
return ""
|
|
}
|
|
return string(pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(r.key)}))
|
|
}
|
|
|
|
func (r *RSA) EncryptByte(msg []byte) ([]byte, error) {
|
|
if r.key == nil {
|
|
return nil, fmt.Errorf("no key found")
|
|
}
|
|
b, err := rsa.EncryptOAEP(sha256.New(), rand.Reader, &r.key.PublicKey, msg, []byte(""))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return b, nil
|
|
}
|
|
|
|
func (r *RSA) Encrypt(msg string) (string, error) {
|
|
b, err := r.EncryptByte([]byte(msg))
|
|
return hex.EncodeToString(b), err
|
|
}
|
|
|
|
func (r *RSA) DecryptByte(msg []byte) ([]byte, error) {
|
|
if r.key == nil {
|
|
return nil, fmt.Errorf("no key found")
|
|
}
|
|
b, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, r.key, msg, []byte(""))
|
|
return b, err
|
|
}
|
|
|
|
func (r *RSA) Decrypt(cypher string) (string, error) {
|
|
block, err := hex.DecodeString(cypher)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
msg, err := r.DecryptByte(block)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(msg), nil
|
|
}
|
|
|
|
func (r *RSA) LoadPublic(pub string) error {
|
|
if r.key == nil {
|
|
r.key = &rsa.PrivateKey{}
|
|
}
|
|
parsed, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(pub))
|
|
if err != nil {
|
|
block, rest := pem.Decode([]byte(pub))
|
|
if block == nil || block.Type != "RSA PUBLIC KEY" {
|
|
return fmt.Errorf("ssh: no key found")
|
|
}
|
|
if len(rest) != 0 {
|
|
r.Comment = string(rest)
|
|
}
|
|
p, err := x509.ParsePKCS1PublicKey(block.Bytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r.key.PublicKey = *p
|
|
return nil
|
|
}
|
|
parsedCryptoKey := parsed.(ssh.CryptoPublicKey)
|
|
pubCrypto := parsedCryptoKey.CryptoPublicKey()
|
|
p := pubCrypto.(*rsa.PublicKey)
|
|
|
|
r.key.PublicKey = *p
|
|
r.Comment = comment
|
|
return nil
|
|
}
|
|
|
|
func (r *RSA) LoadPrivate(pri string) error {
|
|
var p *rsa.PrivateKey
|
|
var err error
|
|
opssh, err := ssh.ParseRawPrivateKey([]byte(pri))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p = opssh.(*rsa.PrivateKey)
|
|
if r.key != nil {
|
|
p.PublicKey = r.key.PublicKey
|
|
}
|
|
r.key = p
|
|
return nil
|
|
}
|
|
|
|
func (r *RSA) LoadPrivateWithPassphrase(pri, passphrase string) error {
|
|
var p *rsa.PrivateKey
|
|
var err error
|
|
opssh, err := ssh.ParseRawPrivateKeyWithPassphrase([]byte(pri), []byte(passphrase))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
p = opssh.(*rsa.PrivateKey)
|
|
if r.key != nil {
|
|
p.PublicKey = r.key.PublicKey
|
|
}
|
|
r.key = p
|
|
return nil
|
|
}
|