diff --git a/acme/acme.go b/acme/acme.go new file mode 100644 index 0000000..08f7d7e --- /dev/null +++ b/acme/acme.go @@ -0,0 +1,160 @@ +package acme + +import ( + "b612.me/starcrypto" + "b612.me/starlog" + "fmt" + "github.com/go-acme/lego/v4/certcrypto" + "github.com/go-acme/lego/v4/challenge/http01" + "github.com/go-acme/lego/v4/challenge/tlsalpn01" + "github.com/go-acme/lego/v4/lego" + "github.com/go-acme/lego/v4/providers/dns/acmedns" + "github.com/go-acme/lego/v4/providers/dns/alidns" + "github.com/go-acme/lego/v4/providers/dns/azuredns" + "github.com/go-acme/lego/v4/providers/dns/cloudflare" + "github.com/go-acme/lego/v4/providers/dns/tencentcloud" + "os" +) + +func run(a Acme) error { + + // Create a user. New accounts need an email and private key to start. + if a.KeyPath != "" { + data, err := os.ReadFile(a.KeyPath) + if err != nil { + return fmt.Errorf("read key file error:%w", err) + } + a.key, err = starcrypto.DecodePrivateKey(data, "") + if err != nil { + return fmt.Errorf("decode key error:%w", err) + } + } + for _, req := range a.CertReqs { + starlog.Info("request cert for %v", req.Domains) + config := lego.NewConfig(&a) + // This CA URL is configured for a local dev instance of Boulder running in Docker in a VM. + config.CADirURL = "https://acme-v02.api.letsencrypt.org/directory" + switch req.KeyType { + case "rsa2048": + config.Certificate.KeyType = certcrypto.RSA2048 + case "rsa4096": + config.Certificate.KeyType = certcrypto.RSA4096 + case "rsa8192": + config.Certificate.KeyType = certcrypto.RSA8192 + case "ec256": + config.Certificate.KeyType = certcrypto.EC256 + case "ec384": + config.Certificate.KeyType = certcrypto.EC384 + default: + config.Certificate.KeyType = certcrypto.EC384 + } + + // A client facilitates communication with the CA server. + client, err := lego.NewClient(config) + if err != nil { + starlog.Errorf("new client error:%v", err) + return fmt.Errorf("new client error:%w", err) + } + p := a.DnsPrivders[req.PrivderName] + switch p.Type { + case "http": + err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", p.KeyID)) + if err != nil { + starlog.Errorf("set http provider error:%v", err) + return fmt.Errorf("set http provider error:%w", err) + } + err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", p.KeySecret)) + if err != nil { + starlog.Errorf("set tlsalpn provider error:%v", err) + return fmt.Errorf("set tlsalpn provider error:%w", err) + } + case "tencent": + cfg := tencentcloud.NewDefaultConfig() + cfg.SecretID = p.KeyID + cfg.SecretKey = p.KeySecret + dnsSet, err := tencentcloud.NewDNSProviderConfig(cfg) + if err != nil { + starlog.Errorf("new dns provider error:%v", err) + return fmt.Errorf("new dns provider error:%w", err) + } + err = client.Challenge.SetDNS01Provider(dnsSet) + if err != nil { + starlog.Errorf("set dns provider error:%v", err) + return fmt.Errorf("set dns provider error:%w", err) + } + case "cloudflare": + cfg := cloudflare.NewDefaultConfig() + cfg.AuthKey = p.KeySecret + cfg.AuthEmail = p.KeyID + dnsSet, err := cloudflare.NewDNSProviderConfig(cfg) + if err != nil { + starlog.Errorf("new dns provider error:%v", err) + return fmt.Errorf("new dns provider error:%w", err) + } + err = client.Challenge.SetDNS01Provider(dnsSet) + if err != nil { + starlog.Errorf("set dns provider error:%v", err) + return fmt.Errorf("set dns provider error:%w", err) + } + case "alidns": + cfg := alidns.NewDefaultConfig() + cfg.APIKey = p.KeyID + cfg.SecretKey = p.KeySecret + dnsSet, err := alidns.NewDNSProviderConfig(cfg) + if err != nil { + starlog.Errorf("new dns provider error:%v", err) + return fmt.Errorf("new dns provider error:%w", err) + } + err = client.Challenge.SetDNS01Provider(dnsSet) + if err != nil { + starlog.Errorf("set dns provider error:%v", err) + return fmt.Errorf("set dns provider error:%w", err) + } + case "azure": + cfg := azuredns.NewDefaultConfig() + cfg.ClientID = p.KeyID + cfg.ClientSecret = p.KeySecret + dnsSet, err := azuredns.NewDNSProviderConfig(cfg) + if err != nil { + starlog.Errorf("new dns provider error:%v", err) + return fmt.Errorf("new dns provider error:%w", err) + } + err = client.Challenge.SetDNS01Provider(dnsSet) + if err != nil { + starlog.Errorf("set dns provider error:%v", err) + return fmt.Errorf("set dns provider error:%w", err) + } + default: + cfg, _ := acmedns.NewDNSProvider() + err = client.Challenge.SetDNS01Provider(cfg) + if err != nil { + starlog.Errorf("set dns provider error:%v", err) + return fmt.Errorf("set dns provider error:%w", err) + } + } + + /* + // New users will need to register + reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) + if err != nil { + log.Fatal(err) + } + a.Registration = reg + + request := certificate.ObtainRequest{ + Domains: []string{"mydomain.com"}, + Bundle: true, + } + certificates, err := client.Certificate.Obtain(request) + if err != nil { + log.Fatal(err) + } + + // Each certificate comes back with the cert bytes, the bytes of the client's + // private key, and a certificate URL. SAVE THESE TO DISK. + fmt.Printf("%#v\n", certificates) + + */ + } + return nil +} diff --git a/acme/config.go b/acme/config.go new file mode 100644 index 0000000..8ac2755 --- /dev/null +++ b/acme/config.go @@ -0,0 +1,43 @@ +package acme + +import ( + "crypto" + "github.com/go-acme/lego/v4/registration" +) + +type DnsProvider struct { + Name string + Type string + KeyID string + KeySecret string +} + +type CertReq struct { + Domains []string + Type string + PrivderName string + KeyType string + SaveFolder string + SaveName string +} + +// You'll need a user or account type that implements acme.User +type Acme struct { + Email string + KeyPath string + SaveFolder string + CertReqs map[string]CertReq + DnsPrivders map[string]DnsProvider + Registration *registration.Resource + key crypto.PrivateKey +} + +func (u *Acme) GetEmail() string { + return u.Email +} +func (u Acme) GetRegistration() *registration.Resource { + return u.Registration +} +func (u *Acme) GetPrivateKey() crypto.PrivateKey { + return u.key +} diff --git a/cert/cert.go b/cert/cert.go index 27eed57..e757eab 100644 --- a/cert/cert.go +++ b/cert/cert.go @@ -13,12 +13,14 @@ import ( "encoding/pem" "errors" "fmt" + "golang.org/x/crypto/ssh" "os" "software.sslmate.com/src/go-pkcs12" "strings" ) func ParseCert(data []byte, pwd string) { + oriData := data { pems, err := pkcs12.ToPEM(data, pwd) if err == nil { @@ -349,6 +351,64 @@ func ParseCert(data []byte, pwd string) { starlog.Green("公钥长度:%d\n", n.Params().BitSize) starlog.Green("公钥公钥X:%d\n", n.X) starlog.Green("公钥公钥Y:%d\n", n.Y) + case "OPENSSH PRIVATE KEY": + starlog.Infof("这是一个OpenSSH私钥文件\n") + var priv interface{} + var err error + if pwd == "" { + priv, err = ssh.ParseRawPrivateKey(oriData) + if err != nil { + starlog.Errorf("解析OPENSSH私钥错误:%s\n", err) + continue + } + } else { + priv, err = ssh.ParseRawPrivateKeyWithPassphrase(oriData, []byte(pwd)) + if err != nil { + starlog.Errorf("解析OPENSSH私钥错误:%s\n", err) + continue + } + } + switch n := priv.(type) { + case *rsa.PrivateKey: + starlog.Green("这是一个RSA私钥\n") + starlog.Green("私钥位数:%d\n", n.Size()) + starlog.Green("私钥长度:%d\n", n.N.BitLen()) + starlog.Green("私钥指数:%d\n", n.E) + starlog.Green("私钥系数:%d\n", n.D) + starlog.Green("私钥质数p:%d\n", n.Primes[0]) + starlog.Green("私钥质数q:%d\n", n.Primes[1]) + starlog.Green("私钥系数dP:%d\n", n.Precomputed.Dp) + starlog.Green("私钥系数dQ:%d\n", n.Precomputed.Dq) + starlog.Green("私钥系数qInv:%d\n", n.Precomputed.Qinv) + case *ecdsa.PrivateKey: + starlog.Green("这是一个ECDSA私钥\n") + starlog.Green("私钥位数:%d\n", n.Curve.Params().BitSize) + starlog.Green("私钥曲线:%s\n", n.Curve.Params().Name) + starlog.Green("私钥长度:%d\n", n.Params().BitSize) + starlog.Green("私钥系数:%d\n", n.D) + starlog.Green("私钥公钥X:%d\n", n.PublicKey.X) + starlog.Green("私钥公钥Y:%d\n", n.PublicKey.Y) + case *dsa.PrivateKey: + starlog.Green("这是一个DSA私钥\n") + starlog.Green("私钥系数:%d\n", n.X) + starlog.Green("私钥公钥Y:%d\n", n.Y) + case *ed25519.PrivateKey: + starlog.Green("这是一个ED25519私钥\n") + case *ecdh.PrivateKey: + starlog.Green("这是一个ECDH私钥\n") + default: + starlog.Green("未知私钥类型\n") + } + continue + case "OPENSSH PUBLIC KEY": + starlog.Infof("这是一个OPENSSH公钥文件\n") + pub, err := ssh.ParsePublicKey(block.Bytes) + if err != nil { + starlog.Errorf("解析公钥错误:%s\n", err) + continue + } + starlog.Green("公钥算法:%s\n", pub.Type()) + continue default: starlog.Infof("未知证书文件类型\n") } @@ -427,6 +487,7 @@ func extKeyUsageToStrings(extKeyUsages []x509.ExtKeyUsage) string { } func GetCert(data []byte, pwd string) ([]any, []x509.Certificate, error) { + var oriData = data var common []any var certs []x509.Certificate { @@ -581,7 +642,6 @@ func GetCert(data []byte, pwd string) ([]any, []x509.Certificate, error) { } common = append(common, priv) continue - case "PUBLIC KEY": starlog.Infof("这是一个公钥文件\n") pub, err := x509.ParsePKIXPublicKey(block.Bytes) @@ -666,13 +726,53 @@ func GetCert(data []byte, pwd string) ([]any, []x509.Certificate, error) { starlog.Green("公钥公钥X:%d\n", n.X) starlog.Green("公钥公钥Y:%d\n", n.Y) common = append(common, n) + case "OPENSSH PRIVATE KEY": + starlog.Infof("这是一个OpenSSH私钥文件\n") + var priv interface{} + var err error + if pwd == "" { + priv, err = ssh.ParseRawPrivateKey(oriData) + if err != nil { + starlog.Errorf("解析私钥错误:%s\n", err) + continue + } + } else { + priv, err = ssh.ParseRawPrivateKeyWithPassphrase(oriData, []byte(pwd)) + if err != nil { + starlog.Errorf("解析私钥错误:%s\n", err) + continue + } + } + switch n := priv.(type) { + case *rsa.PrivateKey: + common = append(common, n) + starlog.Green("这是一个RSA私钥\n") + starlog.Green("私钥位数:%d\n", n.Size()) + starlog.Green("私钥长度:%d\n", n.N.BitLen()) + case *ecdsa.PrivateKey: + common = append(common, n) + starlog.Green("这是一个ECDSA私钥\n") + starlog.Green("私钥位数:%d\n", n.Curve.Params().BitSize) + case *dsa.PrivateKey: + common = append(common, n) + starlog.Green("这是一个DSA私钥\n") + case *ed25519.PrivateKey: + common = append(common, n) + starlog.Green("这是一个ED25519私钥\n") + case *ecdh.PrivateKey: + common = append(common, n) + starlog.Green("这是一个ECDH私钥\n") + default: + starlog.Green("未知私钥类型\n") + } + continue default: starlog.Infof("未知证书文件类型\n") } } } -func Pkcs8(data []byte, pwd string, originName string, outpath string) error { +func Pkcs8(data []byte, pwd, newPwd string, originName string, outpath string) error { keys, _, err := GetCert(data, pwd) if err != nil { return err @@ -687,7 +787,13 @@ func Pkcs8(data []byte, pwd string, originName string, outpath string) error { if err != nil { return err } - err = os.WriteFile(outpath+"/"+originName+".pkcs8", pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: data}), 0644) + var block *pem.Block + if newPwd != "" { + block, err = x509.EncryptPEMBlock(rand.Reader, "PRIVATE KEY", data, []byte(newPwd), x509.PEMCipherAES256) + } else { + block = &pem.Block{Type: "PRIVATE KEY", Bytes: data} + } + err = os.WriteFile(outpath+"/"+originName+".pkcs8", pem.EncodeToMemory(block), 0644) if err != nil { return err } else { @@ -709,7 +815,7 @@ func Pkcs8(data []byte, pwd string, originName string, outpath string) error { return nil } -func Pkcs1(data []byte, pwd string, originName string, outpath string) error { +func Pkcs1(data []byte, pwd, newPwd string, originName string, outpath string) error { keys, _, err := GetCert(data, pwd) if err != nil { return err @@ -724,7 +830,13 @@ func Pkcs1(data []byte, pwd string, originName string, outpath string) error { if err != nil { return err } - err = os.WriteFile(fmt.Sprintf("%s/%s_%v.pkcs1", outpath, originName, idx), pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: data}), 0644) + var block *pem.Block + if newPwd != "" { + block, err = x509.EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", data, []byte(newPwd), x509.PEMCipherAES256) + } else { + block = &pem.Block{Type: "RSA PRIVATE KEY", Bytes: data} + } + err = os.WriteFile(fmt.Sprintf("%s/%s_%v.pkcs1", outpath, originName, idx), pem.EncodeToMemory(block), 0644) if err != nil { return err } else { @@ -842,3 +954,46 @@ func Tran(data []byte, pwd string, originName string, outpath string) error { } return nil } + +func Openssh(data []byte, pwd, newPwd string, originName string, outpath string) error { + keys, _, err := GetCert(data, pwd) + if err != nil { + return err + } + for _, v := range keys { + if v == nil { + continue + } + var block *pem.Block + switch n := v.(type) { + case *ecdsa.PrivateKey, *rsa.PrivateKey, *dsa.PrivateKey, *ed25519.PrivateKey, *ecdh.PrivateKey: + if newPwd != "" { + block, err = ssh.MarshalPrivateKey(n, "") + } else { + block, err = ssh.MarshalPrivateKeyWithPassphrase(n, "", []byte(newPwd)) + } + if err != nil { + return err + } + err = os.WriteFile(outpath+"/"+originName+".openssh", pem.EncodeToMemory(block), 0644) + if err != nil { + return err + } else { + starlog.Green("已将私钥保存到%s\n", outpath+"/"+originName+".openssh") + } + case *ecdsa.PublicKey, *rsa.PublicKey, *dsa.PublicKey, *ed25519.PublicKey, *ecdh.PublicKey: + sk, err := ssh.NewPublicKey(n) + if err != nil { + return err + } + data = ssh.MarshalAuthorizedKey(sk) + err = os.WriteFile(outpath+"/"+originName+".pub.openssh", data, 0644) + if err != nil { + return err + } else { + starlog.Green("已将公钥保存到%s\n", outpath+"/"+originName+".pub.openssh") + } + } + } + return nil +} diff --git a/cert/cmd.go b/cert/cmd.go index 65e5200..de60390 100644 --- a/cert/cmd.go +++ b/cert/cmd.go @@ -195,21 +195,30 @@ func init() { CmdParse.Flags().StringVarP(&passwd, "passwd", "p", "", "pfx解密密码") Cmd.AddCommand(CmdParse) - CmdPkcs8.Flags().StringVarP(&passwd, "passwd", "p", "", "pfx解密密码") + + CmdPkcs8.Flags().StringVarP(&passwd, "passwd", "p", "", "解密密码") CmdPkcs8.Flags().StringVarP(&savefolder, "savefolder", "s", ".", "保存文件夹") + CmdPkcs8.Flags().StringVarP(&enPasswd, "en-passwd", "P", "", "加密密码") Cmd.AddCommand(CmdPkcs8) - CmdPkcs1.Flags().StringVarP(&passwd, "passwd", "p", "", "pfx解密密码") + CmdPkcs1.Flags().StringVarP(&passwd, "passwd", "p", "", "解密密码") CmdPkcs1.Flags().StringVarP(&savefolder, "savefolder", "s", ".", "保存文件夹") + CmdPkcs1.Flags().StringVarP(&enPasswd, "en-passwd", "P", "", "加密密码") Cmd.AddCommand(CmdPkcs1) CmdPkcs12.Flags().StringVarP(&passwd, "passwd", "p", "", "pfx解密密码") CmdPkcs12.Flags().StringVarP(&enPasswd, "pfx-passwd", "P", "", "pfx加密密码") CmdPkcs12.Flags().StringVarP(&savefolder, "savefolder", "s", ".", "保存文件夹") Cmd.AddCommand(CmdPkcs12) - CmdBasic.Flags().StringVarP(&passwd, "passwd", "p", "", "pfx解密密码") + CmdBasic.Flags().StringVarP(&passwd, "passwd", "p", "", "解密密码") CmdBasic.Flags().StringVarP(&savefolder, "savefolder", "s", ".", "保存文件夹") + CmdBasic.Flags().StringVarP(&enPasswd, "en-passwd", "P", "", "加密密码") Cmd.AddCommand(CmdBasic) + CmdOpenssh.Flags().StringVarP(&passwd, "passwd", "p", "", "解密密码") + CmdOpenssh.Flags().StringVarP(&savefolder, "savefolder", "s", ".", "保存文件夹") + CmdOpenssh.Flags().StringVarP(&enPasswd, "en-passwd", "P", "", "加密密码") + Cmd.AddCommand(CmdOpenssh) + } var CmdPkcs8 = &cobra.Command{ @@ -227,7 +236,7 @@ var CmdPkcs8 = &cobra.Command{ starlog.Errorln("读取证书错误", err) continue } - err = Pkcs8(data, passwd, filepath.Base(v), savefolder) + err = Pkcs8(data, passwd, enPasswd, filepath.Base(v), savefolder) if err != nil { starlog.Errorln("pkcs8转换错误", err) continue @@ -252,7 +261,7 @@ var CmdPkcs1 = &cobra.Command{ starlog.Errorln("读取证书错误", err) continue } - err = Pkcs1(data, passwd, filepath.Base(v), savefolder) + err = Pkcs1(data, passwd, enPasswd, filepath.Base(v), savefolder) if err != nil { starlog.Errorln("pkcs1转换错误", err) continue @@ -321,3 +330,28 @@ var CmdBasic = &cobra.Command{ } }, } + +var CmdOpenssh = &cobra.Command{ + Use: "openssh", + Short: "openssh转换", + Long: "openssh转换", + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + starlog.Errorln("请输入证书文件") + os.Exit(1) + } + for _, v := range args { + data, err := os.ReadFile(v) + if err != nil { + starlog.Errorln("读取证书错误", err) + continue + } + err = Openssh(data, passwd, enPasswd, filepath.Base(v), savefolder) + if err != nil { + starlog.Errorln("openssh转换错误", err) + continue + } + fmt.Println("\n-------" + v + "转换完毕---------\n") + } + }, +} diff --git a/go.mod b/go.mod index 87787cd..d0af76b 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/elazarl/goproxy v0.0.0-20231117061959-7cc037d33fb5 github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 github.com/emersion/go-smtp v0.20.2 + github.com/go-acme/lego/v4 v4.16.1 github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9 github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 @@ -33,7 +34,9 @@ require ( require ( b612.me/starmap v1.2.4 // indirect b612.me/win32api v0.0.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect + github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/jlaffaye/ftp v0.1.0 // indirect github.com/kr/fs v0.1.0 // indirect github.com/pkg/sftp v1.13.4 // indirect diff --git a/go.sum b/go.sum index adb75e4..8bf2fa7 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ b612.me/win32api v0.0.2 h1:5PwvPR5fYs3a/v+LjYdtRif+5Q04zRGLTVxmCYNjCpA= b612.me/win32api v0.0.2/go.mod h1:sj66sFJDKElEjOR+0YhdSW6b4kq4jsXu4T5/Hnpyot0= b612.me/wincmd v0.0.3 h1:GYrkYnNun39yfNcA2+u0h4VW/BYbTrJK39QW4W1LCYA= b612.me/wincmd v0.0.3/go.mod h1:nWdNREHO6F+2PngEUcyYN3Eo7DzYEVa/fO6czd9d/fo= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -32,12 +34,17 @@ github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1X github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-smtp v0.20.2 h1:peX42Qnh5Q0q3vrAnRy43R/JwTnnv75AebxbkTL7Ia4= github.com/emersion/go-smtp v0.20.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= +github.com/go-acme/lego/v4 v4.16.1 h1:JxZ93s4KG0jL27rZ30UsIgxap6VGzKuREsSkkyzeoCQ= +github.com/go-acme/lego/v4 v4.16.1/go.mod h1:AVvwdPned/IWpD/ihHhMsKnveF7HHYAz/CmtXi7OZoE= +github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U= +github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9 h1:cC0Hbb+18DJ4i6ybqDybvj4wdIDS4vnD0QEci98PgM8= github.com/goftp/file-driver v0.0.0-20180502053751-5d604a0fc0c9/go.mod h1:GpOj6zuVBG3Inr9qjEnuVTgBlk2lZ1S9DcoFiXWyKss= github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42 h1:JdOp2qR5PF4O75tzHeqrwnDDv8oHDptWyTbyYS4fD8E= github.com/goftp/server v0.0.0-20200708154336-f64f7c2d8a42/go.mod h1:k/SS6VWkxY7dHPhoMQ8IdRu8L4lQtmGbhyXGg+vCnXE= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= diff --git a/httpserver/server.go b/httpserver/server.go index b83c67e..4e7d79e 100644 --- a/httpserver/server.go +++ b/httpserver/server.go @@ -581,6 +581,8 @@ func (h *HttpServer) CalcRange(r *http.Request) (int64, int64) { if strings.ToLower(k) == "range" { if strings.Contains(v[0], "bytes=") { v[0] = strings.Replace(v[0], "bytes=", "", -1) + } else { + continue } data := strings.Split(v[0], "-") if len(data) == 0 { @@ -632,7 +634,7 @@ func (h *HttpServer) BuildHeader(w http.ResponseWriter, r *http.Request, fullpat start, end := h.CalcRange(r) if start != -1 { if end == -1 { - w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(start, 10)+"-"+strconv.FormatInt(finfo.Size(), 10)+"/"+strconv.FormatInt(finfo.Size(), 10)) + w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(start, 10)+"-"+strconv.FormatInt(finfo.Size()-1, 10)+"/"+strconv.FormatInt(finfo.Size(), 10)) //w.Header().Set("Content-Length", strconv.FormatInt(fpinfo.Size()-rangeStart, 10)) } else { w.Header().Set("Content-Range", `bytes `+strconv.FormatInt(start, 10)+"-"+strconv.FormatInt(end, 10)+"/"+strconv.FormatInt(finfo.Size(), 10)) diff --git a/keygen/keygen.go b/keygen/keygen.go index c68fd3d..d0ea7c0 100644 --- a/keygen/keygen.go +++ b/keygen/keygen.go @@ -15,6 +15,7 @@ import ( "encoding/pem" "errors" "fmt" + "golang.org/x/crypto/ssh" "io" "math/big" "os" @@ -50,10 +51,13 @@ func (k *KeyGen) Gen() error { if !k.Force && staros.Exists(filepath.Join(k.Outfolder, k.Prefix+".pub")) { return errors.New("ssh pub file exists") } + if !k.Force && staros.Exists(filepath.Join(k.Outfolder, k.Prefix+".openssh")) { + return errors.New("ssh priv file exists") + } if !k.Force && staros.Exists(filepath.Join(k.Outfolder, k.Prefix+".key.pub")) { return errors.New("pub file exists") } - var sshPubByte, keyPubByte, keyPrivByte, Crt []byte + var sshPubByte, sshPrivByte, keyPubByte, keyPrivByte, Crt []byte var priv, pub any var err error @@ -101,10 +105,27 @@ func (k *KeyGen) Gen() error { if err != nil { return err } + var block *pem.Block + if k.Encrypt != "" { + block, err = ssh.MarshalPrivateKey(priv, "") + } else { + block, err = ssh.MarshalPrivateKeyWithPassphrase(priv, "", []byte(k.Encrypt)) + } + if err != nil { + return err + } + sshPrivByte = pem.EncodeToMemory(block) + if err != nil { + return err + } _, Crt, err = k.GenerateCert(priv) if err != nil { return err } + err = os.WriteFile(filepath.Join(k.Outfolder, k.Prefix+".openssh"), sshPrivByte, 0644) + if err != nil { + return err + } err = os.WriteFile(filepath.Join(k.Outfolder, k.Prefix+".crt"), Crt, 0644) if err != nil { return err diff --git a/net/cmd.go b/net/cmd.go index d24f349..9c9cae2 100644 --- a/net/cmd.go +++ b/net/cmd.go @@ -57,7 +57,7 @@ func init() { } var CmdNatClient = &cobra.Command{ - Use: "natc", + Use: "natpc", Short: "nat穿透客户端", Run: func(cmd *cobra.Command, args []string) { if natc.ServiceTarget == "" || natc.CmdTarget == "" { @@ -69,7 +69,7 @@ var CmdNatClient = &cobra.Command{ } var CmdNatServer = &cobra.Command{ - Use: "nats", + Use: "natps", Short: "nat穿透服务端", Run: func(cmd *cobra.Command, args []string) {