├── util ├── version.go ├── banner.go └── log.go ├── .idea ├── modules.xml ├── p12tool.iml └── workspace.xml ├── go.mod ├── vars └── var.go ├── cmd └── main.go ├── work ├── command.go ├── bruteforce.go └── parse.go ├── .github └── workflows │ └── release.yml ├── .goreleaser.yml ├── LICENSE ├── common └── flag.go ├── README.MD └── go.sum /util/version.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "runtime" 5 | "time" 6 | ) 7 | 8 | var ( 9 | Version = "1.0" 10 | GitCommit = "n/a" 11 | BuildDate = time.Now().Format("01/02/06") 12 | GoVersion = runtime.Version() 13 | Author = "Evi1cg" 14 | ) 15 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module p12tool 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect 7 | github.com/fatih/color v1.10.0 8 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 9 | github.com/urfave/cli/v2 v2.3.0 10 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 11 | ) 12 | -------------------------------------------------------------------------------- /vars/var.go: -------------------------------------------------------------------------------- 1 | package vars 2 | 3 | import ( 4 | "p12tool/util" 5 | "sync" 6 | ) 7 | 8 | var ( 9 | Threads = 100 10 | DebugMode bool 11 | Cert string 12 | Pass string 13 | File string 14 | OutFile string 15 | Logger util.Logger 16 | CrackedPassword string 17 | Attempts int 18 | ResultsLock sync.RWMutex 19 | ) -------------------------------------------------------------------------------- /.idea/p12tool.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /util/banner.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import "fmt" 4 | 5 | func PrintBanner() { 6 | banner := ` 7 | ██████╗ ██╗██████╗ ████████╗ ██████╗ ██████╗ ██╗ 8 | ██╔══██╗███║╚════██╗╚══██╔══╝██╔═══██╗██╔═══██╗██║ 9 | ██████╔╝╚██║ █████╔╝ ██║ ██║ ██║██║ ██║██║ 10 | ██╔═══╝ ██║██╔═══╝ ██║ ██║ ██║██║ ██║██║ 11 | ██║ ██║███████╗ ██║ ╚██████╔╝╚██████╔╝███████╗ 12 | ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ 13 | ` 14 | fmt.Printf("%v\nVersion: %v (%v) - %v - %v\n\n", banner, Version, GitCommit, BuildDate, Author) 15 | } 16 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/urfave/cli/v2" 5 | "log" 6 | "os" 7 | "p12tool/common" 8 | "p12tool/util" 9 | ) 10 | 11 | func main() { 12 | util.PrintBanner() 13 | app := cli.NewApp() 14 | app.Name = "p12tool" 15 | app.Authors = []*cli.Author{ 16 | &cli.Author{ 17 | Name: "Evi1cg", 18 | }} 19 | app.Usage = "A tool to parse p12 cert file or bruteforce attacks against cert password" 20 | app.Commands = []*cli.Command{&common.Parse, &common.Crack} 21 | app.Flags = append(app.Flags,common.Flags...) 22 | err := app.Run(os.Args) 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /work/command.go: -------------------------------------------------------------------------------- 1 | package work 2 | 3 | import ( 4 | "github.com/urfave/cli/v2" 5 | "p12tool/vars" 6 | ) 7 | 8 | // 传入参数解析 9 | func Parse(ctx *cli.Context) (err error) { 10 | if ctx.IsSet("debug") { 11 | vars.DebugMode = ctx.Bool("debug") 12 | } 13 | if ctx.IsSet("cert"){ 14 | vars.Cert = ctx.String("cert") 15 | } 16 | if ctx.IsSet("password"){ 17 | vars.Pass = ctx.String("password") 18 | } 19 | if ctx.IsSet("file"){ 20 | vars.File = ctx.String("file") 21 | } 22 | if ctx.IsSet("thread"){ 23 | vars.Threads = ctx.Int("thread") 24 | } 25 | if ctx.IsSet("out"){ 26 | vars.OutFile = ctx.String("out") 27 | } 28 | return err 29 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Release 4 | on: 5 | create: 6 | tags: 7 | - v* 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | goreleaser: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - 18 | name: Checkout 19 | uses: actions/checkout@v2 20 | with: 21 | fetch-depth: 0 22 | - 23 | name: Set up Go 24 | uses: actions/setup-go@v2 25 | with: 26 | go-version: 1.15 27 | - 28 | name: Run GoReleaser 29 | uses: goreleaser/goreleaser-action@v2 30 | with: 31 | version: latest 32 | args: release --rm-dist 33 | env: 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | # This is an example goreleaser.yaml file with some sane defaults. 2 | # Make sure to check the documentation at http://goreleaser.com 3 | before: 4 | hooks: 5 | # You may remove this if you don't use go modules. 6 | - go mod download 7 | # you may remove this if you don't need go generate 8 | - go generate ./... 9 | builds: 10 | - env: 11 | - CGO_ENABLED=0 12 | goos: 13 | - linux 14 | - windows 15 | - darwin 16 | main: ./cmd/main.go 17 | 18 | ldflags: 19 | - -s -w 20 | 21 | archives: 22 | - replacements: 23 | darwin: Darwin 24 | linux: Linux 25 | windows: Windows 26 | 386: i386 27 | amd64: x86_64 28 | checksum: 29 | name_template: 'checksums.txt' 30 | 31 | snapshot: 32 | name_template: "{{ .Tag }}-next" 33 | 34 | changelog: 35 | skip: true 36 | sort: asc 37 | filters: 38 | exclude: 39 | - '^docs:' 40 | - '^test:' 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Evi1cg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /util/log.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/op/go-logging" 7 | ) 8 | 9 | type Logger struct { 10 | Log *logging.Logger 11 | } 12 | 13 | func NewLogger(verbose bool, logFileName string) Logger { 14 | log := logging.MustGetLogger("p12tool") 15 | format := logging.MustStringFormatter( 16 | `%{color}%{time:2006/01/02 15:04:05} -> %{message}%{color:reset}`, 17 | ) 18 | formatNoColor := logging.MustStringFormatter( 19 | `%{time:2006/01/02 15:04:05} -> %{message}`, 20 | ) 21 | backend := logging.NewLogBackend(os.Stdout, "", 0) 22 | backendFormatter := logging.NewBackendFormatter(backend, format) 23 | 24 | if logFileName != "" { 25 | outputFile, err := os.Create(logFileName) 26 | if err != nil { 27 | panic(err) 28 | } 29 | fileBackend := logging.NewLogBackend(outputFile, "", 0) 30 | fileFormatter := logging.NewBackendFormatter(fileBackend, formatNoColor) 31 | logging.SetBackend(backendFormatter, fileFormatter) 32 | } else { 33 | logging.SetBackend(backendFormatter) 34 | } 35 | 36 | if verbose { 37 | logging.SetLevel(logging.DEBUG, "") 38 | } else { 39 | logging.SetLevel(logging.INFO, "") 40 | } 41 | return Logger{log} 42 | } 43 | -------------------------------------------------------------------------------- /common/flag.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "github.com/urfave/cli/v2" 5 | "p12tool/vars" 6 | "p12tool/work" 7 | ) 8 | 9 | 10 | 11 | var Flags = []cli.Flag{ 12 | &cli.StringFlag{Name: "cert", Aliases: []string{"c"},Usage: "The cert file you choice."}, 13 | &cli.BoolFlag{Name: "debug", Aliases: []string{"d"}, Value: false, Usage: "Debug mode."}, 14 | } 15 | var ParseFlag = []cli.Flag{ 16 | &cli.StringFlag{Name: "password", Aliases: []string{"p"} ,Usage: "The cert file password."}, 17 | } 18 | var BruteFlag = []cli.Flag{ 19 | &cli.StringFlag{Name: "file", Aliases: []string{"f"} ,Usage: "The cert file password."}, 20 | &cli.IntFlag{Name: "thread", Aliases: []string{"t"} , Value: vars.Threads ,Usage: "Crack thread num."}, 21 | &cli.StringFlag{Name: "out", Aliases: []string{"o"} ,Usage: "Output file to save cracked password."}, 22 | } 23 | 24 | 25 | var Parse = cli.Command{ 26 | Name: "parse", 27 | Usage: "Parse p12 file and print cert info", 28 | Description: "Parse p12 file and print cert info", 29 | Action: work.ParseP12file, 30 | Flags: append(Flags, ParseFlag...), 31 | } 32 | 33 | var Crack = cli.Command{ 34 | Name: "crack", 35 | Usage: "Crack p12 file password.", 36 | Description: "Crack p12 file password.", 37 | Action: work.P12FileBrute, 38 | Flags: append(Flags,BruteFlag...), 39 | } -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # P12tool 2 | 学习golang写的一个用来解析和爆破p12证书的小工具,代码写的有点戳,能用就行。 3 | 4 | ## Usage 5 | ``` 6 | 7 | ██████╗ ██╗██████╗ ████████╗ ██████╗ ██████╗ ██╗ 8 | ██╔══██╗███║╚════██╗╚══██╔══╝██╔═══██╗██╔═══██╗██║ 9 | ██████╔╝╚██║ █████╔╝ ██║ ██║ ██║██║ ██║██║ 10 | ██╔═══╝ ██║██╔═══╝ ██║ ██║ ██║██║ ██║██║ 11 | ██║ ██║███████╗ ██║ ╚██████╔╝╚██████╔╝███████╗ 12 | ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝ 13 | 14 | Version: dev (n/a) - 12/31/20 - Evi1cg 15 | 16 | NAME: 17 | p12tool - A tool to parse p12 cert file or bruteforce attacks against cert password 18 | 19 | USAGE: 20 | main [global options] command [command options] [arguments...] 21 | 22 | AUTHOR: 23 | Evi1cg 24 | 25 | COMMANDS: 26 | parse Parse p12 file and print cert info 27 | crack Crack p12 file password. 28 | help, h Shows a list of commands or help for one command 29 | 30 | GLOBAL OPTIONS: 31 | --cert value, -c value The cert file you choice. 32 | --debug, -d Debug mode. (default: false) 33 | --help, -h show help (default: false) 34 | ``` 35 | 36 | ## crack 37 | ```bash 38 | go run cmd/main.go crack -c file.pfx -f passwords.txt 39 | ``` 40 | >可选: -t 指定线程,-d 开启debug模式,-o 将破解成功的密码输出至指定文件。 41 | 42 | ![](https://blogpics-1251691280.file.myqcloud.com/imgs/20201231232938.png) 43 | 44 | 45 | ## parse 46 | ```bash 47 | go run cmd/main.go parse -c file.pfx -p password 48 | ``` 49 | 50 | ![](https://blogpics-1251691280.file.myqcloud.com/imgs/20201231233107.png) 51 | 52 | 对证书进行解析,输出证书信息,顺便输出是否可对程序进行签名,免去手动验证的烦恼。 ~~ 53 | 54 | 2020年推得最后一个小工具,祝大家新年快乐!! 55 | 56 | ## 参考 57 | * 1、https://github.com/allyomalley/p12CrackerGo 58 | * 2、https://golang.org/pkg/crypto/x509 59 | * 3、https://godoc.org/golang.org/x/crypto/pkcs12 -------------------------------------------------------------------------------- /work/bruteforce.go: -------------------------------------------------------------------------------- 1 | package work 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "github.com/urfave/cli/v2" 7 | "golang.org/x/crypto/pkcs12" 8 | "io/ioutil" 9 | "os" 10 | "p12tool/util" 11 | "p12tool/vars" 12 | "strconv" 13 | ) 14 | 15 | func P12FileBrute(ctx *cli.Context) (err error) { 16 | Parse(ctx) 17 | vars.Logger = util.NewLogger(vars.DebugMode, "") 18 | p12Bytes, err := ioutil.ReadFile(vars.Cert) 19 | if err != nil { 20 | vars.Logger.Log.Error("[-] Please input cert file") 21 | return nil 22 | } 23 | targetFile, err := os.Open(vars.File) 24 | if err != nil { 25 | vars.Logger.Log.Error("[-] Please input pass list file") 26 | return nil 27 | } 28 | scanner := bufio.NewScanner(targetFile) 29 | scanner.Split(bufio.ScanLines) 30 | vars.Logger.Log.Info("[*] Brute forcing...") 31 | crack(scanner, p12Bytes, vars.Threads) 32 | if vars.CrackedPassword !=""{ 33 | success := fmt.Sprintf("[+] Password found ==> %s", vars.CrackedPassword) 34 | vars.Logger.Log.Noticef(success) 35 | if vars.OutFile != ""{ 36 | fi, err := os.Create(vars.OutFile) 37 | if err != nil{ 38 | vars.Logger.Log.Errorf("[!] Can't create file %s",vars.OutFile) 39 | } 40 | defer fi.Close() 41 | _, err2 := fi.WriteString(success) 42 | if err2 != nil { 43 | vars.Logger.Log.Errorf("[!] Write file error") 44 | } 45 | } 46 | vars.Logger.Log.Infof("[*] Successfully cracked password after " + strconv.Itoa(vars.Attempts) + " attempts!") 47 | } 48 | return err 49 | } 50 | 51 | func crack(scanner *bufio.Scanner, p12Bytes []byte, threads int) { 52 | vars.Logger.Log.Infof("[*] Start thread num %d",vars.Threads) 53 | semaphore := make(chan bool, threads) 54 | lineNo := 0 55 | for scanner.Scan() { 56 | lineNo = lineNo + 1 57 | semaphore <- true 58 | 59 | go func(password string, line int) { 60 | decrypted := checkPass(p12Bytes, password) 61 | if decrypted != "" { 62 | vars.ResultsLock.Lock() 63 | vars.Attempts = line 64 | vars.CrackedPassword = password 65 | vars.ResultsLock.Unlock() 66 | } 67 | <-semaphore 68 | }(scanner.Text(), lineNo) 69 | } 70 | 71 | for i := 0; i < cap(semaphore); i++ { 72 | semaphore <- true 73 | } 74 | } 75 | func checkPass(p12Bytes []byte, password string) string { 76 | _, err := pkcs12.ToPEM(p12Bytes, password) 77 | if err != nil{ 78 | if err == pkcs12.ErrIncorrectPassword{ 79 | if vars.DebugMode{ 80 | vars.Logger.Log.Debugf("[-] Password [%s] incorrect",password) 81 | } 82 | }else{ 83 | vars.Logger.Log.Error("[-] Check your file is P12 cert file !!") 84 | os.Exit(1) 85 | } 86 | 87 | }else{ 88 | return password 89 | } 90 | return "" 91 | } -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 2 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 3 | github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= 4 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 5 | github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= 6 | github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= 7 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 8 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 9 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 10 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 11 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= 12 | github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= 13 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 14 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 15 | github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= 16 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 17 | github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= 18 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 19 | github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= 20 | github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= 21 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 22 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU= 23 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 24 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 25 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 26 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 27 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 28 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= 29 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 30 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 31 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 32 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 33 | -------------------------------------------------------------------------------- /work/parse.go: -------------------------------------------------------------------------------- 1 | package work 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "crypto/x509" 7 | "encoding/pem" 8 | "fmt" 9 | "github.com/urfave/cli/v2" 10 | "io/ioutil" 11 | "log" 12 | "p12tool/util" 13 | "p12tool/vars" 14 | 15 | "golang.org/x/crypto/pkcs12" 16 | ) 17 | 18 | func ParseP12file(ctx *cli.Context) (err error) { 19 | Parse(ctx) 20 | vars.Logger = util.NewLogger(vars.DebugMode, "") 21 | p12Bytes, err := ioutil.ReadFile(vars.Cert) 22 | if err != nil { 23 | vars.Logger.Log.Error("[-] Please input cert file") 24 | return nil 25 | } 26 | pass := vars.Pass 27 | if len(pass) == 0{ 28 | vars.Logger.Log.Error("[-] Please input a password") 29 | return nil 30 | } 31 | // P12 to PEM 32 | blocks, err := pkcs12.ToPEM(p12Bytes, pass) 33 | 34 | if err != nil{ 35 | if err == pkcs12.ErrIncorrectPassword{ 36 | vars.Logger.Log.Error("[-] Password incorrect") 37 | }else{ 38 | vars.Logger.Log.Error("[-] Check your file is P12 cert file !!") 39 | } 40 | return nil 41 | } 42 | // Append all PEM Blocks together 43 | var pemData []byte 44 | for _, b := range blocks { 45 | pemData = append(pemData, pem.EncodeToMemory(b)...) 46 | } 47 | vars.Logger.Log.Notice("[+] Parse cert file ok ;)") 48 | //println(PemPrivateKeyFromPem(string(pemData))) 49 | //println(PemCertFromPem(string(pemData))) 50 | block, rest := pem.Decode([]byte(PemCertFromPem(string(pemData)))) 51 | if block == nil || len(rest) > 0 { 52 | log.Fatal("Certificate decoding error") 53 | return nil 54 | } 55 | cert, err := x509.ParseCertificate(block.Bytes) 56 | if err != nil { 57 | log.Fatal(err) 58 | } 59 | fmt.Printf("=============================INFO===========================\nCommonName:\t\t%s\nCountry:\t\t%s\nOrganization:\t\t%s\nLocality:\t\t%s\nNotAfter:\t\t%s\n============================================================\n",cert.Subject.CommonName,cert.Subject.Country,cert.Subject.Organization,cert.Subject.Locality,cert.NotAfter) 60 | for i := range cert.ExtKeyUsage{ 61 | if cert.ExtKeyUsage[i] == 0 || cert.ExtKeyUsage[i] == 3{ 62 | vars.Logger.Log.Notice("[+] Can be used for code signing!!;)") 63 | return nil 64 | } 65 | } 66 | vars.Logger.Log.Error("[-] Not suitable for code signing ;(") 67 | return err 68 | } 69 | 70 | 71 | func PemPrivateKeyFromPem(data string) string { 72 | pemBytes := []byte(data) 73 | 74 | // Use tls lib to construct tls certificate and key object from PEM data 75 | // The tls.X509KeyPair function is smart enough to parse combined cert and key pem data 76 | certAndKey, err := tls.X509KeyPair(pemBytes, pemBytes) 77 | if err != nil { 78 | panic(err) 79 | } 80 | 81 | // Get parsed private key as PKCS8 data 82 | privBytes, err := x509.MarshalPKCS8PrivateKey(certAndKey.PrivateKey) 83 | if err != nil { 84 | panic(fmt.Sprintf("Unable to marshal private key: %v", err)) 85 | } 86 | 87 | // Encode just the private key back to PEM and return it 88 | var privPem bytes.Buffer 89 | if err := pem.Encode(&privPem, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { 90 | panic(fmt.Sprintf("Failed to write data: %s", err)) 91 | } 92 | 93 | return privPem.String() 94 | } 95 | 96 | func PemCertFromPem(data string) string { 97 | pemBytes := []byte(data) 98 | 99 | // Use tls lib to construct tls certificate and key object from PEM data 100 | // The tls.X509KeyPair function is smart enough to parse combined cert and key pem data 101 | certAndKey, err := tls.X509KeyPair(pemBytes, pemBytes) 102 | if err != nil { 103 | panic(fmt.Sprintf("Error generating X509KeyPair: %v", err)) 104 | } 105 | 106 | leaf, err := x509.ParseCertificate(certAndKey.Certificate[0]) 107 | if err != nil { 108 | panic(err) 109 | } 110 | 111 | // Encode just the leaf cert as pem 112 | var certPem bytes.Buffer 113 | if err := pem.Encode(&certPem, &pem.Block{Type: "CERTIFICATE", Bytes: leaf.Raw}); err != nil { 114 | panic(fmt.Sprintf("Failed to write data: %s", err)) 115 | } 116 | 117 | return certPem.String() 118 | } 119 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 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 | 92 | 93 | true 94 | 95 | --------------------------------------------------------------------------------