diff --git a/cmd/edgetk/main.go b/cmd/edgetk/main.go index ad65ef1..3418dcd 100644 --- a/cmd/edgetk/main.go +++ b/cmd/edgetk/main.go @@ -1,6 +1,6 @@ /* EDGE Toolkit -- Pure Go Command-line Unique Integrated Security Suite - Copyright (C) 2020-2023 Pedro F. Albanese + Copyright (C) 2020-2024 Pedro F. Albanese This program is free software: you can redistribute it and/or modify it under the terms of the ISC License. @@ -40,6 +40,7 @@ import ( "encoding/asn1" "encoding/base64" "encoding/binary" + "encoding/gob" "encoding/hex" "encoding/pem" "errors" @@ -145,6 +146,9 @@ import ( "github.com/pedroalbanese/whirlpool" "github.com/pedroalbanese/xoodoo/xoodyak" "github.com/zeebo/blake3" + + "github.com/pedroalbanese/kryptology/pkg/core/curves" + "github.com/pedroalbanese/kryptology/pkg/verenc/elgamal" ) var ( @@ -156,13 +160,14 @@ var ( cph = flag.String("cipher", "aes", "Symmetric algorithm: aes, blowfish, magma or sm4.") crl = flag.String("crl", "", "Certificate Revocation List path.") crypt = flag.String("crypt", "", "Bulk Encryption with Stream and Block ciphers. [enc|dec|help]") + curveFlag = flag.String("curve", "ecdsa", "Subjacent curve (Koblitz, ECDSA, BLS12381G1/2.)") digest = flag.Bool("digest", false, "Target file/wildcard to generate hashsum list. ('-' for STDIN)") encode = flag.String("hex", "", "Encode binary string to hex format and vice-versa. [enc|dump|dec]") factorPStr = flag.String("factorp", "", "Makwa private Factor P. (for Makwa Password-hashing Scheme)") factorQStr = flag.String("factorq", "", "Makwa private Factor Q. (for Makwa Password-hashing Scheme)") hierarchy = flag.Uint("hid", 0x01, "Hierarchy Identifier. (for SM9 User Private Key)") id = flag.String("id", "", "User Identifier. (for SM9 User Private Key operations)") - id2 = flag.String("peerid", "", "Remote's side User Identifier. (for SM9 Key Agreement)") + id2 = flag.String("peerid", "", "Remote's side User Identifier. (for SM9 Key Exchange)") info = flag.String("info", "", "Additional info. (for HKDF command and AEAD bulk encryption)") iport = flag.String("ipport", "", "Local Port/remote's side Public IP:Port.") iter = flag.Int("iter", 1, "Iter. (for Password-based key derivation function)") @@ -175,6 +180,7 @@ var ( mode = flag.String("mode", "CTR", "Mode of operation: GCM, MGM, CBC, CFB8, OCB, OFB.") modulusStr = flag.String("modulus", "", "Makwa modulus. (Makwa hash Public Parameter)") paramset = flag.String("paramset", "A", "Elliptic curve ParamSet: A, B, C, D. (for GOST2012)") + params = flag.String("params", "", "ElGamal Public Parameters path.") pkey = flag.String("pkey", "", "Subcommands: keygen|certgen, sign|verify|derive, text|modulus.") priv = flag.String("priv", "Private.pem", "Private key path. (for keypair generation)") pub = flag.String("pub", "Public.pem", "Public key path. (for keypair generation)") @@ -243,9 +249,9 @@ Public Key Subcommands: crl decrypt verify setup Public Key Algorithms: - ecdsa gost2012 sm9encrypt sphincs - ed25519 rsa (default) sm9sign x25519 - ed25519ph sm2 + ecdsa elgamal sm2 gost2012 + ed25519 ec-elgamal sm9encrypt sphincs + ed25519ph rsa (default) sm9sign x25519 Stream Ciphers: ascon hc128 rabbit skein @@ -440,7 +446,7 @@ Subcommands: *pwd = string(pass) } - if (*pkey == "setup") && *pwd == "" { + if (*pkey == "setup") && *pwd == "" && strings.ToUpper(*alg) != "ELGAMAL" { print("Passphrase: ") pass, _ := gopass.GetPasswdMasked() *pwd = string(pass) @@ -475,7 +481,7 @@ Subcommands: *pwd2 = string(pass) } - if (*pkey == "sign" || *pkey == "decrypt" || *pkey == "derive" || *pkey == "derivea" || *pkey == "unwrapkey" || *pkey == "deriveb" || *pkey == "certgen" || *pkey == "text" || *pkey == "modulus" || *tcpip == "server" || *tcpip == "client" || *pkey == "pkcs12" || *pkey == "req" || *pkey == "x509" || *pkey == "x25519" || *pkey == "vko" || *pkey == "crl") && *key != "" && *pwd == "" { + if (*pkey == "sign" || *pkey == "decrypt" || *pkey == "derive" || *pkey == "derivea" || *pkey == "unwrapkey" || *pkey == "deriveb" || *pkey == "certgen" || *pkey == "text" || *pkey == "modulus" || *tcpip == "server" || *tcpip == "client" || *pkey == "pkcs12" || *pkey == "req" || *pkey == "x509" || *pkey == "x25519" || *pkey == "vko" || *pkey == "crl") && (*key != "") && *pwd == "" { file, err := os.Open(*key) if err != nil { log.Fatal(err) @@ -769,12 +775,16 @@ Subcommands: *iter = 4096 } + if (strings.ToUpper(*alg) == "ELGAMAL" && *pkey != "wrapkey" && *pkey != "unwrapkey") && *length != 256 && *length != 512 && *length != 768 && *length != 1024 && *length != 2048 && *length != 3072 && *length != 4096 && *length != 7680 { + *length = 3072 + } + if *digest && *md == "spritz" && *length == 0 { *length = 256 } - if *pkey == "keygen" && *alg == "sphincs" && *iter == 1 { - *iter = 1048576 + if *pkey == "keygen" && strings.ToUpper(*alg) == "SPHINCS" && *iter == 1 { + *iter = 16384 } if (*pkey == "wrapkey" || *pkey == "unwrapkey") && *length == 0 { @@ -4763,7 +4773,7 @@ Subcommands: os.Exit(1) } - fmt.Printf("SM9Sign(%s)= %x\n", inputdesc, signature) + fmt.Printf("PureSM9(%s)= %x\n", inputdesc, signature) } if *pkey == "verify" && (strings.ToUpper(*alg) == "SM9SIGN") { @@ -4799,13 +4809,15 @@ Subcommands: } if sm9.VerifyASN1(pubKey, []byte(*id), byte(*hierarchy), hashed, signature) { - fmt.Println("Signature verified successfully!") + fmt.Println("Verified: true") + os.Exit(0) } else { - fmt.Println("Signature verification failed.") + fmt.Println("Verified: false") + os.Exit(1) } } - if *pkey == "sign" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA" || strings.ToUpper(*alg) == "SM2") { + if *pkey == "sign" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA") { var privatekey *ecdsa.PrivateKey var h hash.Hash if *md == "sha224" { @@ -4891,7 +4903,7 @@ Subcommands: os.Exit(0) } - if *pkey == "verify" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA" || strings.ToUpper(*alg) == "SM2") { + if *pkey == "verify" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA") { var h hash.Hash if *md == "sha224" { h = sha256.New224() @@ -4980,6 +4992,58 @@ Subcommands: os.Exit(0) } + if *pkey == "sign" && (strings.ToUpper(*alg) == "SM2") { + var privatekey *sm2.PrivateKey + file, err := ioutil.ReadFile(*key) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + privatekey, err = DecodeSM2PrivateKey(file) + if err != nil { + log.Fatal(err) + } + inputBytes, err := ioutil.ReadAll(inputfile) + if err != nil { + log.Fatal(err) + } + signature, err := privatekey.Sign(rand.Reader, inputBytes, sm2.DefaultSM2SignerOpts) + if err != nil { + log.Fatal(err) + } + fmt.Println("PureSM2("+inputdesc+")=", hex.EncodeToString(signature)) + os.Exit(0) + } + + if *pkey == "verify" && (strings.ToUpper(*alg) == "SM2") { + file, err := ioutil.ReadFile(*key) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + public, err = DecodePublicKey(file) + if err != nil { + log.Fatal(err) + } + inputBytes, err := ioutil.ReadAll(inputfile) + if err != nil { + log.Fatal(err) + } + sigBytes, err := hex.DecodeString(*sig) + if err != nil { + log.Fatal(err) + } + verifystatus := sm2.VerifyASN1WithSM2(public, nil, inputBytes, sigBytes) + if verifystatus == true { + fmt.Printf("Verified: %v\n", verifystatus) + os.Exit(0) + } else { + fmt.Printf("Verified: %v\n", verifystatus) + os.Exit(1) + } + os.Exit(0) + } + if *pkey == "sign" && (strings.ToUpper(*alg) == "ED25519PH") { var h hash.Hash if *md == "sha224" { @@ -5717,7 +5781,7 @@ Subcommands: var PEM string var b []byte - if (*pkey == "text" || *pkey == "modulus" || *pkey == "check" || *pkey == "randomart" || *pkey == "fingerprint" || *pkey == "info") && *crl == "" { + if (*pkey == "text" || *pkey == "modulus" || *pkey == "check" || *pkey == "randomart" || *pkey == "fingerprint" || *pkey == "info") && *crl == "" && *params == "" { if *key != "" { b, err = ioutil.ReadFile(*key) if err != nil { @@ -5756,6 +5820,10 @@ Subcommands: *alg = "SM9SIGN" } else if strings.Contains(s, "SPHINCS") { *alg = "SPHINCS" + } else if strings.Contains(s, "EC-ELGAMAL") { + *alg = "EC-ELGAMAL" + } else if strings.Contains(s, "ELGAMAL") { + *alg = "ELGAMAL" } else if strings.Contains(s, "PRIVATE") { *alg = "ED25519" } @@ -5834,7 +5902,7 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) - println("SPHINCS+ (512-bit)") + println("SPHINCS+ (256-bit)") randomArt := randomart.FromString(string(buf)) println(randomArt) os.Exit(0) @@ -5857,830 +5925,1098 @@ Subcommands: os.Exit(0) } - if *pkey == "modulus" && (strings.ToUpper(*alg) == "SM9SIGN" || strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Master" || PEM == "Private") { - keyFileContent, err := ioutil.ReadFile(*key) - if err != nil { - log.Fatal("Error reading key file:", err) - } - - keyBlock, _ := pem.Decode(keyFileContent) - if keyBlock == nil { - log.Fatal("Failed to decode PEM block containing the private key.") - } - - var privPEM []byte - - if IsEncryptedPEMBlock(keyBlock) { - privKeyBytes, err := DecryptPEMBlock(keyBlock, []byte(*pwd)) + if (strings.ToUpper(*alg) == "ELGAMAL" && strings.ToUpper(*alg) != "EC-ELGAMAL" || *params != "") && (*pkey == "keygen" || *pkey == "setup" || *pkey == "wrapkey" || *pkey == "unwrapkey" || *pkey == "text" || *pkey == "modulus" || *pkey == "sign" || *pkey == "verify") { + if *pkey == "setup" { + setParams, err := generateSchnorrGroup() + err = saveSchnorrParamsToPEM(*params, setParams) if err != nil { - log.Fatal("Error decrypting private key:", err) + log.Fatal("Error saving Schnorr parameters to PEM file:", err) + return } - privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 PRIVATE KEY", Bytes: privKeyBytes}) - } else { - privPEM = keyFileContent - } - - var privateKeyPemBlock *pem.Block - privateKeyPemBlock, _ = pem.Decode(privPEM) - - privateKey, err := smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) - if err != nil { - log.Fatal("Error parsing private key:", err) + os.Exit(0) } - - switch keyType := privateKey.(type) { - case *sm9.EncryptPrivateKey: - fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) - case *sm9.SignPrivateKey: - fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) - case *sm9.EncryptMasterPrivateKey: - fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) - case *sm9.SignMasterPrivateKey: - fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) - default: - log.Fatal("Invalid private key type. Expected sm9.EncryptPrivateKey, or sm9.SignPrivateKey.") + var blockType string + if *key != "" { + pemData, err := ioutil.ReadFile(*key) + if err != nil { + fmt.Println("Error reading PEM file:", err) + return + } + block, _ := pem.Decode(pemData) + if block == nil { + fmt.Println("Error decoding PEM block") + return + } + blockType = block.Type } - } + if *pkey == "text" && *key != "" && blockType == "ELGAMAL PRIVATE KEY" { + priv, err := readPrivateKeyFromPEM(*key) + if err != nil { + fmt.Println("Error reading private key:", err) + return + } + privPEM := &PrivateKey{ + X: priv.X, + P: priv.P, + G: priv.G, + } - if *pkey == "modulus" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { - keyFileContent, err := ioutil.ReadFile(*key) - if err != nil { - log.Fatal("Error reading key file:", err) - } + privBytes, err := encodePrivateKeyPEM(privPEM) + if err != nil { + return + } + pemBlock := &pem.Block{ + Type: "ELGAMAL PRIVATE KEY", + Bytes: privBytes, + } - keyBlock, _ := pem.Decode(keyFileContent) - if keyBlock == nil { - log.Fatal("Failed to decode PEM block containing the public key.") + pemData := pem.EncodeToMemory(pemBlock) + fmt.Print(string(pemData)) + xval := new(big.Int).Set(priv.X) + fmt.Println("PrivateKey(x):") + x := fmt.Sprintf("%x", xval) + splitz := SplitSubN(x, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Prime(p):") + p := fmt.Sprintf("%x", priv.P) + splitz = SplitSubN(p, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Generator(g):") + g := fmt.Sprintf("%x", priv.G) + splitz = SplitSubN(g, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("PublicKey(Y):") + publicKey := setup(priv.X, priv.G, priv.P) + pub := fmt.Sprintf("%x", publicKey) + splitz = SplitSubN(pub, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + os.Exit(0) } - - pubKey := new(sm9.SignMasterPublicKey) - err = pubKey.UnmarshalASN1(keyBlock.Bytes) - if err != nil { - fmt.Println("Error parsing public key with UnmarshalASN1:", err) + if *pkey == "text" && *key != "" && blockType == "ELGAMAL PUBLIC KEY" { + pemData, err := ioutil.ReadFile(*key) + if err != nil { + fmt.Println("Error reading PEM file:", err) + return + } + fmt.Print(string(pemData)) + publicKeyVal, err := readPublicKeyFromPEM(*key) + if err != nil { + fmt.Println("Error: Invalid public key value") + return + } + fmt.Println("Public Key Parameters:") + fmt.Println("Prime(p):") + p := fmt.Sprintf("%x", publicKeyVal.P) + splitz := SplitSubN(p, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Generator(g):") + g := fmt.Sprintf("%x", publicKeyVal.G) + splitz = SplitSubN(g, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("PublicKey(Y):") + y := fmt.Sprintf("%x", publicKeyVal.Y) + splitz = SplitSubN(y, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } return } - - fmt.Printf("Public=%X\n", pubKey.MasterPublicKey.Marshal()) - os.Exit(0) - } - - if *pkey == "modulus" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { - keyFileContent, err := ioutil.ReadFile(*key) - if err != nil { - log.Fatal("Error reading key file:", err) - } - - keyBlock, _ := pem.Decode(keyFileContent) - if keyBlock == nil { - log.Fatal("Failed to decode PEM block containing the public key.") + if *pkey == "modulus" && blockType == "ELGAMAL PRIVATE KEY" { + privKey, err := readPrivateKeyFromPEM(*key) + if err != nil { + fmt.Println("Error reading private key:", err) + return + } + publicKey := setup(privKey.X, privKey.G, privKey.P) + fmt.Printf("Y=%X\n", publicKey) + return } - - pubKey := new(sm9.EncryptMasterPublicKey) - err = pubKey.UnmarshalASN1(keyBlock.Bytes) - if err != nil { - fmt.Println("Error parsing public key with UnmarshalASN1:", err) + if *pkey == "modulus" && blockType == "ELGAMAL PUBLIC KEY" { + publicKey, err := readPublicKeyFromPEM(*key) + if err != nil { + fmt.Println("Error reading public key:", err) + return + } + fmt.Printf("Y=%X\n", publicKey.Y) return } + if *pkey == "wrapkey" { + publicKeyVal, err := readPublicKeyFromPEM(*key) + if err != nil { + fmt.Println("Error: Invalid public key value") + return + } - fmt.Printf("Public=%X\n", pubKey.MasterPublicKey.Marshal()) - os.Exit(0) - } + pub := &PublicKey{ + G: publicKeyVal.G, + P: publicKeyVal.P, + Y: publicKeyVal.Y, + } - if *pkey == "text" && (strings.ToUpper(*alg) == "SM9SIGN" || strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Master" || PEM == "Private") { - keyFileContent, err := ioutil.ReadFile(*key) - if err != nil { - log.Fatal("Error reading key file:", err) - } + messageBytes := make([]byte, *length/8) + _, err = rand.Read(messageBytes) + if err != nil { + fmt.Println("Error generating random key:", err) + return + } + c, err := encrypt(rand.Reader, pub, messageBytes) + if err != nil { + fmt.Println("Error encrypting message:", err) + return + } - keyBlock, _ := pem.Decode(keyFileContent) - if keyBlock == nil { - log.Fatal("Failed to decode PEM block containing the private key.") + fmt.Printf("Cipher= %s\n", c) + fmt.Printf("Shared= %x\n", messageBytes) + os.Exit(0) } + if *pkey == "unwrapkey" { + if *key == "" { + fmt.Println("Error: Private key file not provided for unwrapping.") + return + } - var privPEM []byte - var privateKeyPemBlock *pem.Block - - var privKeyBytes []byte - if IsEncryptedPEMBlock(keyBlock) { - privKeyBytes, err = DecryptPEMBlock(keyBlock, []byte(*pwd)) + priv, err := readPrivateKeyFromPEM(*key) if err != nil { - log.Fatal(err) - } - if PEM == "Master" && strings.ToUpper(*alg) == "SM9ENCRYPT" { - privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 ENC MASTER KEY", Bytes: privKeyBytes}) - } else if PEM == "Master" && strings.ToUpper(*alg) == "SM9SIGN" { - privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN MASTER KEY", Bytes: privKeyBytes}) - } else if PEM == "Private" && strings.ToUpper(*alg) == "SM9ENCRYPT" { - privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 ENC PRIVATE KEY", Bytes: privKeyBytes}) - } else if PEM == "Private" && strings.ToUpper(*alg) == "SM9SIGN" { - privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN PRIVATE KEY", Bytes: privKeyBytes}) + fmt.Println("Error reading private key:", err) + return } - } else { - privPEM = keyFileContent - } - privateKeyPemBlock, _ = pem.Decode(privPEM) - privateKey, err := smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) - if err != nil { - log.Fatal("Error parsing private key:", err) + ciphertext := *cph + message, err := decrypt(priv, ciphertext) + if err != nil { + fmt.Println("Error decrypting message:", err) + return + } + fmt.Printf("Shared= %x\n", message) } + if *pkey == "text" { + readParams, err := readSchnorrParamsFromPEM(*params) + if err != nil { + fmt.Println("Error reading Schnorr parameters from PEM file:", err) + return + } - fmt.Print(string(privPEM)) - switch keyType := privateKey.(type) { - case *sm9.EncryptPrivateKey: - fmt.Println("Encrypt Private-Key: (256-bit)") - fmt.Println("pub:") - pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) - splitz := SplitSubN(pubKeyHex, 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + pemData, err := ioutil.ReadFile(*params) + if err != nil { + fmt.Println("Error reading PEM file:", err) + return } - fmt.Println("Curve: sm9p256v1") - case *sm9.SignPrivateKey: - fmt.Println("Sign Private-Key: (256-bit)") - fmt.Println("pub:") - pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) - splitz := SplitSubN(pubKeyHex, 2) + fmt.Print(string(pemData)) + fmt.Println("Schnorr Parameters:") + fmt.Println("Prime(p):") + p := fmt.Sprintf("%x", readParams.P) + splitz := SplitSubN(p, 2) for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) } - fmt.Println("Curve: sm9p256v1") - case *sm9.EncryptMasterPrivateKey: - fmt.Println("Encrypt Master-Key: (256-bit)") - fmt.Println("pub:") - pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) - splitz := SplitSubN(pubKeyHex, 2) + fmt.Println("Order(q):") + q := fmt.Sprintf("%x", readParams.Q) + splitz = SplitSubN(q, 2) for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) } - fmt.Println("Curve: sm9p256v1") - case *sm9.SignMasterPrivateKey: - fmt.Println("Sign Master-Key: (256-bit)") - fmt.Println("pub:") - pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) - splitz := SplitSubN(pubKeyHex, 2) + fmt.Println("Generator(g):") + g := fmt.Sprintf("%x", readParams.G) + splitz = SplitSubN(g, 2) for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) } - fmt.Println("Curve: sm9p256v1") - default: - log.Fatal("Invalid private key type. Expected sm9.EncryptPrivateKey, or sm9.SignPrivateKey.") - } - } - - if *pkey == "text" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { - keyFileContent, err := ioutil.ReadFile(*key) - if err != nil { - log.Fatal("Error reading key file:", err) + os.Exit(0) } + if *pkey == "keygen" { + var xval *big.Int + var path string - keyBlock, _ := pem.Decode(keyFileContent) - if keyBlock == nil { - log.Fatal("Failed to decode PEM block containing the public key.") - } + readParams, err := readSchnorrParamsFromPEM(*params) + if err != nil { + log.Fatal("Error reading Schnorr parameters from PEM file:", err) + return + } - pubKey := new(sm9.SignMasterPublicKey) - err = pubKey.UnmarshalASN1(keyBlock.Bytes) - if err != nil { - fmt.Println("Error parsing public key with UnmarshalASN1:", err) - return - } + if *key == "" { + xval, err = generateRandomX(readParams.P) + if err != nil { + log.Fatal("Error generating x:", err) + return + } + path, err = filepath.Abs(*priv) + privateKey := &PrivateKey{ + X: xval, + P: readParams.P, + G: readParams.G, + } + if err := savePrivateKeyToPEM(*priv, privateKey); err != nil { + log.Fatal("Error saving private key:", err) + return + } + fmt.Fprintf(os.Stderr, "Private Key save to: %s\n", path) + } else { + priv, err := readPrivateKeyFromPEM(*key) + if err != nil { + log.Fatal("Error reading private key:", err) + return + } + xval = new(big.Int).Set(priv.X) + } - fmt.Print(string(keyFileContent)) - fmt.Println("Sign Public-Key: (256-bit)") - fmt.Println("pub:") - pubKeyHex := fmt.Sprintf("%x", pubKey.MasterPublicKey.Marshal()) - splitz := SplitSubN(pubKeyHex, 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Println("Curve: sm9p256v1") - os.Exit(0) - } + publicKey := setup(xval, readParams.G, readParams.P) - if *pkey == "text" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { - keyFileContent, err := ioutil.ReadFile(*key) - if err != nil { - log.Fatal("Error reading key file:", err) - } + path, err = filepath.Abs(*pub) + fmt.Fprintf(os.Stderr, "Public Key save to: %s\n", path) + if err := savePublicKeyToPEM(*pub, &PublicKey{Y: publicKey, G: readParams.G, P: readParams.P}); err != nil { + log.Fatal("Error saving public key:", err) + return + } - keyBlock, _ := pem.Decode(keyFileContent) - if keyBlock == nil { - log.Fatal("Failed to decode PEM block containing the public key.") - } + fingerprint := calculateFingerprint(publicKey.Bytes()) + fmt.Fprintf(os.Stderr, "Fingerprint: %s\n", fingerprint) + + primeBitLength := readParams.P.BitLen() + fmt.Fprintf(os.Stderr, "ElGamal (%d-bits)\n", primeBitLength) + + file, err := os.Open(*pub) + if err != nil { + log.Fatal(err) + } + + info, err := file.Stat() + if err != nil { + log.Fatal(err) + } + + buf := make([]byte, info.Size()) + file.Read(buf) + randomArt := randomart.FromString(string(buf)) + fmt.Fprintln(os.Stderr, randomArt) - pubKey := new(sm9.EncryptMasterPublicKey) - err = pubKey.UnmarshalASN1(keyBlock.Bytes) - if err != nil { - fmt.Println("Error parsing public key with UnmarshalASN1:", err) return } + if *pkey == "sign" { + message, err := ioutil.ReadAll(inputfile) + if err != nil { + fmt.Println("Error reading file:", err) + return + } - fmt.Print(string(keyFileContent)) - fmt.Println("Encrypt Public-Key: (256-bit)") - fmt.Println("pub:") - pubKeyHex := fmt.Sprintf("%x", pubKey.MasterPublicKey.Marshal()) - splitz := SplitSubN(pubKeyHex, 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Println("Curve: sm9p256v1") - os.Exit(0) - } + priv, err := readPrivateKeyFromPEM(*key) + if err != nil { + fmt.Println("Error reading private key:", err) + return + } - if *pkey == "randomart" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) - } - buf := make([]byte, info.Size()) - file.Read(buf) - randomArt := randomart.FromString(string(buf)) - fmt.Fprintln(os.Stderr, "SM9 Sign (256-bit)") - println(randomArt) - os.Exit(0) - } + sign, err := sign(priv, message, myHash) + if err != nil { + log.Fatal("Error signing message:", err) + return + } - if *pkey == "randomart" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) + fmt.Println("EG-"+strings.ToUpper(*md)+"("+inputdesc+")=", sign) } - buf := make([]byte, info.Size()) - file.Read(buf) - randomArt := randomart.FromString(string(buf)) - fmt.Fprintln(os.Stderr, "SM9 Enc (256-bit)") - println(randomArt) - os.Exit(0) - } + if *pkey == "verify" { + message, err := ioutil.ReadAll(inputfile) + if err != nil { + fmt.Println("Error reading file:", err) + return + } - if *pkey == "fingerprint" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) - } - buf := make([]byte, info.Size()) - file.Read(buf) - fingerprint := calculateFingerprint(buf) - print("Fingerprint= ") - println(fingerprint) - os.Exit(0) - } + if *key == "" { + fmt.Println("Error: Public key file not provided for verification.") + return + } - if *pkey == "fingerprint" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) + publicKeyVal, err := readPublicKeyFromPEM(*key) + if err != nil { + fmt.Println("Error: Invalid public key value") + return + } + + pub := &PublicKey{ + G: publicKeyVal.G, + P: publicKeyVal.P, + Y: publicKeyVal.Y, + } + + isValid := verify(pub, message, *sig, myHash) + fmt.Println("Verified:", isValid) } - buf := make([]byte, info.Size()) - file.Read(buf) - fingerprint := calculateFingerprint(buf) - print("Fingerprint= ") - println(fingerprint) - os.Exit(0) } - if *pkey == "certgen" && strings.ToUpper(*alg) == "GOST2012" { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) + if (strings.ToUpper(*alg) == "EC-ELGAMAL") && (*pkey == "keygen" || *pkey == "wrapkey" || *pkey == "unwrapkey" || *pkey == "text" || *pkey == "modulus" || *pkey == "fingerprint" || *pkey == "randomart") { + var blockType string + if *key != "" { + pemData, err := ioutil.ReadFile(*key) + if err != nil { + fmt.Println("Error reading PEM file:", err) + return + } + block, _ := pem.Decode(pemData) + if block == nil { + fmt.Println("Error decoding PEM block") + return + } + blockType = block.Type } - buf := make([]byte, info.Size()) - file.Read(buf) + if *pkey == "text" && *key != "" && blockType == "EC-ELGAMAL ENCRYPTION KEY" { + keyBytes, err := readKeyFromPEM(*key, false) + if err != nil { + fmt.Println("Error reading key from PEM:", err) + return + } + pubKeyPEM := pem.Block{Type: "EC-ELGAMAL ENCRYPTION KEY", Bytes: keyBytes} + keyPEMText := string(pem.EncodeToMemory(&pubKeyPEM)) + fmt.Print(keyPEMText) + fmt.Println("EncryptionKey:") + p := fmt.Sprintf("%x", keyBytes) + splitz := SplitSubN(p, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + os.Exit(0) + } else if *pkey == "text" && *key != "" && blockType == "EC-ELGAMAL DECRYPTION KEY" { + keyBytes, err := ioutil.ReadFile(*key) + if err != nil { + log.Fatal(err) + } - var priv interface{} + block, _ := pem.Decode(keyBytes) + if block == nil { + log.Fatal(err) + } - var block *pem.Block - block, _ = pem.Decode(buf) + curve, ok := block.Headers["Curve"] + if !ok { + fmt.Println("Curve not found in headers.") + } - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) + keyBytes, err = readKeyFromPEM(*key, true) if err != nil { - log.Fatal(err) + fmt.Println("Error reading key from PEM:", err) + return } - priv, err = x509.ParsePKCS8PrivateKey(privKeyBytes) + privKeyPEM := pem.Block{ + Type: "EC-ELGAMAL DECRYPTION KEY", + Bytes: keyBytes, + Headers: map[string]string{ + "Curve": curve, + }, + } + keyPEMText := string(pem.EncodeToMemory(&privKeyPEM)) + fmt.Print(keyPEMText) + + dk := new(elgamal.DecryptionKey) + + err = dk.UnmarshalBinary(keyBytes) if err != nil { - log.Fatal(err) + fmt.Println("Error decoding private key:", err) + return } - } else { - priv, err = x509.ParsePKCS8PrivateKey(block.Bytes) + ek := dk.EncryptionKey() + pubBytes, _ := ek.MarshalBinary() + + fmt.Println("DecryptionKey:") + prv := fmt.Sprintf("%x", keyBytes) + splitz := SplitSubN(prv, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("EncryptionKey:") + pub := fmt.Sprintf("%x", pubBytes) + splitz = SplitSubN(pub, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + os.Exit(0) + } + if *pkey == "modulus" && *key != "" && blockType == "EC-ELGAMAL ENCRYPTION KEY" { + keyBytes, err := readKeyFromPEM(*key, false) if err != nil { - log.Fatal(err) + fmt.Println("Error reading key from PEM:", err) + return + } + fmt.Printf("Pub=%x\n", keyBytes) + os.Exit(0) + } + if *pkey == "modulus" && *key != "" && blockType == "EC-ELGAMAL DECRYPTION KEY" { + keyBytes, err := readKeyFromPEM(*key, true) + if err != nil { + fmt.Println("Error reading key from PEM:", err) + return + } + dk := new(elgamal.DecryptionKey) + err = dk.UnmarshalBinary(keyBytes) + if err != nil { + fmt.Println("Error decoding private key:", err) + return + } + ek := dk.EncryptionKey() + pubBytes, _ := ek.MarshalBinary() + fmt.Printf("Pub=%x\n", pubBytes) + os.Exit(0) + } + if *pkey == "fingerprint" && *key != "" { + keyBytes, err := readKeyFromPEM(*key, false) + if err != nil { + fmt.Println("Error reading key from PEM:", err) + return } + fingerprint := calculateFingerprint(keyBytes) + fmt.Printf("Fingerprint: %s\n", fingerprint) + os.Exit(0) } + if *pkey == "randomart" && *key != "" { + fmt.Printf("EC-ElGamal (256-bit)\n") - gost341012256Priv := priv.(*gost3410.PrivateKey) - gost341012256Pub := gost341012256Priv.Public() + pubFile, err := os.Open(*pub) + if err != nil { + fmt.Println("Error opening public key file:", err) + return + } + defer pubFile.Close() - keyUsage := x509.KeyUsageDigitalSignature + pubInfo, err := pubFile.Stat() + if err != nil { + fmt.Println("Error getting public key file info:", err) + return + } - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 160) - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - log.Fatalf("Failed to generate serial number: %v", err) + pubBuf := make([]byte, pubInfo.Size()) + pubFile.Read(pubBuf) + randomArt := randomart.FromString(string(pubBuf)) + fmt.Println(randomArt) + os.Exit(0) } + if *pkey == "keygen" { + var curve *curves.Curve + switch strings.ToUpper(*curveFlag) { + case "BLS12381G1": + curve = curves.BLS12381G1() + case "BLS12381G2": + curve = curves.BLS12381G2() + case "P256", "ECDSA", "EC", "SECP256R1": + curve = curves.P256() + case "K256", "KOBLITZ", "SECP256K1": + curve = curves.K256() + default: + fmt.Println("Unsupported curve:", *curveFlag) + return + } + ek, dk, _ := elgamal.NewKeys(curve) - println("You are about to be asked to enter information \nthat will be incorporated into your certificate.") + privBytes, _ := dk.MarshalBinary() + pubBytes, _ := ek.MarshalBinary() - scanner := bufio.NewScanner(os.Stdin) + privKeyPEM := pem.Block{Type: "EC-ELGAMAL DECRYPTION KEY", Bytes: privBytes} + privKeyPEM.Headers = map[string]string{"Curve": strings.ToUpper(*curveFlag)} - print("Common Name: ") - scanner.Scan() - name := scanner.Text() + pubKeyPEM := pem.Block{Type: "EC-ELGAMAL ENCRYPTION KEY", Bytes: pubBytes} - print("Country Name (2 letter code) [AU]: ") - scanner.Scan() - country := scanner.Text() + savePEMToFile(*priv, &privKeyPEM, true) + privPath, err := filepath.Abs(*priv) + if err != nil { + fmt.Println("Error getting absolute path for private key:", err) + return + } + fmt.Printf("Private Key saved to: %s\n", privPath) - print("State or Province Name (full name) [Some-State]: ") - scanner.Scan() - province := scanner.Text() + savePEMToFile(*pub, &pubKeyPEM, false) + pubPath, err := filepath.Abs(*pub) + if err != nil { + fmt.Println("Error getting absolute path for public key:", err) + return + } + fmt.Printf("Public Key saved to: %s\n", pubPath) - print("Locality Name (eg, city): ") - scanner.Scan() - locality := scanner.Text() + fingerprint := calculateFingerprint(pubBytes) + fmt.Printf("Fingerprint: %s\n", fingerprint) - print("Organization Name (eg, company) [Internet Widgits Pty Ltd]: ") - scanner.Scan() - organization := scanner.Text() + fmt.Printf("EC-ElGamal (256-bit)\n") - print("Organizational Unit Name (eg, section): ") - scanner.Scan() - organizationunit := scanner.Text() + pubFile, err := os.Open(*pub) + if err != nil { + fmt.Println("Error opening public key file:", err) + return + } + defer pubFile.Close() - print("Email Address []: ") - scanner.Scan() - email := scanner.Text() + pubInfo, err := pubFile.Stat() + if err != nil { + fmt.Println("Error getting public key file info:", err) + return + } - print("StreetAddress: ") - scanner.Scan() - street := scanner.Text() + pubBuf := make([]byte, pubInfo.Size()) + pubFile.Read(pubBuf) + randomArt := randomart.FromString(string(pubBuf)) + fmt.Println(randomArt) - print("PostalCode: ") - scanner.Scan() - postalcode := scanner.Text() + os.Exit(0) + } else { + if *pkey == "unwrapkey" { + if *key == "" { + fmt.Println("A key is required for decryption.") + return + } - print("SerialNumber: ") - scanner.Scan() - number := scanner.Text() + keyBytes, err := readKeyFromPEM(*key, true) + if err != nil { + fmt.Println("Error reading key from PEM:", err) + return + } - print("Validity (in Days): ") - scanner.Scan() - validity := scanner.Text() + domain := []byte(*id) + dk := new(elgamal.DecryptionKey) - intVar, err := strconv.Atoi(validity) - NotAfter := time.Now().AddDate(0, 0, intVar) + err = dk.UnmarshalBinary(keyBytes) + if err != nil { + fmt.Println("Error decoding private key:", err) + return + } - hasher := gost34112012256.New() - if _, err = hasher.Write(gost341012256Pub.(*gost3410.PublicKey).Raw()); err != nil { - log.Fatalln(err) - } - spki := hasher.Sum(nil) - spki = spki[:20] + ciphertextBytes, err := hex.DecodeString(*cph) + if err != nil { + fmt.Println("Error decoding ciphertext:", err) + return + } - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - CommonName: name, - SerialNumber: number, - Country: []string{country}, - Province: []string{province}, - Locality: []string{locality}, - Organization: []string{organization}, - OrganizationalUnit: []string{organizationunit}, - StreetAddress: []string{street}, - PostalCode: []string{postalcode}, - }, - EmailAddresses: []string{email}, - SubjectKeyId: spki, - AuthorityKeyId: spki, + cs := new(elgamal.CipherText) - NotBefore: time.Now(), - NotAfter: NotAfter, + err = cs.UnmarshalBinary(ciphertextBytes) + if err != nil { + fmt.Println("Error decoding ciphertext:", err) + return + } - KeyUsage: keyUsage, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - IsCA: true, - PermittedDNSDomainsCritical: true, - DNSNames: []string{name}, + dbytes, _, err := dk.VerifiableDecryptWithDomain(domain, cs) + if err != nil { + fmt.Println("Error decrypting:", err) + return + } + fmt.Printf("Shared= %x\n", dbytes) + os.Exit(0) + } else { + if *key == "" { + fmt.Println("A key is required for encryption.") + return + } - /* - PermittedDNSDomainsCritical: true, - DNSNames: []string{ip.String()}, - IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, - */ - } + keyBytes, err := readKeyFromPEM(*key, false) + if err != nil { + fmt.Println("Error reading key from PEM:", err) + return + } - template.IsCA = true - template.KeyUsage |= x509.KeyUsageContentCommitment | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement | x509.KeyUsageCertSign | x509.KeyUsageCRLSign + domain := []byte(*id) + ek := new(elgamal.EncryptionKey) - derBytes, err := x509.CreateCertificate( - rand.Reader, - &template, &template, - gost341012256Pub, &gost3410.PrivateKeyReverseDigest{Prv: gost341012256Priv}, - ) - if err != nil { - log.Println(err) - } + err = ek.UnmarshalBinary(keyBytes) + if err != nil { + fmt.Println("Error decoding public key:", err) + return + } - certfile, err := os.Create(*cert) - if err != nil { - log.Println(err) + msgBytes := make([]byte, *length/8) + _, err = rand.Read(msgBytes) + if err != nil { + return + } + + cs, proof, err := ek.VerifiableEncrypt(msgBytes, &elgamal.EncryptParams{ + Domain: domain, + MessageIsHashed: true, + GenProof: true, + ProofNonce: domain, + }) + + if err != nil { + fmt.Println("Error encrypting:", err) + return + } + + res3, _ := cs.MarshalBinary() + + fmt.Fprint(os.Stderr, "Verified: ") + rtn := ek.VerifyDomainEncryptProof(domain, cs, proof) + if rtn == nil { + fmt.Fprintln(os.Stderr, "true") + } else { + fmt.Fprintln(os.Stderr, "false") + } + fmt.Printf("Cipher= %x\n", res3) + fmt.Printf("Shared= %x\n", msgBytes) + os.Exit(0) + } } - pem.Encode(certfile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - os.Exit(0) } - if *pkey == "req" && *key != "" && strings.ToUpper(*alg) == "GOST2012" { - file, err := os.Open(*key) + if *pkey == "modulus" && (strings.ToUpper(*alg) == "SM9SIGN" || strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Master" || PEM == "Private") { + keyFileContent, err := ioutil.ReadFile(*key) if err != nil { - log.Fatal(err) + log.Fatal("Error reading key file:", err) } - info, err := file.Stat() - if err != nil { - log.Fatal(err) + + keyBlock, _ := pem.Decode(keyFileContent) + if keyBlock == nil { + log.Fatal("Failed to decode PEM block containing the private key.") } - buf := make([]byte, info.Size()) - file.Read(buf) - var block *pem.Block - block, _ = pem.Decode(buf) + var privPEM []byte - var priva interface{} - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) - if err != nil { - log.Fatal(err) - } - priva, err = x509.ParsePKCS8PrivateKey(privKeyBytes) + if IsEncryptedPEMBlock(keyBlock) { + privKeyBytes, err := DecryptPEMBlock(keyBlock, []byte(*pwd)) if err != nil { - log.Fatal(err) + log.Fatal("Error decrypting private key:", err) } + privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 PRIVATE KEY", Bytes: privKeyBytes}) } else { - priva, err = x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - log.Fatal(err) - } + privPEM = keyFileContent } - println("You are about to be asked to enter information that \nwill be incorporated into your certificate request.") - - scanner := bufio.NewScanner(os.Stdin) + var privateKeyPemBlock *pem.Block + privateKeyPemBlock, _ = pem.Decode(privPEM) - print("Common Name: ") - scanner.Scan() - name := scanner.Text() + privateKey, err := smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) + if err != nil { + log.Fatal("Error parsing private key:", err) + } - print("Country Name (2 letter code) [AU]: ") - scanner.Scan() - country := scanner.Text() + switch keyType := privateKey.(type) { + case *sm9.EncryptPrivateKey: + fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) + case *sm9.SignPrivateKey: + fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) + case *sm9.EncryptMasterPrivateKey: + fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) + case *sm9.SignMasterPrivateKey: + fmt.Printf("Public=%X\n", keyType.MasterPublicKey.Marshal()) + default: + log.Fatal("Invalid private key type. Expected sm9.EncryptPrivateKey, or sm9.SignPrivateKey.") + } + } - print("State or Province Name (full name) [Some-State]: ") - scanner.Scan() - province := scanner.Text() + if *pkey == "modulus" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { + keyFileContent, err := ioutil.ReadFile(*key) + if err != nil { + log.Fatal("Error reading key file:", err) + } - print("Locality Name (eg, city): ") - scanner.Scan() - locality := scanner.Text() + keyBlock, _ := pem.Decode(keyFileContent) + if keyBlock == nil { + log.Fatal("Failed to decode PEM block containing the public key.") + } - print("Organization Name (eg, company) [Internet Widgits Pty Ltd]: ") - scanner.Scan() - organization := scanner.Text() + pubKey := new(sm9.SignMasterPublicKey) + err = pubKey.UnmarshalASN1(keyBlock.Bytes) + if err != nil { + fmt.Println("Error parsing public key with UnmarshalASN1:", err) + return + } - print("Organizational Unit Name (eg, section): ") - scanner.Scan() - organizationunit := scanner.Text() + fmt.Printf("Public=%X\n", pubKey.MasterPublicKey.Marshal()) + os.Exit(0) + } - print("Email Address []: ") - scanner.Scan() - email := scanner.Text() + if *pkey == "modulus" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { + keyFileContent, err := ioutil.ReadFile(*key) + if err != nil { + log.Fatal("Error reading key file:", err) + } - print("StreetAddress: ") - scanner.Scan() - street := scanner.Text() + keyBlock, _ := pem.Decode(keyFileContent) + if keyBlock == nil { + log.Fatal("Failed to decode PEM block containing the public key.") + } - print("PostalCode: ") - scanner.Scan() - postalcode := scanner.Text() + pubKey := new(sm9.EncryptMasterPublicKey) + err = pubKey.UnmarshalASN1(keyBlock.Bytes) + if err != nil { + fmt.Println("Error parsing public key with UnmarshalASN1:", err) + return + } - print("SerialNumber: ") - scanner.Scan() - number := scanner.Text() + fmt.Printf("Public=%X\n", pubKey.MasterPublicKey.Marshal()) + os.Exit(0) + } - var sigalg x509.SignatureAlgorithm - if *length == 512 { - sigalg = x509.GOST512 - } else { - sigalg = x509.GOST256 + if *pkey == "text" && (strings.ToUpper(*alg) == "SM9SIGN" || strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Master" || PEM == "Private") { + keyFileContent, err := ioutil.ReadFile(*key) + if err != nil { + log.Fatal("Error reading key file:", err) } - emailAddress := email - subj := pkix.Name{ - CommonName: name, - SerialNumber: number, - Country: []string{country}, - Province: []string{province}, - Locality: []string{locality}, - Organization: []string{organization}, - OrganizationalUnit: []string{organizationunit}, - StreetAddress: []string{street}, - PostalCode: []string{postalcode}, + keyBlock, _ := pem.Decode(keyFileContent) + if keyBlock == nil { + log.Fatal("Failed to decode PEM block containing the private key.") } - rawSubj := subj.ToRDNSequence() - rawSubj = append(rawSubj, []pkix.AttributeTypeAndValue{ - {Type: oidEmailAddress, Value: emailAddress}, - }) - asn1Subj, _ := asn1.Marshal(rawSubj) - var template x509.CertificateRequest + var privPEM []byte + var privateKeyPemBlock *pem.Block - template = x509.CertificateRequest{ - RawSubject: asn1Subj, - EmailAddresses: []string{emailAddress}, - SignatureAlgorithm: sigalg, - } - - var output *os.File - if *cert == "" { - output = os.Stdout - } else { - file, err := os.Create(*cert) + var privKeyBytes []byte + if IsEncryptedPEMBlock(keyBlock) { + privKeyBytes, err = DecryptPEMBlock(keyBlock, []byte(*pwd)) if err != nil { log.Fatal(err) } - defer file.Close() - output = file + if PEM == "Master" && strings.ToUpper(*alg) == "SM9ENCRYPT" { + privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 ENC MASTER KEY", Bytes: privKeyBytes}) + } else if PEM == "Master" && strings.ToUpper(*alg) == "SM9SIGN" { + privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN MASTER KEY", Bytes: privKeyBytes}) + } else if PEM == "Private" && strings.ToUpper(*alg) == "SM9ENCRYPT" { + privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 ENC PRIVATE KEY", Bytes: privKeyBytes}) + } else if PEM == "Private" && strings.ToUpper(*alg) == "SM9SIGN" { + privPEM = pem.EncodeToMemory(&pem.Block{Type: "SM9 SIGN PRIVATE KEY", Bytes: privKeyBytes}) + } + } else { + privPEM = keyFileContent } - csrBytes, _ := x509.CreateCertificateRequest(rand.Reader, &template, &gost3410.PrivateKeyReverseDigest{Prv: priva.(*gost3410.PrivateKey)}) - pem.Encode(output, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) + privateKeyPemBlock, _ = pem.Decode(privPEM) + + privateKey, err := smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) + if err != nil { + log.Fatal("Error parsing private key:", err) + } + + fmt.Print(string(privPEM)) + switch keyType := privateKey.(type) { + case *sm9.EncryptPrivateKey: + fmt.Println("Encrypt Private-Key: (256-bit)") + fmt.Println("pub:") + pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) + splitz := SplitSubN(pubKeyHex, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Curve: sm9p256v1") + case *sm9.SignPrivateKey: + fmt.Println("Sign Private-Key: (256-bit)") + fmt.Println("pub:") + pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) + splitz := SplitSubN(pubKeyHex, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Curve: sm9p256v1") + case *sm9.EncryptMasterPrivateKey: + fmt.Println("Encrypt Master-Key: (256-bit)") + fmt.Println("pub:") + pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) + splitz := SplitSubN(pubKeyHex, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Curve: sm9p256v1") + case *sm9.SignMasterPrivateKey: + fmt.Println("Sign Master-Key: (256-bit)") + fmt.Println("pub:") + pubKeyHex := fmt.Sprintf("%x", keyType.MasterPublicKey.Marshal()) + splitz := SplitSubN(pubKeyHex, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Curve: sm9p256v1") + default: + log.Fatal("Invalid private key type. Expected sm9.EncryptPrivateKey, or sm9.SignPrivateKey.") + } + } + + if *pkey == "text" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { + keyFileContent, err := ioutil.ReadFile(*key) + if err != nil { + log.Fatal("Error reading key file:", err) + } + + keyBlock, _ := pem.Decode(keyFileContent) + if keyBlock == nil { + log.Fatal("Failed to decode PEM block containing the public key.") + } + + pubKey := new(sm9.SignMasterPublicKey) + err = pubKey.UnmarshalASN1(keyBlock.Bytes) + if err != nil { + fmt.Println("Error parsing public key with UnmarshalASN1:", err) + return + } + + fmt.Print(string(keyFileContent)) + fmt.Println("Sign Public-Key: (256-bit)") + fmt.Println("pub:") + pubKeyHex := fmt.Sprintf("%x", pubKey.MasterPublicKey.Marshal()) + splitz := SplitSubN(pubKeyHex, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Curve: sm9p256v1") os.Exit(0) } - if (*tcpip == "server" || *tcpip == "client") && strings.ToUpper(*alg) == "GOST2012" { - var certPEM []byte - var privPEM []byte + if *pkey == "text" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { + keyFileContent, err := ioutil.ReadFile(*key) + if err != nil { + log.Fatal("Error reading key file:", err) + } - tls.GOSTInstall() + keyBlock, _ := pem.Decode(keyFileContent) + if keyBlock == nil { + log.Fatal("Failed to decode PEM block containing the public key.") + } + + pubKey := new(sm9.EncryptMasterPublicKey) + err = pubKey.UnmarshalASN1(keyBlock.Bytes) + if err != nil { + fmt.Println("Error parsing public key with UnmarshalASN1:", err) + return + } + + fmt.Print(string(keyFileContent)) + fmt.Println("Encrypt Public-Key: (256-bit)") + fmt.Println("pub:") + pubKeyHex := fmt.Sprintf("%x", pubKey.MasterPublicKey.Marshal()) + splitz := SplitSubN(pubKeyHex, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Println("Curve: sm9p256v1") + os.Exit(0) + } + if *pkey == "randomart" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { file, err := os.Open(*key) if err != nil { - log.Println(err) + log.Fatal(err) } info, err := file.Stat() if err != nil { - log.Println(err) + log.Fatal(err) } buf := make([]byte, info.Size()) file.Read(buf) + randomArt := randomart.FromString(string(buf)) + fmt.Fprintln(os.Stderr, "SM9 Sign (256-bit)") + println(randomArt) + os.Exit(0) + } - var block *pem.Block - block, _ = pem.Decode(buf) + if *pkey == "randomart" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) + } + buf := make([]byte, info.Size()) + file.Read(buf) + randomArt := randomart.FromString(string(buf)) + fmt.Fprintln(os.Stderr, "SM9 Enc (256-bit)") + println(randomArt) + os.Exit(0) + } - if block == nil { - errors.New("no valid private key found") + if *pkey == "fingerprint" && (strings.ToUpper(*alg) == "SM9SIGN") && (PEM == "Public") { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) } + buf := make([]byte, info.Size()) + file.Read(buf) + fingerprint := calculateFingerprint(buf) + print("Fingerprint= ") + println(fingerprint) + os.Exit(0) + } - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) - if err != nil { - log.Println(err) - } - privPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privKeyBytes}) - } else { - privPEM = buf + if *pkey == "fingerprint" && (strings.ToUpper(*alg) == "SM9ENCRYPT") && (PEM == "Public") { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) } + buf := make([]byte, info.Size()) + file.Read(buf) + fingerprint := calculateFingerprint(buf) + print("Fingerprint= ") + println(fingerprint) + os.Exit(0) + } - file, err = os.Open(*cert) + if *pkey == "certgen" && strings.ToUpper(*alg) == "GOST2012" { + file, err := os.Open(*key) if err != nil { - log.Println(err) + log.Fatal(err) } - info, err = file.Stat() + info, err := file.Stat() if err != nil { - log.Println(err) + log.Fatal(err) } - buf = make([]byte, info.Size()) + buf := make([]byte, info.Size()) file.Read(buf) - certPEM = buf - if *tcpip == "server" { - cert, err := tls.X509KeyPair(certPEM, privPEM) - cfg := tls.Config{Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAnyClientCert, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13} - cfg.Rand = rand.Reader + var priv interface{} - port := "8081" - if *iport != "" { - port = *iport - } + var block *pem.Block + block, _ = pem.Decode(buf) - ln, err := tls.Listen("tcp", ":"+port, &cfg) + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) if err != nil { log.Fatal(err) } - - fmt.Fprintln(os.Stderr, "Server(TLS) up and listening on port "+port) - - conn, err := ln.Accept() + priv, err = x509.ParsePKCS8PrivateKey(privKeyBytes) if err != nil { - log.Println(err) + log.Fatal(err) } - defer ln.Close() - - tlscon := conn.(*tls.Conn) - err = tlscon.Handshake() + } else { + priv, err = x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { - log.Fatalf("server: handshake failed: %s", err) - } else { - log.Print("server: conn: Handshake completed") + log.Fatal(err) } - state := tlscon.ConnectionState() + } - for _, v := range state.PeerCertificates { - derBytes, err := x509.MarshalPKIXPublicKey(v.PublicKey) - if err != nil { - log.Fatal(err) - } - pubPEM := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: derBytes}) - fmt.Printf("%s\n", pubPEM) - } - - go handleConnectionTLS(conn) - fmt.Println("Connection accepted") + gost341012256Priv := priv.(*gost3410.PrivateKey) + gost341012256Pub := gost341012256Priv.Public() - for { - message, err := bufio.NewReader(conn).ReadString('\n') - if err != nil { - fmt.Println(err) - os.Exit(3) - } - fmt.Print("Client response: " + string(message)) + keyUsage := x509.KeyUsageDigitalSignature - reader := bufio.NewReader(os.Stdin) - fmt.Print("Text to be sent: ") - text, err := reader.ReadString('\n') - if err != nil { - fmt.Println(err) - os.Exit(3) - } - fmt.Fprintf(conn, text+"\n") - } + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 160) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + log.Fatalf("Failed to generate serial number: %v", err) } - if *tcpip == "client" { - cert, err := tls.X509KeyPair(certPEM, privPEM) - cfg := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} + println("You are about to be asked to enter information \nthat will be incorporated into your certificate.") - ipport := "127.0.0.1:8081" - if *iport != "" { - ipport = *iport - } + scanner := bufio.NewScanner(os.Stdin) - conn, err := tls.Dial("tcp", ipport, &cfg) - if err != nil { - log.Fatal(err) - } - certs := conn.ConnectionState().PeerCertificates - for _, cert := range certs { - fmt.Printf("Issuer: \n\t%s\n", cert.Issuer) - fmt.Printf("Subject: \n\t%s\n", cert.Subject) - fmt.Printf("Expiry: %s \n", cert.NotAfter.Format("Monday, 02-Jan-06 15:04:05 MST")) - } - if err != nil { - log.Fatal(err) - } - defer conn.Close() + print("Common Name: ") + scanner.Scan() + name := scanner.Text() - var b bytes.Buffer - for _, cert := range conn.ConnectionState().PeerCertificates { - err := pem.Encode(&b, &pem.Block{ - Type: "CERTIFICATE", - Bytes: cert.Raw, - }) - if err != nil { - log.Println(err) - } - } - fmt.Println(b.String()) + print("Country Name (2 letter code) [AU]: ") + scanner.Scan() + country := scanner.Text() - for { - reader := bufio.NewReader(os.Stdin) - fmt.Print("Text to be sent: ") - text, err := reader.ReadString('\n') - if err != nil { - fmt.Println(err) - os.Exit(3) - } - fmt.Fprintf(conn, text+"\n") + print("State or Province Name (full name) [Some-State]: ") + scanner.Scan() + province := scanner.Text() - message, err := bufio.NewReader(conn).ReadString('\n') - if err != nil { - fmt.Println(err) - os.Exit(3) - } - fmt.Print("Server response: " + message) - } - } - os.Exit(0) - } + print("Locality Name (eg, city): ") + scanner.Scan() + locality := scanner.Text() - if *pkey == "keygen" && strings.ToUpper(*alg) == "RSA" { - GenerateRsaKey(*length) - os.Exit(0) - } + print("Organization Name (eg, company) [Internet Widgits Pty Ltd]: ") + scanner.Scan() + organization := scanner.Text() - if *pkey == "pkcs12" && *key != "" { - err := PfxGen() - if err != nil { - log.Fatal(err) - } - os.Exit(0) - } + print("Organizational Unit Name (eg, section): ") + scanner.Scan() + organizationunit := scanner.Text() - if *pkey == "pkcs12" && *key == "" { - err := PfxParse() - if err != nil { - log.Fatal(err) - } - os.Exit(0) - } + print("Email Address []: ") + scanner.Scan() + email := scanner.Text() - if *pkey == "x509" && strings.ToUpper(*alg) != "GOST2012" { - err := csrToCrt() - if err != nil { - log.Fatal(err) + print("StreetAddress: ") + scanner.Scan() + street := scanner.Text() + + print("PostalCode: ") + scanner.Scan() + postalcode := scanner.Text() + + print("SerialNumber: ") + scanner.Scan() + number := scanner.Text() + + print("Validity (in Days): ") + scanner.Scan() + validity := scanner.Text() + + intVar, err := strconv.Atoi(validity) + NotAfter := time.Now().AddDate(0, 0, intVar) + + hasher := gost34112012256.New() + if _, err = hasher.Write(gost341012256Pub.(*gost3410.PublicKey).Raw()); err != nil { + log.Fatalln(err) } - os.Exit(0) - } + spki := hasher.Sum(nil) + spki = spki[:20] - if *pkey == "x509" && strings.ToUpper(*alg) == "GOST2012" { - err := csrToCrt2() - if err != nil { - log.Fatal(err) + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + CommonName: name, + SerialNumber: number, + Country: []string{country}, + Province: []string{province}, + Locality: []string{locality}, + Organization: []string{organization}, + OrganizationalUnit: []string{organizationunit}, + StreetAddress: []string{street}, + PostalCode: []string{postalcode}, + }, + EmailAddresses: []string{email}, + SubjectKeyId: spki, + AuthorityKeyId: spki, + + NotBefore: time.Now(), + NotAfter: NotAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IsCA: true, + PermittedDNSDomainsCritical: true, + DNSNames: []string{name}, + + /* + PermittedDNSDomainsCritical: true, + DNSNames: []string{ip.String()}, + IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")}, + */ } - os.Exit(0) - } - if *pkey == "sign" && *key == "" && strings.ToUpper(*alg) == "RSA" { - fmt.Fprintln(os.Stderr, "Usage:") - fmt.Fprintln(os.Stderr, os.Args[0]+" -pkey sign -key ") - os.Exit(1) - } else if *pkey == "sign" && *key != "" && strings.ToUpper(*alg) == "RSA" { - buf := bytes.NewBuffer(nil) - data := inputfile - io.Copy(buf, data) - Data := string(buf.Bytes()) - sourceData := []byte(Data) - signData, err := SignatureRSA(sourceData) + template.IsCA = true + template.KeyUsage |= x509.KeyUsageContentCommitment | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement | x509.KeyUsageCertSign | x509.KeyUsageCRLSign + + derBytes, err := x509.CreateCertificate( + rand.Reader, + &template, &template, + gost341012256Pub, &gost3410.PrivateKeyReverseDigest{Prv: gost341012256Priv}, + ) if err != nil { - fmt.Println("cryption error:", err) - os.Exit(1) + log.Println(err) } - fmt.Println("RSA-"+strings.ToUpper(*md)+"("+inputdesc+")=", hex.EncodeToString(signData)) - os.Exit(0) - } - if *pkey == "verify" && (*key == "" || *sig == "") && strings.ToUpper(*alg) == "RSA" { - fmt.Fprintln(os.Stderr, "Usage:") - fmt.Fprintln(os.Stderr, os.Args[0]+" -pkey verify -key -signature <$signature>") - os.Exit(1) - } else if *pkey == "verify" && (*key != "" || *sig != "") && strings.ToUpper(*alg) == "RSA" { - buf := bytes.NewBuffer(nil) - data := inputfile - io.Copy(buf, data) - Data := string(buf.Bytes()) - Signature, err := hex.DecodeString(*sig) - err = VerifyRSA([]byte(Data), Signature) + certfile, err := os.Create(*cert) if err != nil { - fmt.Println("Checksum error:", err) - os.Exit(1) + log.Println(err) } - fmt.Println("Verify correct.") + pem.Encode(certfile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + os.Exit(0) } - if *pkey == "encrypt" && (*key != "") && strings.ToUpper(*alg) == "RSA" { + if *pkey == "req" && *key != "" && strings.ToUpper(*alg) == "GOST2012" { file, err := os.Open(*key) if err != nil { log.Fatal(err) @@ -6691,72 +7027,127 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) - block, _ := pem.Decode(buf) - publicInterface, err := x509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - log.Fatal(err) - } - publicKey := publicInterface.(*rsa.PublicKey) - - buffer := bytes.NewBuffer(nil) - data := inputfile - io.Copy(buffer, data) - ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, buffer.Bytes()) - if err != nil { - fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err) - return - } - fmt.Printf("%s", ciphertext) - } + var block *pem.Block + block, _ = pem.Decode(buf) - if *pkey == "decrypt" && (*key != "") && strings.ToUpper(*alg) == "RSA" { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) - } - buf := make([]byte, info.Size()) - file.Read(buf) - - var block *pem.Block - block, _ = pem.Decode(buf) - - var privateKey *rsa.PrivateKey + var priva interface{} var privKeyBytes []byte if IsEncryptedPEMBlock(block) { privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) if err != nil { log.Fatal(err) } - privateKey, err = x509.ParsePKCS1PrivateKey(privKeyBytes) + priva, err = x509.ParsePKCS8PrivateKey(privKeyBytes) if err != nil { log.Fatal(err) } } else { - privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + priva, err = x509.ParsePKCS8PrivateKey(block.Bytes) if err != nil { log.Fatal(err) } } - buffer := bytes.NewBuffer(nil) - data := inputfile - io.Copy(buffer, data) + println("You are about to be asked to enter information that \nwill be incorporated into your certificate request.") - plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, buffer.Bytes()) - if err != nil { - fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err) - return + scanner := bufio.NewScanner(os.Stdin) + + print("Common Name: ") + scanner.Scan() + name := scanner.Text() + + print("Country Name (2 letter code) [AU]: ") + scanner.Scan() + country := scanner.Text() + + print("State or Province Name (full name) [Some-State]: ") + scanner.Scan() + province := scanner.Text() + + print("Locality Name (eg, city): ") + scanner.Scan() + locality := scanner.Text() + + print("Organization Name (eg, company) [Internet Widgits Pty Ltd]: ") + scanner.Scan() + organization := scanner.Text() + + print("Organizational Unit Name (eg, section): ") + scanner.Scan() + organizationunit := scanner.Text() + + print("Email Address []: ") + scanner.Scan() + email := scanner.Text() + + print("StreetAddress: ") + scanner.Scan() + street := scanner.Text() + + print("PostalCode: ") + scanner.Scan() + postalcode := scanner.Text() + + print("SerialNumber: ") + scanner.Scan() + number := scanner.Text() + + var sigalg x509.SignatureAlgorithm + if *length == 512 { + sigalg = x509.GOST512 + } else { + sigalg = x509.GOST256 } - fmt.Printf("%s", plaintext) + + emailAddress := email + subj := pkix.Name{ + CommonName: name, + SerialNumber: number, + Country: []string{country}, + Province: []string{province}, + Locality: []string{locality}, + Organization: []string{organization}, + OrganizationalUnit: []string{organizationunit}, + StreetAddress: []string{street}, + PostalCode: []string{postalcode}, + } + rawSubj := subj.ToRDNSequence() + rawSubj = append(rawSubj, []pkix.AttributeTypeAndValue{ + {Type: oidEmailAddress, Value: emailAddress}, + }) + + asn1Subj, _ := asn1.Marshal(rawSubj) + var template x509.CertificateRequest + + template = x509.CertificateRequest{ + RawSubject: asn1Subj, + EmailAddresses: []string{emailAddress}, + SignatureAlgorithm: sigalg, + } + + var output *os.File + if *cert == "" { + output = os.Stdout + } else { + file, err := os.Create(*cert) + if err != nil { + log.Fatal(err) + } + defer file.Close() + output = file + } + csrBytes, _ := x509.CreateCertificateRequest(rand.Reader, &template, &gost3410.PrivateKeyReverseDigest{Prv: priva.(*gost3410.PrivateKey)}) + pem.Encode(output, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) + os.Exit(0) } - if (*pkey == "text" || *pkey == "modulus") && PEM == "Private" && strings.ToUpper(*alg) == "GOST2012" { + if (*tcpip == "server" || *tcpip == "client") && strings.ToUpper(*alg) == "GOST2012" { + var certPEM []byte var privPEM []byte + + tls.GOSTInstall() + file, err := os.Open(*key) if err != nil { log.Println(err) @@ -6767,139 +7158,232 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) + var block *pem.Block block, _ = pem.Decode(buf) + if block == nil { errors.New("no valid private key found") } + var privKeyBytes []byte if IsEncryptedPEMBlock(block) { privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) if err != nil { - log.Fatal(err) + log.Println(err) } - privPEM = pem.EncodeToMemory(&pem.Block{Type: "GOST PRIVATE KEY", Bytes: privKeyBytes}) + privPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privKeyBytes}) } else { privPEM = buf } - var privateKeyPemBlock, _ = pem.Decode([]byte(privPEM)) - var privKey, _ = x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) + + file, err = os.Open(*cert) if err != nil { log.Println(err) } - gostKey := privKey.(*gost3410.PrivateKey) - pubKey := gostKey.Public() - if *pkey == "modulus" { - var publicKey = pubKey.(*gost3410.PublicKey) - fmt.Printf("Public.X=%X\n", publicKey.X) - fmt.Printf("Public.Y=%X\n", publicKey.Y) - os.Exit(0) + info, err = file.Stat() + if err != nil { + log.Println(err) } - fmt.Printf(string(privPEM)) - /* - derBytes, err := x509.MarshalPKIXPublicKey(gostKey.Public()) + buf = make([]byte, info.Size()) + file.Read(buf) + certPEM = buf + + if *tcpip == "server" { + cert, err := tls.X509KeyPair(certPEM, privPEM) + cfg := tls.Config{Certificates: []tls.Certificate{cert}, ClientAuth: tls.RequireAnyClientCert, MinVersion: tls.VersionTLS13, MaxVersion: tls.VersionTLS13} + cfg.Rand = rand.Reader + + port := "8081" + if *iport != "" { + port = *iport + } + + ln, err := tls.Listen("tcp", ":"+port, &cfg) if err != nil { log.Fatal(err) } - */ - p := fmt.Sprintf("%X", gostKey.Raw()) - fmt.Println("Private key:", p) - fmt.Printf("Public key: \n") - var publicKey = pubKey.(*gost3410.PublicKey) - fmt.Printf(" X:%X\n", publicKey.X) - fmt.Printf(" Y:%X\n", publicKey.Y) - /* - var spki struct { - Algorithm pkix.AlgorithmIdentifier - SubjectPublicKey asn1.BitString - } - _, err = asn1.Unmarshal(derBytes, &spki) + fmt.Fprintln(os.Stderr, "Server(TLS) up and listening on port "+port) + + conn, err := ln.Accept() if err != nil { log.Println(err) } - skid := sha1.Sum(spki.SubjectPublicKey.Bytes) - fmt.Printf("\nKeyID: %x \n", skid) - */ + defer ln.Close() - fmt.Printf("Curve: %s\n", publicKey.C.Name) + tlscon := conn.(*tls.Conn) + err = tlscon.Handshake() + if err != nil { + log.Fatalf("server: handshake failed: %s", err) + } else { + log.Print("server: conn: Handshake completed") + } + state := tlscon.ConnectionState() - hasher := gost34112012256.New() - if _, err = hasher.Write(publicKey.Raw()); err != nil { - log.Fatalln(err) - } - spki := hasher.Sum(nil) - spki = spki[:20] - fmt.Printf("\nKeyID: %x \n", spki) - os.Exit(0) - } + for _, v := range state.PeerCertificates { + derBytes, err := x509.MarshalPKIXPublicKey(v.PublicKey) + if err != nil { + log.Fatal(err) + } + pubPEM := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: derBytes}) + fmt.Printf("%s\n", pubPEM) + } - if (*pkey == "randomart") && PEM == "Public" { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) - } - buf := make([]byte, info.Size()) - file.Read(buf) - block, _ := pem.Decode(buf) - publicInterface, err := smx509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - publicInterface, err = x509.ParsePKIXPublicKey(block.Bytes) - } - switch publicInterface.(type) { - case *rsa.PublicKey: - publicKey := publicInterface.(*rsa.PublicKey) - fmt.Printf("RSA (%v-bit)\n", publicKey.N.BitLen()) - case *ecdsa.PublicKey: - publicKey := publicInterface.(*ecdsa.PublicKey) - fmt.Printf("ECDSA (%v-bit)\n", publicKey.Curve.Params().BitSize) - case *ecdh.PublicKey: - fmt.Println("X25519 (256-bit)") - case ed25519.PublicKey: - fmt.Println("Ed25519 (256-bit)") - case *gost3410.PublicKey: - publicKey := publicInterface.(*gost3410.PublicKey) - fmt.Printf("GOST2012 (%v-bit)\n", len(publicKey.Raw())*4) - default: - log.Fatal("unknown type of public key") - } - fmt.Println(randomart.FromString(strings.ReplaceAll(string(buf), "\r\n", "\n"))) - } + go handleConnectionTLS(conn) + fmt.Println("Connection accepted") - if (*pkey == "fingerprint") && PEM == "Public" { - file, err := os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err := file.Stat() - if err != nil { - log.Fatal(err) - } - buf := make([]byte, info.Size()) - file.Read(buf) - block, _ := pem.Decode(buf) - publicInterface, err := smx509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - publicInterface, err = x509.ParsePKIXPublicKey(block.Bytes) - } - var fingerprint string - switch publicInterface.(type) { - case *rsa.PublicKey, *ecdsa.PublicKey, *ecdh.PublicKey, ed25519.PublicKey: - fingerprint = calculateFingerprint(buf) - case *gost3410.PublicKey: - fingerprint = calculateFingerprintGOST(buf) - default: - log.Fatal("unknown type of public key") + for { + message, err := bufio.NewReader(conn).ReadString('\n') + if err != nil { + fmt.Println(err) + os.Exit(3) + } + fmt.Print("Client response: " + string(message)) + + reader := bufio.NewReader(os.Stdin) + fmt.Print("Text to be sent: ") + text, err := reader.ReadString('\n') + if err != nil { + fmt.Println(err) + os.Exit(3) + } + fmt.Fprintf(conn, text+"\n") + } } - fmt.Print("Fingerprint= ") - fmt.Println(fingerprint) + + if *tcpip == "client" { + cert, err := tls.X509KeyPair(certPEM, privPEM) + cfg := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true} + + ipport := "127.0.0.1:8081" + if *iport != "" { + ipport = *iport + } + + conn, err := tls.Dial("tcp", ipport, &cfg) + if err != nil { + log.Fatal(err) + } + certs := conn.ConnectionState().PeerCertificates + for _, cert := range certs { + fmt.Printf("Issuer: \n\t%s\n", cert.Issuer) + fmt.Printf("Subject: \n\t%s\n", cert.Subject) + fmt.Printf("Expiry: %s \n", cert.NotAfter.Format("Monday, 02-Jan-06 15:04:05 MST")) + } + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + var b bytes.Buffer + for _, cert := range conn.ConnectionState().PeerCertificates { + err := pem.Encode(&b, &pem.Block{ + Type: "CERTIFICATE", + Bytes: cert.Raw, + }) + if err != nil { + log.Println(err) + } + } + fmt.Println(b.String()) + + for { + reader := bufio.NewReader(os.Stdin) + fmt.Print("Text to be sent: ") + text, err := reader.ReadString('\n') + if err != nil { + fmt.Println(err) + os.Exit(3) + } + fmt.Fprintf(conn, text+"\n") + + message, err := bufio.NewReader(conn).ReadString('\n') + if err != nil { + fmt.Println(err) + os.Exit(3) + } + fmt.Print("Server response: " + message) + } + } + os.Exit(0) } - if (*pkey == "text" || *pkey == "modulus") && PEM == "Public" { + if *pkey == "keygen" && strings.ToUpper(*alg) == "RSA" { + GenerateRsaKey(*length) + os.Exit(0) + } + + if *pkey == "pkcs12" && *key != "" { + err := PfxGen() + if err != nil { + log.Fatal(err) + } + os.Exit(0) + } + + if *pkey == "pkcs12" && *key == "" { + err := PfxParse() + if err != nil { + log.Fatal(err) + } + os.Exit(0) + } + + if *pkey == "x509" && strings.ToUpper(*alg) != "GOST2012" { + err := csrToCrt() + if err != nil { + log.Fatal(err) + } + os.Exit(0) + } + + if *pkey == "x509" && strings.ToUpper(*alg) == "GOST2012" { + err := csrToCrt2() + if err != nil { + log.Fatal(err) + } + os.Exit(0) + } + + if *pkey == "sign" && *key == "" && strings.ToUpper(*alg) == "RSA" { + fmt.Fprintln(os.Stderr, "Usage:") + fmt.Fprintln(os.Stderr, os.Args[0]+" -pkey sign -key ") + os.Exit(1) + } else if *pkey == "sign" && *key != "" && strings.ToUpper(*alg) == "RSA" { + buf := bytes.NewBuffer(nil) + data := inputfile + io.Copy(buf, data) + Data := string(buf.Bytes()) + sourceData := []byte(Data) + signData, err := SignatureRSA(sourceData) + if err != nil { + fmt.Println("cryption error:", err) + os.Exit(1) + } + fmt.Println("RSA-"+strings.ToUpper(*md)+"("+inputdesc+")=", hex.EncodeToString(signData)) + os.Exit(0) + } + + if *pkey == "verify" && (*key == "" || *sig == "") && strings.ToUpper(*alg) == "RSA" { + fmt.Fprintln(os.Stderr, "Usage:") + fmt.Fprintln(os.Stderr, os.Args[0]+" -pkey verify -key -signature <$signature>") + os.Exit(1) + } else if *pkey == "verify" && (*key != "" || *sig != "") && strings.ToUpper(*alg) == "RSA" { + buf := bytes.NewBuffer(nil) + data := inputfile + io.Copy(buf, data) + Data := string(buf.Bytes()) + Signature, err := hex.DecodeString(*sig) + err = VerifyRSA([]byte(Data), Signature) + if err != nil { + fmt.Println("Checksum error:", err) + os.Exit(1) + } + fmt.Println("Verify correct.") + } + + if *pkey == "encrypt" && (*key != "") && strings.ToUpper(*alg) == "RSA" { file, err := os.Open(*key) if err != nil { log.Fatal(err) @@ -6911,210 +7395,78 @@ Subcommands: buf := make([]byte, info.Size()) file.Read(buf) block, _ := pem.Decode(buf) - publicInterface, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { - publicInterface, err = smx509.ParsePKIXPublicKey(block.Bytes) + log.Fatal(err) } - switch publicInterface.(type) { - case *ecdh.PublicKey: - *alg = "X25519" - case ed25519.PublicKey: - *alg = "ED25519" - case *rsa.PublicKey: - *alg = "RSA" - case *ecdsa.PublicKey: - *alg = "EC" - case *gost3410.PublicKey: - *alg = "GOST2012" - default: - log.Fatal("unknown type of public key") + publicKey := publicInterface.(*rsa.PublicKey) + + buffer := bytes.NewBuffer(nil) + data := inputfile + io.Copy(buffer, data) + + ciphertext, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, buffer.Bytes()) + if err != nil { + fmt.Fprintf(os.Stderr, "Error from encryption: %s\n", err) + return } + fmt.Printf("%s", ciphertext) + } - if *pkey == "modulus" && strings.ToUpper(*alg) == "RSA" { - var publicKey = publicInterface.(*rsa.PublicKey) - fmt.Printf("Modulus=%X\n", publicKey.N) - os.Exit(0) - } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "SM2") { - var publicKey = publicInterface.(*ecdsa.PublicKey) - fmt.Printf("Public.X=%X\n", publicKey.X) - fmt.Printf("Public.Y=%X\n", publicKey.Y) - os.Exit(0) - } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "ED25519") { - var publicKey = publicInterface.(ed25519.PublicKey) - fmt.Printf("Public=%X\n", publicKey) - os.Exit(0) - } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "GOST2012") { - var publicKey = publicInterface.(*gost3410.PublicKey) - fmt.Printf("Public.X=%X\n", publicKey.X) - fmt.Printf("Public.Y=%X\n", publicKey.Y) - os.Exit(0) + if *pkey == "decrypt" && (*key != "") && strings.ToUpper(*alg) == "RSA" { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) } + buf := make([]byte, info.Size()) + file.Read(buf) - if strings.ToUpper(*alg) == "RSA" { - publicKey := publicInterface.(*rsa.PublicKey) - derBytes, err := x509.MarshalPKIXPublicKey(publicKey) + var block *pem.Block + block, _ = pem.Decode(buf) + + var privateKey *rsa.PrivateKey + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) if err != nil { log.Fatal(err) } - block := &pem.Block{ - Type: "PUBLIC KEY", - Bytes: derBytes, - } - public := pem.EncodeToMemory(block) - fmt.Printf(string(public)) - fmt.Printf("RSA Public-Key: (%v-bit)\n", publicKey.N.BitLen()) - fmt.Printf("Modulus: \n") - m := publicKey.N.Bytes() - b, _ := hex.DecodeString("00") - c := []byte{} - c = append(c, b...) - c = append(c, m...) - splitz := SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Printf("Exponent: %X\n", publicKey.E) - } else if strings.ToUpper(*alg) == "ED25519" { - publicKey := publicInterface.(ed25519.PublicKey) - derBytes, err := smx509.MarshalPKIXPublicKey(publicKey) + privateKey, err = x509.ParsePKCS1PrivateKey(privKeyBytes) if err != nil { log.Fatal(err) } - block := &pem.Block{ - Type: "PUBLIC KEY", - Bytes: derBytes, + } else { + privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + log.Fatal(err) } - public := pem.EncodeToMemory(block) - fmt.Printf(string(public)) - - fmt.Printf("ED25519 Public-Key:\n") - fmt.Printf("pub: \n") - splitz := SplitSubN(hex.EncodeToString(derBytes)[24:], 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - var spki struct { - Algorithm pkix.AlgorithmIdentifier - SubjectPublicKey asn1.BitString - } - _, err = asn1.Unmarshal(derBytes, &spki) - if err != nil { - log.Fatal(err) - } - skid := sha1.Sum(spki.SubjectPublicKey.Bytes) - fmt.Printf("\nKeyID: %x \n", skid) - } else if strings.ToUpper(*alg) == "X25519" { - publicKey := publicInterface.(*ecdh.PublicKey) - derBytes, err := x509.MarshalPKIXPublicKey(publicKey) - if err != nil { - log.Fatal(err) - } - block := &pem.Block{ - Type: "PUBLIC KEY", - Bytes: derBytes, - } - public := pem.EncodeToMemory(block) - fmt.Printf(string(public)) + } - fmt.Printf("X25519 Public-Key:\n") - fmt.Printf("pub: \n") - splitz := SplitSubN(hex.EncodeToString(derBytes)[24:], 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - var spki struct { - Algorithm pkix.AlgorithmIdentifier - SubjectPublicKey asn1.BitString - } - _, err = asn1.Unmarshal(derBytes, &spki) - if err != nil { - log.Fatal(err) - } - skid := sha1.Sum(spki.SubjectPublicKey.Bytes) - fmt.Printf("\nKeyID: %x \n", skid) - } else if strings.ToUpper(*alg) == "EC" { - publicKey := publicInterface.(*ecdsa.PublicKey) - derBytes, err := smx509.MarshalPKIXPublicKey(publicKey) - if err != nil { - log.Fatal(err) - } - block := &pem.Block{ - Type: "PUBLIC KEY", - Bytes: derBytes, - } - public := pem.EncodeToMemory(block) - fmt.Printf(string(public)) + buffer := bytes.NewBuffer(nil) + data := inputfile + io.Copy(buffer, data) - fmt.Printf("Public-Key: (%v-bit)\n", publicKey.Curve.Params().BitSize) - x := publicKey.X.Bytes() - if n := len(x); n < 24 && n < 32 && n < 48 && n < 64 { - x = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], x...) - } - c := []byte{} - c = append(c, x...) - fmt.Printf("pub.X: \n") - splitz := SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - y := publicKey.Y.Bytes() - if n := len(y); n < 24 && n < 32 && n < 48 && n < 64 { - y = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], y...) - } - c = []byte{} - c = append(c, y...) - fmt.Printf("pub.Y: \n") - splitz = SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Printf("pub: \n") - x = publicKey.X.Bytes() - y = publicKey.Y.Bytes() - if n := len(x); n < 24 && n < 32 && n < 48 && n < 64 { - x = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], x...) - } - if n := len(y); n < 24 && n < 32 && n < 48 && n < 64 { - y = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], y...) - } - c = []byte{} - c = append(c, x...) - c = append(c, y...) - c = append([]byte{0x04}, c...) - splitz = SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Printf("Curve: %s\n", publicKey.Params().Name) - } else if strings.ToUpper(*alg) == "GOST2012" { - publicKey := publicInterface.(*gost3410.PublicKey) - derBytes, err := x509.MarshalPKIXPublicKey(publicKey) - if err != nil { - log.Println(err) - } - block = &pem.Block{ - Type: "PUBLIC KEY", - Bytes: derBytes, - } - public := pem.EncodeToMemory(block) - fmt.Printf(string(public)) - fmt.Printf("Public key:\n") - fmt.Printf(" X:%X\n", publicKey.X) - fmt.Printf(" Y:%X\n", publicKey.Y) - fmt.Printf("Curve: %s\n", publicKey.C.Name) + plaintext, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, buffer.Bytes()) + if err != nil { + fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err) + return } + fmt.Printf("%s", plaintext) } - if (*pkey == "text" || *pkey == "modulus") && PEM == "Private" { + if (*pkey == "text" || *pkey == "modulus") && PEM == "Private" && strings.ToUpper(*alg) == "GOST2012" { var privPEM []byte file, err := os.Open(*key) if err != nil { - log.Fatal(err) + log.Println(err) } info, err := file.Stat() if err != nil { - log.Fatal(err) + log.Println(err) } buf := make([]byte, info.Size()) file.Read(buf) @@ -7129,188 +7481,102 @@ Subcommands: if err != nil { log.Fatal(err) } - privPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privKeyBytes}) + privPEM = pem.EncodeToMemory(&pem.Block{Type: "GOST PRIVATE KEY", Bytes: privKeyBytes}) } else { privPEM = buf } var privateKeyPemBlock, _ = pem.Decode([]byte(privPEM)) - if strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "SM2" { - var privKey, err = smx509.ParseECPrivateKey(privateKeyPemBlock.Bytes) - if err != nil { - log.Fatal(err) - } - derBytes, err := smx509.MarshalPKIXPublicKey(&privKey.PublicKey) + var privKey, _ = x509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) + if err != nil { + log.Println(err) + } + gostKey := privKey.(*gost3410.PrivateKey) + pubKey := gostKey.Public() + if *pkey == "modulus" { + var publicKey = pubKey.(*gost3410.PublicKey) + fmt.Printf("Public.X=%X\n", publicKey.X) + fmt.Printf("Public.Y=%X\n", publicKey.Y) + os.Exit(0) + } + fmt.Printf(string(privPEM)) + /* + derBytes, err := x509.MarshalPKIXPublicKey(gostKey.Public()) if err != nil { log.Fatal(err) } - if *pkey == "modulus" { - fmt.Printf("Public.X=%X\n", privKey.PublicKey.X) - fmt.Printf("Public.Y=%X\n", privKey.PublicKey.Y) - os.Exit(0) - } - fmt.Printf(string(privPEM)) - d := privKey.D.Bytes() - if n := len(d); n < 24 && n < 32 && n < 48 && n < 64 { - d = append(zeroByteSlice()[:(privKey.Curve.Params().BitSize/8)-n], d...) - } - c := []byte{} - c = append(c, d...) - fmt.Printf("Private-Key: (%v-bit)\n", privKey.Curve.Params().BitSize) - fmt.Printf("priv: \n") - splitz := SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } + */ + p := fmt.Sprintf("%X", gostKey.Raw()) + fmt.Println("Private key:", p) - publicKey := privKey.PublicKey - fmt.Printf("pub: \n") - x := publicKey.X.Bytes() - y := publicKey.Y.Bytes() - if n := len(x); n < 24 && n < 32 && n < 48 && n < 64 { - x = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], x...) - } - if n := len(y); n < 24 && n < 32 && n < 48 && n < 64 { - y = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], y...) - } - c = []byte{} - c = append(c, x...) - c = append(c, y...) - c = append([]byte{0x04}, c...) - splitz = SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } + fmt.Printf("Public key: \n") + var publicKey = pubKey.(*gost3410.PublicKey) + fmt.Printf(" X:%X\n", publicKey.X) + fmt.Printf(" Y:%X\n", publicKey.Y) + /* var spki struct { Algorithm pkix.AlgorithmIdentifier SubjectPublicKey asn1.BitString } _, err = asn1.Unmarshal(derBytes, &spki) if err != nil { - log.Fatal(err) + log.Println(err) } - fmt.Printf("Curve: %s\n", publicKey.Params().Name) skid := sha1.Sum(spki.SubjectPublicKey.Bytes) fmt.Printf("\nKeyID: %x \n", skid) - } else if strings.ToUpper(*alg) == "ED25519" { - var privKey, _ = smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) - if err != nil { - log.Fatal(err) - } - edKey := privKey.(ed25519.PrivateKey) + */ - if *pkey == "modulus" { - fmt.Printf("Public=%X\n", edKey.Public()) - os.Exit(0) - } + fmt.Printf("Curve: %s\n", publicKey.C.Name) - fmt.Printf(string(privPEM)) - derBytes, err := smx509.MarshalPKIXPublicKey(edKey.Public()) - if err != nil { - log.Fatal(err) - } - fmt.Printf("ED25519 Private-Key:\n") - p := fmt.Sprintf("%x", privKey) - fmt.Printf("priv: \n") - splitz := SplitSubN(p[:64], 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Printf("pub: \n") - splitz = SplitSubN(p[64:], 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } + hasher := gost34112012256.New() + if _, err = hasher.Write(publicKey.Raw()); err != nil { + log.Fatalln(err) + } + spki := hasher.Sum(nil) + spki = spki[:20] + fmt.Printf("\nKeyID: %x \n", spki) + os.Exit(0) + } - var spki struct { - Algorithm pkix.AlgorithmIdentifier - SubjectPublicKey asn1.BitString - } - _, err = asn1.Unmarshal(derBytes, &spki) - if err != nil { - log.Fatal(err) - } - skid := sha1.Sum(spki.SubjectPublicKey.Bytes) - fmt.Printf("\nKeyID: %x \n", skid) - } else if strings.ToUpper(*alg) == "X25519" { - var privKey, _ = smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) - if err != nil { - log.Fatal(err) - } - edKey := privKey.(*ecdh.PrivateKey) - fmt.Printf(string(privPEM)) - derBytes, err := x509.MarshalPKIXPublicKey(edKey.Public()) - if err != nil { - log.Fatal(err) - } - fmt.Printf("X25519 Private-Key:\n") - p := fmt.Sprintf("%x", edKey.Bytes()) - fmt.Printf("priv: \n") - splitz := SplitSubN(p, 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - p = fmt.Sprintf("%x", edKey.PublicKey().Bytes()) - fmt.Printf("pub: \n") - splitz = SplitSubN(p, 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } + if *pkey == "fingerprint" && (strings.ToUpper(*alg) == "ELGAMAL") && (PEM == "Public") { + publicKeyVal, err := readPublicKeyFromPEM(*key) + if err != nil { + fmt.Println("Error reading PEM file:", err) + return + } - var spki struct { - Algorithm pkix.AlgorithmIdentifier - SubjectPublicKey asn1.BitString - } - _, err = asn1.Unmarshal(derBytes, &spki) - if err != nil { - log.Fatal(err) - } - skid := sha1.Sum(spki.SubjectPublicKey.Bytes) - fmt.Printf("\nKeyID: %x \n", skid) - } else if strings.ToUpper(*alg) == "RSA" { - var privKey, _ = x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes) - if err := privKey.Validate(); err != nil { - panic("error validating the private key: " + err.Error()) - } - var privKeyPublicKey = privKey.PublicKey + fingerprint := calculateFingerprint(publicKeyVal.Y.Bytes()) + fmt.Println("Fingerprint=", fingerprint) + os.Exit(0) + } + if *pkey == "randomart" && (strings.ToUpper(*alg) == "ELGAMAL") && (PEM == "Public") { + publicKeyVal, err := readPublicKeyFromPEM(*key) + if err != nil { + fmt.Println("Error reading PEM file:", err) + return + } - if *pkey == "modulus" { - fmt.Printf("Modulus=%X\n", privKey.N) - os.Exit(0) - } - fmt.Printf(string(privPEM)) - fmt.Printf("RSA Private-Key: (%v-bit)\n", privKey.N.BitLen()) - fmt.Printf("Modulus: \n") - m := privKeyPublicKey.N.Bytes() - b, _ := hex.DecodeString("00") - c := []byte{} - c = append(c, b...) - c = append(c, m...) - splitz := SplitSubN(hex.EncodeToString(c), 2) - for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) - } - fmt.Printf("Exponent: %X\n\n", privKeyPublicKey.E) - derBytes, err := x509.MarshalPKIXPublicKey(&privKeyPublicKey) - if err != nil { - log.Fatal(err) - } + primeBitLength := publicKeyVal.P.BitLen() + fmt.Fprintf(os.Stderr, "ElGamal (%d-bits)\n", primeBitLength) - var spki struct { - Algorithm pkix.AlgorithmIdentifier - SubjectPublicKey asn1.BitString - } - _, err = asn1.Unmarshal(derBytes, &spki) - if err != nil { - log.Fatal(err) - } - skid := sha1.Sum(spki.SubjectPublicKey.Bytes) - fmt.Printf("KeyID: %x \n", skid) + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + + info, err := file.Stat() + if err != nil { + log.Fatal(err) } + + buf := make([]byte, info.Size()) + file.Read(buf) + randomArt := randomart.FromString(string(buf)) + fmt.Println(randomArt) + os.Exit(0) } - if (*pkey == "text" || *pkey == "modulus" || *pkey == "info") && (PEM == "Certificate") { - var certPEM []byte - file, err := os.Open(*cert) + if (*pkey == "randomart") && PEM == "Public" { + file, err := os.Open(*key) if err != nil { log.Fatal(err) } @@ -7320,163 +7586,270 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) - certPEM = buf - var certPemBlock, _ = pem.Decode([]byte(certPEM)) - var certa, _ = smx509.ParseCertificate(certPemBlock.Bytes) + block, _ := pem.Decode(buf) + publicInterface, err := smx509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + publicInterface, err = x509.ParsePKIXPublicKey(block.Bytes) + } + switch publicInterface.(type) { + case *rsa.PublicKey: + publicKey := publicInterface.(*rsa.PublicKey) + fmt.Printf("RSA (%v-bit)\n", publicKey.N.BitLen()) + case *ecdsa.PublicKey: + publicKey := publicInterface.(*ecdsa.PublicKey) + fmt.Printf("ECDSA (%v-bit)\n", publicKey.Curve.Params().BitSize) + case *ecdh.PublicKey: + fmt.Println("X25519 (256-bit)") + case ed25519.PublicKey: + fmt.Println("Ed25519 (256-bit)") + case *gost3410.PublicKey: + publicKey := publicInterface.(*gost3410.PublicKey) + fmt.Printf("GOST2012 (%v-bit)\n", len(publicKey.Raw())*4) + default: + log.Fatal("unknown type of public key") + } + fmt.Println(randomart.FromString(strings.ReplaceAll(string(buf), "\r\n", "\n"))) + } - signature := fmt.Sprintf("%s", certa.SignatureAlgorithm) - if signature == "ECDSA-SHA256" || signature == "ECDSA-SHA384" || signature == "ECDSA-SHA512" { - *alg = "EC" - } else if signature == "99" { - *alg = "SM2" - } else if signature == "Ed25519" { + if (*pkey == "fingerprint") && PEM == "Public" { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) + } + buf := make([]byte, info.Size()) + file.Read(buf) + block, _ := pem.Decode(buf) + publicInterface, err := smx509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + publicInterface, err = x509.ParsePKIXPublicKey(block.Bytes) + } + var fingerprint string + switch publicInterface.(type) { + case *rsa.PublicKey, *ecdsa.PublicKey, *ecdh.PublicKey, ed25519.PublicKey: + fingerprint = calculateFingerprint(buf) + case *gost3410.PublicKey: + fingerprint = calculateFingerprintGOST(buf) + default: + log.Fatal("unknown type of public key") + } + fmt.Print("Fingerprint= ") + fmt.Println(fingerprint) + } + + if (*pkey == "text" || *pkey == "modulus") && PEM == "Public" { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) + } + buf := make([]byte, info.Size()) + file.Read(buf) + block, _ := pem.Decode(buf) + + publicInterface, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + publicInterface, err = smx509.ParsePKIXPublicKey(block.Bytes) + } + switch publicInterface.(type) { + case *ecdh.PublicKey: + *alg = "X25519" + case ed25519.PublicKey: *alg = "ED25519" - } else if signature == "SHA256-RSA" || signature == "SHA384-RSA" || signature == "SHA512-RSA" { + case *rsa.PublicKey: *alg = "RSA" - } else { + case *ecdsa.PublicKey: + *alg = "EC" + case *gost3410.PublicKey: *alg = "GOST2012" + default: + log.Fatal("unknown type of public key") } if *pkey == "modulus" && strings.ToUpper(*alg) == "RSA" { - var certaPublicKey = certa.PublicKey.(*rsa.PublicKey) - fmt.Printf("Modulus=%X\n", certaPublicKey.N) + var publicKey = publicInterface.(*rsa.PublicKey) + fmt.Printf("Modulus=%X\n", publicKey.N) os.Exit(0) } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "SM2") { - var certaPublicKey = certa.PublicKey.(*ecdsa.PublicKey) - fmt.Printf("Public.X=%X\n", certaPublicKey.X) - fmt.Printf("Public.Y=%X\n", certaPublicKey.Y) + var publicKey = publicInterface.(*ecdsa.PublicKey) + fmt.Printf("Public.X=%X\n", publicKey.X) + fmt.Printf("Public.Y=%X\n", publicKey.Y) os.Exit(0) } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "ED25519") { - var certaPublicKey = certa.PublicKey.(ed25519.PublicKey) - fmt.Printf("Public=%X\n", certaPublicKey) + var publicKey = publicInterface.(ed25519.PublicKey) + fmt.Printf("Public=%X\n", publicKey) os.Exit(0) } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "GOST2012") { - var certa, _ = x509.ParseCertificate(certPemBlock.Bytes) - var certaPublicKey = certa.PublicKey.(*gost3410.PublicKey) - fmt.Printf("Public.X=%X\n", certaPublicKey.X) - fmt.Printf("Public.Y=%X\n", certaPublicKey.Y) - os.Exit(0) - } - - if *pkey == "info" { - fmt.Printf("Expiry: %s \n", certa.NotAfter.Format("Monday, 02-Jan-06 15:04:05 MST")) - fmt.Printf("Common Name: %s \n", certa.Issuer.CommonName) - fmt.Printf("EmailAddresses: %s \n", certa.EmailAddresses) - fmt.Printf("IP Address: %s \n", certa.IPAddresses) - fmt.Printf("DNSNames: %s \n", certa.DNSNames) - fmt.Printf("SerialNumber: %x \n", certa.SerialNumber) - fmt.Printf("SubjectKeyId: %x \n", certa.SubjectKeyId) - fmt.Printf("AuthorityKeyId: %x \n", certa.AuthorityKeyId) + var publicKey = publicInterface.(*gost3410.PublicKey) + fmt.Printf("Public.X=%X\n", publicKey.X) + fmt.Printf("Public.Y=%X\n", publicKey.Y) os.Exit(0) } - if *alg == "GOST2012" { - var certPEM []byte - file, err := os.Open(*cert) + if strings.ToUpper(*alg) == "RSA" { + publicKey := publicInterface.(*rsa.PublicKey) + derBytes, err := x509.MarshalPKIXPublicKey(publicKey) if err != nil { - log.Println(err) + log.Fatal(err) } - info, err := file.Stat() + block := &pem.Block{ + Type: "PUBLIC KEY", + Bytes: derBytes, + } + public := pem.EncodeToMemory(block) + fmt.Printf(string(public)) + fmt.Printf("RSA Public-Key: (%v-bit)\n", publicKey.N.BitLen()) + fmt.Printf("Modulus: \n") + m := publicKey.N.Bytes() + b, _ := hex.DecodeString("00") + c := []byte{} + c = append(c, b...) + c = append(c, m...) + splitz := SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Printf("Exponent: %X\n", publicKey.E) + } else if strings.ToUpper(*alg) == "ED25519" { + publicKey := publicInterface.(ed25519.PublicKey) + derBytes, err := smx509.MarshalPKIXPublicKey(publicKey) if err != nil { - log.Println(err) + log.Fatal(err) } - buf := make([]byte, info.Size()) - file.Read(buf) - certPEM = buf - var certPemBlock, _ = pem.Decode([]byte(certPEM)) - var certa, _ = x509.ParseCertificate(certPemBlock.Bytes) + block := &pem.Block{ + Type: "PUBLIC KEY", + Bytes: derBytes, + } + public := pem.EncodeToMemory(block) + fmt.Printf(string(public)) - if *pkey == "modulus" { - var certaPublicKey = certa.PublicKey.(*gost3410.PublicKey) - fmt.Printf("Public.X=%X\n", certaPublicKey.X) - fmt.Printf("Public.Y=%X\n", certaPublicKey.Y) - os.Exit(0) + fmt.Printf("ED25519 Public-Key:\n") + fmt.Printf("pub: \n") + splitz := SplitSubN(hex.EncodeToString(derBytes)[24:], 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) } + var spki struct { + Algorithm pkix.AlgorithmIdentifier + SubjectPublicKey asn1.BitString + } + _, err = asn1.Unmarshal(derBytes, &spki) + if err != nil { + log.Fatal(err) + } + skid := sha1.Sum(spki.SubjectPublicKey.Bytes) + fmt.Printf("\nKeyID: %x \n", skid) + } else if strings.ToUpper(*alg) == "X25519" { + publicKey := publicInterface.(*ecdh.PublicKey) + derBytes, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + log.Fatal(err) + } + block := &pem.Block{ + Type: "PUBLIC KEY", + Bytes: derBytes, + } + public := pem.EncodeToMemory(block) + fmt.Printf(string(public)) - var buf2 bytes.Buffer - buf2.Grow(4096) - - buf2.WriteString(fmt.Sprintf("Certificate:\n")) - buf2.WriteString(fmt.Sprintf("%4sData:\n", "")) - printVersion(certa.Version, &buf2) - buf2.WriteString(fmt.Sprintf("%8sSerial Number : %d (%X)\n", "", certa.SerialNumber, certa.SerialNumber)) - buf2.WriteString(fmt.Sprintf("%8sCommonName : %s \n", "", certa.Subject.CommonName)) - buf2.WriteString(fmt.Sprintf("%8sEmailAddresses: %s \n", "", certa.EmailAddresses)) - buf2.WriteString(fmt.Sprintf("%8sIsCA : %v \n", "", certa.IsCA)) - - buf2.WriteString(fmt.Sprintf("%8sCurve : %s \n", "", certa.PublicKey.(*gost3410.PublicKey).C.Name)) - - buf2.WriteString(fmt.Sprintf("%8sIssuer\n ", "")) - printName(certa.Issuer.Names, &buf2) - buf2.WriteString(fmt.Sprintf("%8sSubject\n ", "")) - printName(certa.Subject.Names, &buf2) - - buf2.WriteString(fmt.Sprintf("%8sValidity\n", "")) - buf2.WriteString(fmt.Sprintf("%12sNot Before: %s\n", "", certa.NotBefore.Format("Jan 2 15:04:05 2006 MST"))) - buf2.WriteString(fmt.Sprintf("%12sNot After : %s\n", "", certa.NotAfter.Format("Jan 2 15:04:05 2006 MST"))) + fmt.Printf("X25519 Public-Key:\n") + fmt.Printf("pub: \n") + splitz := SplitSubN(hex.EncodeToString(derBytes)[24:], 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + var spki struct { + Algorithm pkix.AlgorithmIdentifier + SubjectPublicKey asn1.BitString + } + _, err = asn1.Unmarshal(derBytes, &spki) + if err != nil { + log.Fatal(err) + } + skid := sha1.Sum(spki.SubjectPublicKey.Bytes) + fmt.Printf("\nKeyID: %x \n", skid) + } else if strings.ToUpper(*alg) == "EC" { + publicKey := publicInterface.(*ecdsa.PublicKey) + derBytes, err := smx509.MarshalPKIXPublicKey(publicKey) + if err != nil { + log.Fatal(err) + } + block := &pem.Block{ + Type: "PUBLIC KEY", + Bytes: derBytes, + } + public := pem.EncodeToMemory(block) + fmt.Printf(string(public)) - var certaPublicKey = certa.PublicKey.(*gost3410.PublicKey) - x := certaPublicKey.X.Bytes() + fmt.Printf("Public-Key: (%v-bit)\n", publicKey.Curve.Params().BitSize) + x := publicKey.X.Bytes() + if n := len(x); n < 24 && n < 32 && n < 48 && n < 64 { + x = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], x...) + } c := []byte{} c = append(c, x...) - buf2.WriteString(fmt.Sprintf("%8sPub.X\n", "")) + fmt.Printf("pub.X: \n") splitz := SplitSubN(hex.EncodeToString(c), 2) for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - buf2.WriteString(fmt.Sprintf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":"))) + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + y := publicKey.Y.Bytes() + if n := len(y); n < 24 && n < 32 && n < 48 && n < 64 { + y = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], y...) } - y := certaPublicKey.Y.Bytes() c = []byte{} c = append(c, y...) - buf2.WriteString(fmt.Sprintf("%8sPub.Y\n", "")) + fmt.Printf("pub.Y: \n") splitz = SplitSubN(hex.EncodeToString(c), 2) for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { - buf2.WriteString(fmt.Sprintf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":"))) + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) } - - buf2.WriteString(fmt.Sprintf("%8sSubjectKeyId : %x \n", "", certa.SubjectKeyId)) - buf2.WriteString(fmt.Sprintf("%8sAuthorityKeyId: %x \n", "", certa.AuthorityKeyId)) - - printSignature(certa.SignatureAlgorithm, certa.Signature, &buf2) - fmt.Print(buf2.String()) - - ok := time.Now().Before(certa.NotAfter) - fmt.Println("IsValid:", ok) - - if ok { - os.Exit(0) - } else { - os.Exit(1) + fmt.Printf("pub: \n") + x = publicKey.X.Bytes() + y = publicKey.Y.Bytes() + if n := len(x); n < 24 && n < 32 && n < 48 && n < 64 { + x = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], x...) } - } - - pemData, err := ioutil.ReadFile(*cert) - if err != nil { - log.Fatal(err) - } - block, rest := pem.Decode([]byte(pemData)) - if block == nil || len(rest) > 0 { - log.Fatal("Certificate decoding error") - } - - result, err := certinfo.CertificateText(certa.ToX509()) - if err != nil { - log.Fatal(err) - } - fmt.Print(result) - - ok := time.Now().Before(certa.NotAfter) - fmt.Println("IsValid:", ok) - - if ok { - os.Exit(0) - } else { - os.Exit(1) + if n := len(y); n < 24 && n < 32 && n < 48 && n < 64 { + y = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], y...) + } + c = []byte{} + c = append(c, x...) + c = append(c, y...) + c = append([]byte{0x04}, c...) + splitz = SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Printf("Curve: %s\n", publicKey.Params().Name) + } else if strings.ToUpper(*alg) == "GOST2012" { + publicKey := publicInterface.(*gost3410.PublicKey) + derBytes, err := x509.MarshalPKIXPublicKey(publicKey) + if err != nil { + log.Println(err) + } + block = &pem.Block{ + Type: "PUBLIC KEY", + Bytes: derBytes, + } + public := pem.EncodeToMemory(block) + fmt.Printf(string(public)) + fmt.Printf("Public key:\n") + fmt.Printf(" X:%X\n", publicKey.X) + fmt.Printf(" Y:%X\n", publicKey.Y) + fmt.Printf("Curve: %s\n", publicKey.C.Name) } } - if *pkey == "check" && *crl == "" { - var certPEM []byte - file, err := os.Open(*cert) + if (*pkey == "text" || *pkey == "modulus") && PEM == "Private" { + var privPEM []byte + file, err := os.Open(*key) if err != nil { log.Fatal(err) } @@ -7486,119 +7859,199 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) - certPEM = buf - var certPemBlock, _ = pem.Decode([]byte(certPEM)) - var certa, _ = smx509.ParseCertificate(certPemBlock.Bytes) - - pemData, err := ioutil.ReadFile(*cert) - if err != nil { - log.Fatal(err) - } - block, rest := pem.Decode([]byte(pemData)) - if block == nil || len(rest) > 0 { - log.Fatal("Certificate decoding error") + var block *pem.Block + block, _ = pem.Decode(buf) + if block == nil { + errors.New("no valid private key found") } - - signature := fmt.Sprintf("%s", certa.SignatureAlgorithm) - if signature == "ECDSA-SHA256" || signature == "ECDSA-SHA384" || signature == "ECDSA-SHA512" { - *alg = "EC" - } else if signature == "99" { - *alg = "SM2" - } else if signature == "Ed25519" { - *alg = "ED25519" - } else if signature == "SHA256-RSA" || signature == "SHA384-RSA" || signature == "SHA512-RSA" { - *alg = "RSA" - } else if signature == "0" { - *alg = "GOST2012" + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) + if err != nil { + log.Fatal(err) + } + privPEM = pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privKeyBytes}) + } else { + privPEM = buf } + var privateKeyPemBlock, _ = pem.Decode([]byte(privPEM)) + if strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "SM2" { + var privKey, err = smx509.ParseECPrivateKey(privateKeyPemBlock.Bytes) + if err != nil { + log.Fatal(err) + } + derBytes, err := smx509.MarshalPKIXPublicKey(&privKey.PublicKey) + if err != nil { + log.Fatal(err) + } + if *pkey == "modulus" { + fmt.Printf("Public.X=%X\n", privKey.PublicKey.X) + fmt.Printf("Public.Y=%X\n", privKey.PublicKey.Y) + os.Exit(0) + } + fmt.Printf(string(privPEM)) + d := privKey.D.Bytes() + if n := len(d); n < 24 && n < 32 && n < 48 && n < 64 { + d = append(zeroByteSlice()[:(privKey.Curve.Params().BitSize/8)-n], d...) + } + c := []byte{} + c = append(c, d...) + fmt.Printf("Private-Key: (%v-bit)\n", privKey.Curve.Params().BitSize) + fmt.Printf("priv: \n") + splitz := SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } - var h hash.Hash - h = sha256.New() - if signature == "ECDSA-SHA256" { - h = sha256.New() - } else if signature == "ECDSA-SHA384" { - h = sha512.New384() - } else if signature == "ECDSA-SHA512" { - h = sha512.New() - } else if signature == "SHA384-RSA" { - h = sha512.New384() - } else if signature == "SHA512-RSA" { - h = sha512.New() - } else if signature == "SHA1-RSA" { - h = sha1.New() - } + publicKey := privKey.PublicKey + fmt.Printf("pub: \n") + x := publicKey.X.Bytes() + y := publicKey.Y.Bytes() + if n := len(x); n < 24 && n < 32 && n < 48 && n < 64 { + x = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], x...) + } + if n := len(y); n < 24 && n < 32 && n < 48 && n < 64 { + y = append(zeroByteSlice()[:(publicKey.Curve.Params().BitSize/8)-n], y...) + } + c = []byte{} + c = append(c, x...) + c = append(c, y...) + c = append([]byte{0x04}, c...) + splitz = SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + var spki struct { + Algorithm pkix.AlgorithmIdentifier + SubjectPublicKey asn1.BitString + } + _, err = asn1.Unmarshal(derBytes, &spki) + if err != nil { + log.Fatal(err) + } + fmt.Printf("Curve: %s\n", publicKey.Params().Name) + skid := sha1.Sum(spki.SubjectPublicKey.Bytes) + fmt.Printf("\nKeyID: %x \n", skid) + } else if strings.ToUpper(*alg) == "ED25519" { + var privKey, _ = smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) + if err != nil { + log.Fatal(err) + } + edKey := privKey.(ed25519.PrivateKey) - var verifystatus bool - h.Write(certa.RawTBSCertificate) - hash_data := h.Sum(nil) + if *pkey == "modulus" { + fmt.Printf("Public=%X\n", edKey.Public()) + os.Exit(0) + } - file, err = os.Open(*key) - if err != nil { - log.Fatal(err) - } - info, err = file.Stat() - if err != nil { - log.Fatal(err) - } - buf = make([]byte, info.Size()) - file.Read(buf) - block, _ = pem.Decode(buf) + fmt.Printf(string(privPEM)) + derBytes, err := smx509.MarshalPKIXPublicKey(edKey.Public()) + if err != nil { + log.Fatal(err) + } + fmt.Printf("ED25519 Private-Key:\n") + p := fmt.Sprintf("%x", privKey) + fmt.Printf("priv: \n") + splitz := SplitSubN(p[:64], 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Printf("pub: \n") + splitz = SplitSubN(p[64:], 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } - publicKey, err := x509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - publicKey, err = smx509.ParsePKIXPublicKey(block.Bytes) - } - if *alg == "EC" { - verifystatus = ecdsa.VerifyASN1(publicKey.(*ecdsa.PublicKey), hash_data, certa.Signature) - } else if *alg == "RSA" { - if signature == "SHA256-RSA" { - err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA256, hash_data, certa.Signature) - } else if signature == "SHA384-RSA" { - err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA384, hash_data, certa.Signature) - h = sha512.New384() - } else if signature == "SHA512-RSA" { - err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA512, hash_data, certa.Signature) - h = sha512.New() - } else if signature == "SHA1-RSA" { - err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA1, hash_data, certa.Signature) - h = sha1.New() + var spki struct { + Algorithm pkix.AlgorithmIdentifier + SubjectPublicKey asn1.BitString } + _, err = asn1.Unmarshal(derBytes, &spki) if err != nil { - verifystatus = false - } else { - verifystatus = true + log.Fatal(err) } - } else if *alg == "SM2" { - verifystatus = sm2.VerifyASN1WithSM2(publicKey.(*ecdsa.PublicKey), nil, certa.RawTBSCertificate, certa.Signature) - } else if *alg == "ED25519" { - verifystatus = ed25519.Verify(publicKey.(ed25519.PublicKey), certa.RawTBSCertificate, certa.Signature) - } else if *alg == "GOST2012" { - var certa, _ = x509.ParseCertificate(certPemBlock.Bytes) - signature := fmt.Sprintf("%s", certa.SignatureAlgorithm) - if signature == "GOST512" { - h = gost34112012512.New() - } else { - h = gost34112012256.New() + skid := sha1.Sum(spki.SubjectPublicKey.Bytes) + fmt.Printf("\nKeyID: %x \n", skid) + } else if strings.ToUpper(*alg) == "X25519" { + var privKey, _ = smx509.ParsePKCS8PrivateKey(privateKeyPemBlock.Bytes) + if err != nil { + log.Fatal(err) } - h.Write(certa.RawTBSCertificate) - hash_data := h.Sum(nil) - reverseBytes(hash_data) - verifystatus, err = publicKey.(*gost3410.PublicKey).VerifyDigest(hash_data, certa.Signature) + edKey := privKey.(*ecdh.PrivateKey) + fmt.Printf(string(privPEM)) + derBytes, err := x509.MarshalPKIXPublicKey(edKey.Public()) if err != nil { log.Fatal(err) } - } + fmt.Printf("X25519 Private-Key:\n") + p := fmt.Sprintf("%x", edKey.Bytes()) + fmt.Printf("priv: \n") + splitz := SplitSubN(p, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + p = fmt.Sprintf("%x", edKey.PublicKey().Bytes()) + fmt.Printf("pub: \n") + splitz = SplitSubN(p, 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } - fmt.Println("Verified:", verifystatus) - if verifystatus { - os.Exit(0) - } else { - os.Exit(1) + var spki struct { + Algorithm pkix.AlgorithmIdentifier + SubjectPublicKey asn1.BitString + } + _, err = asn1.Unmarshal(derBytes, &spki) + if err != nil { + log.Fatal(err) + } + skid := sha1.Sum(spki.SubjectPublicKey.Bytes) + fmt.Printf("\nKeyID: %x \n", skid) + } else if strings.ToUpper(*alg) == "RSA" { + var privKey, _ = x509.ParsePKCS1PrivateKey(privateKeyPemBlock.Bytes) + if err := privKey.Validate(); err != nil { + panic("error validating the private key: " + err.Error()) + } + var privKeyPublicKey = privKey.PublicKey + + if *pkey == "modulus" { + fmt.Printf("Modulus=%X\n", privKey.N) + os.Exit(0) + } + fmt.Printf(string(privPEM)) + fmt.Printf("RSA Private-Key: (%v-bit)\n", privKey.N.BitLen()) + fmt.Printf("Modulus: \n") + m := privKeyPublicKey.N.Bytes() + b, _ := hex.DecodeString("00") + c := []byte{} + c = append(c, b...) + c = append(c, m...) + splitz := SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + fmt.Printf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":")) + } + fmt.Printf("Exponent: %X\n\n", privKeyPublicKey.E) + derBytes, err := x509.MarshalPKIXPublicKey(&privKeyPublicKey) + if err != nil { + log.Fatal(err) + } + + var spki struct { + Algorithm pkix.AlgorithmIdentifier + SubjectPublicKey asn1.BitString + } + _, err = asn1.Unmarshal(derBytes, &spki) + if err != nil { + log.Fatal(err) + } + skid := sha1.Sum(spki.SubjectPublicKey.Bytes) + fmt.Printf("KeyID: %x \n", skid) } } - if *pkey == "certgen" { - file, err := os.Open(*key) + if (*pkey == "text" || *pkey == "modulus" || *pkey == "info") && (PEM == "Certificate") { + var certPEM []byte + file, err := os.Open(*cert) if err != nil { log.Fatal(err) } @@ -7608,205 +8061,163 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) + certPEM = buf + var certPemBlock, _ = pem.Decode([]byte(certPEM)) + var certa, _ = smx509.ParseCertificate(certPemBlock.Bytes) - var priv interface{} + signature := fmt.Sprintf("%s", certa.SignatureAlgorithm) + if signature == "ECDSA-SHA256" || signature == "ECDSA-SHA384" || signature == "ECDSA-SHA512" { + *alg = "EC" + } else if signature == "99" { + *alg = "SM2" + } else if signature == "Ed25519" { + *alg = "ED25519" + } else if signature == "SHA256-RSA" || signature == "SHA384-RSA" || signature == "SHA512-RSA" { + *alg = "RSA" + } else { + *alg = "GOST2012" + } - var block *pem.Block - block, _ = pem.Decode(buf) + if *pkey == "modulus" && strings.ToUpper(*alg) == "RSA" { + var certaPublicKey = certa.PublicKey.(*rsa.PublicKey) + fmt.Printf("Modulus=%X\n", certaPublicKey.N) + os.Exit(0) + } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "SM2") { + var certaPublicKey = certa.PublicKey.(*ecdsa.PublicKey) + fmt.Printf("Public.X=%X\n", certaPublicKey.X) + fmt.Printf("Public.Y=%X\n", certaPublicKey.Y) + os.Exit(0) + } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "ED25519") { + var certaPublicKey = certa.PublicKey.(ed25519.PublicKey) + fmt.Printf("Public=%X\n", certaPublicKey) + os.Exit(0) + } else if *pkey == "modulus" && (strings.ToUpper(*alg) == "GOST2012") { + var certa, _ = x509.ParseCertificate(certPemBlock.Bytes) + var certaPublicKey = certa.PublicKey.(*gost3410.PublicKey) + fmt.Printf("Public.X=%X\n", certaPublicKey.X) + fmt.Printf("Public.Y=%X\n", certaPublicKey.Y) + os.Exit(0) + } - if strings.ToUpper(*alg) == "ED25519" { - var priva interface{} - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) - if err != nil { - log.Fatal(err) - } - priva, err = x509.ParsePKCS8PrivateKey(privKeyBytes) - if err != nil { - log.Fatal(err) - } - } else { - priva, err = x509.ParsePKCS8PrivateKey(block.Bytes) - if err != nil { - log.Fatal(err) - } - } - priv = priva - } else if strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA" { - var privateKey *ecdsa.PrivateKey - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) - if err != nil { - log.Fatal(err) - } - privateKey, err = smx509.ParseECPrivateKey(privKeyBytes) - if err != nil { - log.Fatal(err) - } - } else { - privateKey, err = smx509.ParseECPrivateKey(block.Bytes) - if err != nil { - log.Fatal(err) - } - } - priv = privateKey - } else if strings.ToUpper(*alg) == "SM2" { - var privateKey *sm2.PrivateKey - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) - if err != nil { - log.Fatal(err) - } - privateKey, err = smx509.ParseSM2PrivateKey(privKeyBytes) - if err != nil { - log.Fatal(err) - } - } else { - privateKey, err = smx509.ParseSM2PrivateKey(block.Bytes) - if err != nil { - log.Fatal(err) - } - } - priv = privateKey - } else if strings.ToUpper(*alg) == "RSA" { - var privateKey *rsa.PrivateKey - var privKeyBytes []byte - if IsEncryptedPEMBlock(block) { - privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) - if err != nil { - log.Fatal(err) - } - privateKey, err = x509.ParsePKCS1PrivateKey(privKeyBytes) - if err != nil { - log.Fatal(err) - } - } else { - privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - log.Fatal(err) - } - } - priv = privateKey - } - - keyUsage := smx509.KeyUsageDigitalSignature - - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 160) - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - log.Fatalf("Failed to generate serial number: %v", err) + if *pkey == "info" { + fmt.Printf("Expiry: %s \n", certa.NotAfter.Format("Monday, 02-Jan-06 15:04:05 MST")) + fmt.Printf("Common Name: %s \n", certa.Issuer.CommonName) + fmt.Printf("EmailAddresses: %s \n", certa.EmailAddresses) + fmt.Printf("IP Address: %s \n", certa.IPAddresses) + fmt.Printf("DNSNames: %s \n", certa.DNSNames) + fmt.Printf("SerialNumber: %x \n", certa.SerialNumber) + fmt.Printf("SubjectKeyId: %x \n", certa.SubjectKeyId) + fmt.Printf("AuthorityKeyId: %x \n", certa.AuthorityKeyId) + os.Exit(0) } - println("You are about to be asked to enter information \nthat will be incorporated into your certificate.") - - scanner := bufio.NewScanner(os.Stdin) - - print("Common Name: ") - scanner.Scan() - name := scanner.Text() - - print("Country Name (2 letter code) [AU]: ") - scanner.Scan() - country := scanner.Text() - - print("State or Province Name (full name) [Some-State]: ") - scanner.Scan() - province := scanner.Text() - - print("Locality Name (eg, city): ") - scanner.Scan() - locality := scanner.Text() - - print("Organization Name (eg, company) [Internet Widgits Pty Ltd]: ") - scanner.Scan() - organization := scanner.Text() - - print("Organizational Unit Name (eg, section): ") - scanner.Scan() - organizationunit := scanner.Text() - - print("Email Address []: ") - scanner.Scan() - email := scanner.Text() + if *alg == "GOST2012" { + var certPEM []byte + file, err := os.Open(*cert) + if err != nil { + log.Println(err) + } + info, err := file.Stat() + if err != nil { + log.Println(err) + } + buf := make([]byte, info.Size()) + file.Read(buf) + certPEM = buf + var certPemBlock, _ = pem.Decode([]byte(certPEM)) + var certa, _ = x509.ParseCertificate(certPemBlock.Bytes) - print("StreetAddress: ") - scanner.Scan() - street := scanner.Text() + if *pkey == "modulus" { + var certaPublicKey = certa.PublicKey.(*gost3410.PublicKey) + fmt.Printf("Public.X=%X\n", certaPublicKey.X) + fmt.Printf("Public.Y=%X\n", certaPublicKey.Y) + os.Exit(0) + } - print("PostalCode: ") - scanner.Scan() - postalcode := scanner.Text() + var buf2 bytes.Buffer + buf2.Grow(4096) - print("SerialNumber: ") - scanner.Scan() - number := scanner.Text() + buf2.WriteString(fmt.Sprintf("Certificate:\n")) + buf2.WriteString(fmt.Sprintf("%4sData:\n", "")) + printVersion(certa.Version, &buf2) + buf2.WriteString(fmt.Sprintf("%8sSerial Number : %d (%X)\n", "", certa.SerialNumber, certa.SerialNumber)) + buf2.WriteString(fmt.Sprintf("%8sCommonName : %s \n", "", certa.Subject.CommonName)) + buf2.WriteString(fmt.Sprintf("%8sEmailAddresses: %s \n", "", certa.EmailAddresses)) + buf2.WriteString(fmt.Sprintf("%8sIsCA : %v \n", "", certa.IsCA)) - print("Validity (in Days): ") - scanner.Scan() - validity := scanner.Text() + buf2.WriteString(fmt.Sprintf("%8sCurve : %s \n", "", certa.PublicKey.(*gost3410.PublicKey).C.Name)) - intVar, err := strconv.Atoi(validity) - NotAfter := time.Now().AddDate(0, 0, intVar) + buf2.WriteString(fmt.Sprintf("%8sIssuer\n ", "")) + printName(certa.Issuer.Names, &buf2) + buf2.WriteString(fmt.Sprintf("%8sSubject\n ", "")) + printName(certa.Subject.Names, &buf2) - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - CommonName: name, - SerialNumber: number, - Country: []string{country}, - Province: []string{province}, - Locality: []string{locality}, - Organization: []string{organization}, - OrganizationalUnit: []string{organizationunit}, - StreetAddress: []string{street}, - PostalCode: []string{postalcode}, - }, - EmailAddresses: []string{email}, + buf2.WriteString(fmt.Sprintf("%8sValidity\n", "")) + buf2.WriteString(fmt.Sprintf("%12sNot Before: %s\n", "", certa.NotBefore.Format("Jan 2 15:04:05 2006 MST"))) + buf2.WriteString(fmt.Sprintf("%12sNot After : %s\n", "", certa.NotAfter.Format("Jan 2 15:04:05 2006 MST"))) - NotBefore: time.Now(), - NotAfter: NotAfter, + var certaPublicKey = certa.PublicKey.(*gost3410.PublicKey) + x := certaPublicKey.X.Bytes() + c := []byte{} + c = append(c, x...) + buf2.WriteString(fmt.Sprintf("%8sPub.X\n", "")) + splitz := SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + buf2.WriteString(fmt.Sprintf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":"))) + } + y := certaPublicKey.Y.Bytes() + c = []byte{} + c = append(c, y...) + buf2.WriteString(fmt.Sprintf("%8sPub.Y\n", "")) + splitz = SplitSubN(hex.EncodeToString(c), 2) + for _, chunk := range split(strings.Trim(fmt.Sprint(splitz), "[]"), 45) { + buf2.WriteString(fmt.Sprintf(" %-10s \n", strings.ReplaceAll(chunk, " ", ":"))) + } - KeyUsage: keyUsage, - ExtKeyUsage: []smx509.ExtKeyUsage{smx509.ExtKeyUsageClientAuth, smx509.ExtKeyUsageServerAuth}, - BasicConstraintsValid: true, - IsCA: true, + buf2.WriteString(fmt.Sprintf("%8sSubjectKeyId : %x \n", "", certa.SubjectKeyId)) + buf2.WriteString(fmt.Sprintf("%8sAuthorityKeyId: %x \n", "", certa.AuthorityKeyId)) - PermittedDNSDomainsCritical: true, - } + printSignature(certa.SignatureAlgorithm, certa.Signature, &buf2) + fmt.Print(buf2.String()) - template.IsCA = true - template.KeyUsage |= smx509.KeyUsageCertSign | smx509.KeyUsageCRLSign | x509.KeyUsageContentCommitment | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement + ok := time.Now().Before(certa.NotAfter) + fmt.Println("IsValid:", ok) - if strings.ToUpper(*alg) == "RSA" { - if *md == "sha256" { - template.SignatureAlgorithm = smx509.SHA256WithRSA - } else if *md == "sha384" { - template.SignatureAlgorithm = smx509.SHA384WithRSA - } else if *md == "sha512" { - template.SignatureAlgorithm = smx509.SHA512WithRSA - } else if *md == "sha1" { - template.SignatureAlgorithm = smx509.SHA1WithRSA + if ok { + os.Exit(0) + } else { + os.Exit(1) } } - derBytes, err := smx509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) + pemData, err := ioutil.ReadFile(*cert) if err != nil { - log.Fatalf("Failed to create certificate: %v", err) + log.Fatal(err) + } + block, rest := pem.Decode([]byte(pemData)) + if block == nil || len(rest) > 0 { + log.Fatal("Certificate decoding error") } - certfile, err := os.Create(*cert) + result, err := certinfo.CertificateText(certa.ToX509()) if err != nil { log.Fatal(err) } - pem.Encode(certfile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - os.Exit(0) + fmt.Print(result) + + ok := time.Now().Before(certa.NotAfter) + fmt.Println("IsValid:", ok) + + if ok { + os.Exit(0) + } else { + os.Exit(1) + } } - if *pkey == "req" && *key != "" { - file, err := os.Open(*key) + if *pkey == "check" && *crl == "" { + var certPEM []byte + file, err := os.Open(*cert) if err != nil { log.Fatal(err) } @@ -7816,14 +8227,136 @@ Subcommands: } buf := make([]byte, info.Size()) file.Read(buf) + certPEM = buf + var certPemBlock, _ = pem.Decode([]byte(certPEM)) + var certa, _ = smx509.ParseCertificate(certPemBlock.Bytes) - var keyBytes interface{} - - var block *pem.Block - block, _ = pem.Decode(buf) + pemData, err := ioutil.ReadFile(*cert) + if err != nil { + log.Fatal(err) + } + block, rest := pem.Decode([]byte(pemData)) + if block == nil || len(rest) > 0 { + log.Fatal("Certificate decoding error") + } - if strings.ToUpper(*alg) == "ED25519" { - var priva interface{} + signature := fmt.Sprintf("%s", certa.SignatureAlgorithm) + if signature == "ECDSA-SHA256" || signature == "ECDSA-SHA384" || signature == "ECDSA-SHA512" { + *alg = "EC" + } else if signature == "99" { + *alg = "SM2" + } else if signature == "Ed25519" { + *alg = "ED25519" + } else if signature == "SHA256-RSA" || signature == "SHA384-RSA" || signature == "SHA512-RSA" { + *alg = "RSA" + } else if signature == "0" { + *alg = "GOST2012" + } + + var h hash.Hash + h = sha256.New() + if signature == "ECDSA-SHA256" { + h = sha256.New() + } else if signature == "ECDSA-SHA384" { + h = sha512.New384() + } else if signature == "ECDSA-SHA512" { + h = sha512.New() + } else if signature == "SHA384-RSA" { + h = sha512.New384() + } else if signature == "SHA512-RSA" { + h = sha512.New() + } else if signature == "SHA1-RSA" { + h = sha1.New() + } + + var verifystatus bool + h.Write(certa.RawTBSCertificate) + hash_data := h.Sum(nil) + + file, err = os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err = file.Stat() + if err != nil { + log.Fatal(err) + } + buf = make([]byte, info.Size()) + file.Read(buf) + block, _ = pem.Decode(buf) + + publicKey, err := x509.ParsePKIXPublicKey(block.Bytes) + if err != nil { + publicKey, err = smx509.ParsePKIXPublicKey(block.Bytes) + } + if *alg == "EC" { + verifystatus = ecdsa.VerifyASN1(publicKey.(*ecdsa.PublicKey), hash_data, certa.Signature) + } else if *alg == "RSA" { + if signature == "SHA256-RSA" { + err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA256, hash_data, certa.Signature) + } else if signature == "SHA384-RSA" { + err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA384, hash_data, certa.Signature) + h = sha512.New384() + } else if signature == "SHA512-RSA" { + err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA512, hash_data, certa.Signature) + h = sha512.New() + } else if signature == "SHA1-RSA" { + err = rsa.VerifyPKCS1v15(publicKey.(*rsa.PublicKey), crypto.SHA1, hash_data, certa.Signature) + h = sha1.New() + } + if err != nil { + verifystatus = false + } else { + verifystatus = true + } + } else if *alg == "SM2" { + verifystatus = sm2.VerifyASN1WithSM2(publicKey.(*ecdsa.PublicKey), nil, certa.RawTBSCertificate, certa.Signature) + } else if *alg == "ED25519" { + verifystatus = ed25519.Verify(publicKey.(ed25519.PublicKey), certa.RawTBSCertificate, certa.Signature) + } else if *alg == "GOST2012" { + var certa, _ = x509.ParseCertificate(certPemBlock.Bytes) + signature := fmt.Sprintf("%s", certa.SignatureAlgorithm) + if signature == "GOST512" { + h = gost34112012512.New() + } else { + h = gost34112012256.New() + } + h.Write(certa.RawTBSCertificate) + hash_data := h.Sum(nil) + reverseBytes(hash_data) + verifystatus, err = publicKey.(*gost3410.PublicKey).VerifyDigest(hash_data, certa.Signature) + if err != nil { + log.Fatal(err) + } + } + + fmt.Println("Verified:", verifystatus) + if verifystatus { + os.Exit(0) + } else { + os.Exit(1) + } + } + + if *pkey == "certgen" { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) + } + buf := make([]byte, info.Size()) + file.Read(buf) + + var priv interface{} + + var block *pem.Block + block, _ = pem.Decode(buf) + + if strings.ToUpper(*alg) == "ED25519" { + var priva interface{} var privKeyBytes []byte if IsEncryptedPEMBlock(block) { privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) @@ -7840,7 +8373,7 @@ Subcommands: log.Fatal(err) } } - keyBytes = priva + priv = priva } else if strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA" { var privateKey *ecdsa.PrivateKey var privKeyBytes []byte @@ -7859,7 +8392,7 @@ Subcommands: log.Fatal(err) } } - keyBytes = privateKey + priv = privateKey } else if strings.ToUpper(*alg) == "SM2" { var privateKey *sm2.PrivateKey var privKeyBytes []byte @@ -7878,7 +8411,7 @@ Subcommands: log.Fatal(err) } } - keyBytes = privateKey + priv = privateKey } else if strings.ToUpper(*alg) == "RSA" { var privateKey *rsa.PrivateKey var privKeyBytes []byte @@ -7897,10 +8430,18 @@ Subcommands: log.Fatal(err) } } - keyBytes = privateKey + priv = privateKey } - println("You are about to be asked to enter information that \nwill be incorporated into your certificate request.") + keyUsage := smx509.KeyUsageDigitalSignature + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 160) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + log.Fatalf("Failed to generate serial number: %v", err) + } + + println("You are about to be asked to enter information \nthat will be incorporated into your certificate.") scanner := bufio.NewScanner(os.Stdin) @@ -7944,72 +8485,272 @@ Subcommands: scanner.Scan() number := scanner.Text() - emailAddress := email - subj := pkix.Name{ - CommonName: name, - SerialNumber: number, - Country: []string{country}, - Province: []string{province}, - Locality: []string{locality}, - Organization: []string{organization}, - OrganizationalUnit: []string{organizationunit}, - StreetAddress: []string{street}, - PostalCode: []string{postalcode}, + print("Validity (in Days): ") + scanner.Scan() + validity := scanner.Text() + + intVar, err := strconv.Atoi(validity) + NotAfter := time.Now().AddDate(0, 0, intVar) + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + CommonName: name, + SerialNumber: number, + Country: []string{country}, + Province: []string{province}, + Locality: []string{locality}, + Organization: []string{organization}, + OrganizationalUnit: []string{organizationunit}, + StreetAddress: []string{street}, + PostalCode: []string{postalcode}, + }, + EmailAddresses: []string{email}, + + NotBefore: time.Now(), + NotAfter: NotAfter, + + KeyUsage: keyUsage, + ExtKeyUsage: []smx509.ExtKeyUsage{smx509.ExtKeyUsageClientAuth, smx509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + IsCA: true, + + PermittedDNSDomainsCritical: true, } - rawSubj := subj.ToRDNSequence() - rawSubj = append(rawSubj, []pkix.AttributeTypeAndValue{ - {Type: oidEmailAddress, Value: emailAddress}, - }) - asn1Subj, _ := asn1.Marshal(rawSubj) - var template x509.CertificateRequest + template.IsCA = true + template.KeyUsage |= smx509.KeyUsageCertSign | smx509.KeyUsageCRLSign | x509.KeyUsageContentCommitment | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment | x509.KeyUsageKeyAgreement + if strings.ToUpper(*alg) == "RSA" { - template = x509.CertificateRequest{ - RawSubject: asn1Subj, - EmailAddresses: []string{emailAddress}, - SignatureAlgorithm: x509.SHA256WithRSA, - } - } else if strings.ToUpper(*alg) == "ECDSA" || strings.ToUpper(*alg) == "EC" { - template = x509.CertificateRequest{ - RawSubject: asn1Subj, - EmailAddresses: []string{emailAddress}, - SignatureAlgorithm: x509.ECDSAWithSHA256, - } - } else if strings.ToUpper(*alg) == "SM2" { - template = x509.CertificateRequest{ - RawSubject: asn1Subj, - EmailAddresses: []string{emailAddress}, - SignatureAlgorithm: smx509.SM2WithSM3, - } - } else if strings.ToUpper(*alg) == "ED25519" { - template = x509.CertificateRequest{ - RawSubject: asn1Subj, - EmailAddresses: []string{emailAddress}, - SignatureAlgorithm: x509.PureEd25519, + if *md == "sha256" { + template.SignatureAlgorithm = smx509.SHA256WithRSA + } else if *md == "sha384" { + template.SignatureAlgorithm = smx509.SHA384WithRSA + } else if *md == "sha512" { + template.SignatureAlgorithm = smx509.SHA512WithRSA + } else if *md == "sha1" { + template.SignatureAlgorithm = smx509.SHA1WithRSA } } - var output *os.File - if *cert == "" { - output = os.Stdout - } else { - file, err := os.Create(*cert) - if err != nil { - log.Fatal(err) - } - defer file.Close() - output = file + + derBytes, err := smx509.CreateCertificate(rand.Reader, &template, &template, publicKey(priv), priv) + if err != nil { + log.Fatalf("Failed to create certificate: %v", err) } - csrBytes, _ := smx509.CreateCertificateRequest(rand.Reader, &template, keyBytes) - pem.Encode(output, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) + + certfile, err := os.Create(*cert) + if err != nil { + log.Fatal(err) + } + pem.Encode(certfile, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + os.Exit(0) } - if (*pkey == "crl") && *key != "" && *cert != "" && strings.ToUpper(*alg) != "SM2" { - revokedCerts := make([]pkix.RevokedCertificate, 0) + if *pkey == "req" && *key != "" { + file, err := os.Open(*key) + if err != nil { + log.Fatal(err) + } + info, err := file.Stat() + if err != nil { + log.Fatal(err) + } + buf := make([]byte, info.Size()) + file.Read(buf) - scanner := bufio.NewScanner(inputfile) - existingSerialNumbers := make(map[string]bool) - for scanner.Scan() { - serialStr := strings.TrimSpace(scanner.Text()) + var keyBytes interface{} + + var block *pem.Block + block, _ = pem.Decode(buf) + + if strings.ToUpper(*alg) == "ED25519" { + var priva interface{} + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) + if err != nil { + log.Fatal(err) + } + priva, err = x509.ParsePKCS8PrivateKey(privKeyBytes) + if err != nil { + log.Fatal(err) + } + } else { + priva, err = x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + log.Fatal(err) + } + } + keyBytes = priva + } else if strings.ToUpper(*alg) == "EC" || strings.ToUpper(*alg) == "ECDSA" { + var privateKey *ecdsa.PrivateKey + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) + if err != nil { + log.Fatal(err) + } + privateKey, err = smx509.ParseECPrivateKey(privKeyBytes) + if err != nil { + log.Fatal(err) + } + } else { + privateKey, err = smx509.ParseECPrivateKey(block.Bytes) + if err != nil { + log.Fatal(err) + } + } + keyBytes = privateKey + } else if strings.ToUpper(*alg) == "SM2" { + var privateKey *sm2.PrivateKey + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) + if err != nil { + log.Fatal(err) + } + privateKey, err = smx509.ParseSM2PrivateKey(privKeyBytes) + if err != nil { + log.Fatal(err) + } + } else { + privateKey, err = smx509.ParseSM2PrivateKey(block.Bytes) + if err != nil { + log.Fatal(err) + } + } + keyBytes = privateKey + } else if strings.ToUpper(*alg) == "RSA" { + var privateKey *rsa.PrivateKey + var privKeyBytes []byte + if IsEncryptedPEMBlock(block) { + privKeyBytes, err = DecryptPEMBlock(block, []byte(*pwd)) + if err != nil { + log.Fatal(err) + } + privateKey, err = x509.ParsePKCS1PrivateKey(privKeyBytes) + if err != nil { + log.Fatal(err) + } + } else { + privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil { + log.Fatal(err) + } + } + keyBytes = privateKey + } + + println("You are about to be asked to enter information that \nwill be incorporated into your certificate request.") + + scanner := bufio.NewScanner(os.Stdin) + + print("Common Name: ") + scanner.Scan() + name := scanner.Text() + + print("Country Name (2 letter code) [AU]: ") + scanner.Scan() + country := scanner.Text() + + print("State or Province Name (full name) [Some-State]: ") + scanner.Scan() + province := scanner.Text() + + print("Locality Name (eg, city): ") + scanner.Scan() + locality := scanner.Text() + + print("Organization Name (eg, company) [Internet Widgits Pty Ltd]: ") + scanner.Scan() + organization := scanner.Text() + + print("Organizational Unit Name (eg, section): ") + scanner.Scan() + organizationunit := scanner.Text() + + print("Email Address []: ") + scanner.Scan() + email := scanner.Text() + + print("StreetAddress: ") + scanner.Scan() + street := scanner.Text() + + print("PostalCode: ") + scanner.Scan() + postalcode := scanner.Text() + + print("SerialNumber: ") + scanner.Scan() + number := scanner.Text() + + emailAddress := email + subj := pkix.Name{ + CommonName: name, + SerialNumber: number, + Country: []string{country}, + Province: []string{province}, + Locality: []string{locality}, + Organization: []string{organization}, + OrganizationalUnit: []string{organizationunit}, + StreetAddress: []string{street}, + PostalCode: []string{postalcode}, + } + rawSubj := subj.ToRDNSequence() + rawSubj = append(rawSubj, []pkix.AttributeTypeAndValue{ + {Type: oidEmailAddress, Value: emailAddress}, + }) + + asn1Subj, _ := asn1.Marshal(rawSubj) + var template x509.CertificateRequest + if strings.ToUpper(*alg) == "RSA" { + template = x509.CertificateRequest{ + RawSubject: asn1Subj, + EmailAddresses: []string{emailAddress}, + SignatureAlgorithm: x509.SHA256WithRSA, + } + } else if strings.ToUpper(*alg) == "ECDSA" || strings.ToUpper(*alg) == "EC" { + template = x509.CertificateRequest{ + RawSubject: asn1Subj, + EmailAddresses: []string{emailAddress}, + SignatureAlgorithm: x509.ECDSAWithSHA256, + } + } else if strings.ToUpper(*alg) == "SM2" { + template = x509.CertificateRequest{ + RawSubject: asn1Subj, + EmailAddresses: []string{emailAddress}, + SignatureAlgorithm: smx509.SM2WithSM3, + } + } else if strings.ToUpper(*alg) == "ED25519" { + template = x509.CertificateRequest{ + RawSubject: asn1Subj, + EmailAddresses: []string{emailAddress}, + SignatureAlgorithm: x509.PureEd25519, + } + } + var output *os.File + if *cert == "" { + output = os.Stdout + } else { + file, err := os.Create(*cert) + if err != nil { + log.Fatal(err) + } + defer file.Close() + output = file + } + csrBytes, _ := smx509.CreateCertificateRequest(rand.Reader, &template, keyBytes) + pem.Encode(output, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) + } + + if (*pkey == "crl") && *key != "" && *cert != "" && strings.ToUpper(*alg) != "SM2" { + revokedCerts := make([]pkix.RevokedCertificate, 0) + + scanner := bufio.NewScanner(inputfile) + existingSerialNumbers := make(map[string]bool) + for scanner.Scan() { + serialStr := strings.TrimSpace(scanner.Text()) serialNumber, success := new(big.Int).SetString(serialStr, 16) if !success { log.Fatalf("Invalid serial number: %s", serialStr) @@ -10958,16 +11699,10 @@ func savePEMPrivateKey(filename string, keyBytes []byte, passphrase string, twea "Scrypt-Itering": strconv.Itoa(*iter), } - if strings.ToUpper(*cph) == "THREEFISH256" { - headers["DEK-Info"] = fmt.Sprintf("THREEFISH256-CFB,TWEAK,%s", tweak) - } else if strings.ToUpper(*cph) == "THREEFISH512" { - headers["DEK-Info"] = fmt.Sprintf("THREEFISH512-CFB,TWEAK,%s", tweak) - } else if strings.ToUpper(*cph) == "THREEFISH1024" { - headers["DEK-Info"] = fmt.Sprintf("THREEFISH1024-CFB,TWEAK,%s", tweak) - } else if strings.ToUpper(*cph) == "ANUBIS" { - headers["DEK-Info"] = fmt.Sprintf("ANUBIS-CFB") + if strings.ToUpper(*cph) == "ANUBIS" { + headers["DEK-Info"] = fmt.Sprintf("ANUBIS") } else if strings.ToUpper(*cph) == "AES" { - headers["DEK-Info"] = fmt.Sprintf("AES-CFB") + headers["DEK-Info"] = fmt.Sprintf("AES") } privKeyInfo := &pem.Block{ @@ -11010,13 +11745,8 @@ func loadPEMKey(filename string, passphrase string) ([]byte, error) { } dekInfo := block.Headers["DEK-Info"] - tweak := "" if dekInfo != "" { parts := strings.Split(dekInfo, ",") - if len(parts) == 3 && parts[1] == "TWEAK" { - tweak = parts[2] - } - *info = tweak *cph = strings.TrimSuffix(strings.ToLower(parts[0]), "-cfb") } *md = strings.ToLower(block.Headers["Hash-Algorithm"]) @@ -11052,123 +11782,78 @@ func encryptKey(key []byte, passphrase string) ([]byte, error) { return nil, err } - var tweak []byte - tweak = make([]byte, 16) - if *info != "" { - tweak = []byte(*info) - } - - var n int var block cipher.Block - if *cph == "threefish256" { - block, err = threefish.New256(derivedKey[:32], tweak) - if err != nil { - return nil, err - } - n = 32 - } else if *cph == "threefish512" { - block, err = threefish.New512(derivedKey[:64], tweak) - if err != nil { - return nil, err - } - n = 64 - } else if *cph == "threefish1024" { - block, err = threefish.New1024(derivedKey, tweak) + if *cph == "aes" { + block, err = aes.NewCipher(derivedKey[:32]) if err != nil { return nil, err } - n = 128 } else if *cph == "anubis" { block, err = anubis.NewWithKeySize(derivedKey, 40) if err != nil { return nil, err } - n = 16 - } else if *cph == "aes" { - block, err = aes.NewCipher(derivedKey[:32]) - if err != nil { - return nil, err - } - n = 16 + } else { + return nil, fmt.Errorf("Unsupported cipher") + } + + aesGCM, err := cipher.NewGCM(block) + if err != nil { + return nil, err } - ciphertext := make([]byte, n+len(key)) - iv := ciphertext[:n] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { + nonce := make([]byte, aesGCM.NonceSize()) + if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return nil, err } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[n:], key) + ciphertext := aesGCM.Seal(nil, nonce, key, nil) - return append(salt, ciphertext...), nil + return append(salt, append(nonce, ciphertext...)...), nil } func decryptKey(ciphertext []byte, passphrase string) ([]byte, error) { salt := ciphertext[:16] - encryptedKey := ciphertext[16:] + nonce := ciphertext[16 : 16+12] + encryptedKey := ciphertext[16+12:] derivedKey, err := deriveKey(passphrase, salt) if err != nil { return nil, err } - var tweak []byte - tweak = make([]byte, 16) - if *info != "" { - tweak = []byte(*info) - } - /* - block, err := threefish.New512(derivedKey, tweak) - if err != nil { - return nil, err - } - */ - var n int var block cipher.Block - if *cph == "threefish256" { - block, err = threefish.New256(derivedKey[:32], tweak) - if err != nil { - return nil, err - } - n = 32 - } else if *cph == "threefish512" { - block, err = threefish.New512(derivedKey[:64], tweak) - if err != nil { - return nil, err - } - n = 64 - } else if *cph == "threefish1024" { - block, err = threefish.New1024(derivedKey, tweak) + if *cph == "aes" { + block, err = aes.NewCipher(derivedKey[:32]) if err != nil { return nil, err } - n = 128 } else if *cph == "anubis" { block, err = anubis.NewWithKeySize(derivedKey, 40) if err != nil { return nil, err } - n = 16 - } else if *cph == "aes" { - block, err = aes.NewCipher(derivedKey[:32]) - if err != nil { - return nil, err - } - n = 16 + } else { + return nil, fmt.Errorf("unsupported cipher") } - iv := encryptedKey[:n] - encryptedKey = encryptedKey[n:] + aesGCM, err := cipher.NewGCM(block) + if err != nil { + return nil, err + } - stream := cipher.NewCFBDecrypter(block, iv) - stream.XORKeyStream(encryptedKey, encryptedKey) + decryptedKey, err := aesGCM.Open(nil, nonce, encryptedKey, nil) + if err != nil { + return nil, err + } - return encryptedKey, nil + return decryptedKey, nil } func generateKeyPair(privPath, pubPath string) { params := parameters.MakeSphincsPlusSHAKE256256fRobust(true) + fmt.Printf("SPHINCS+ Parameters\nN=%d, W=%d, Hprime=%d, H=%d, D=%d, K=%d, T=%d, LogT=%d, A=%d\n", params.N, params.W, params.Hprime, + params.H, params.D, params.K, params.T, params.LogT, params.A) sk, pk := sphincs.Spx_keygen(params) serializedSK, err := sk.SerializeSK() @@ -11214,7 +11899,7 @@ func generateKeyPair(privPath, pubPath string) { fingerprint := calculateFingerprint(buf) print("Fingerprint: ") println(fingerprint) - println("SPHINCS+ (512-bit)") + println("SPHINCS+ (256-bit)") randomArt := randomart.FromString(string(buf)) println(randomArt) } @@ -11372,7 +12057,7 @@ func printPublicKeyParamsFull(pk *sphincs.SPHINCS_PK) { } pem.Encode(os.Stdout, block) - fmt.Printf("PublicKey: (512-bit)\n") + fmt.Printf("PublicKey: (256-bit)\n") fmt.Printf("PK: \n") splitz := SplitSubN(hex.EncodeToString(serializedPK), 2) @@ -11405,7 +12090,7 @@ func printPrivateKeyParamsFull(sk *sphincs.SPHINCS_SK) { } pem.Encode(os.Stdout, block) - fmt.Printf("SecretKey: (512-bit)\n") + fmt.Printf("SecretKey: (256-bit)\n") /* fmt.Printf("SK: \n") splitz := SplitSubN(hex.EncodeToString(serializedSK), 2) @@ -11650,137 +12335,921 @@ var rfc1423Algos = []rfc1423Algo{{ }, } -func (c rfc1423Algo) deriveKey(password, salt []byte) []byte { - hash := md5.New() - out := make([]byte, c.keySize) - var digest []byte +func (c rfc1423Algo) deriveKey(password, salt []byte) []byte { + hash := md5.New() + out := make([]byte, c.keySize) + var digest []byte + + for i := 0; i < len(out); i += len(digest) { + hash.Reset() + hash.Write(digest) + hash.Write(password) + hash.Write(salt) + digest = hash.Sum(digest[:0]) + copy(out[i:], digest) + } + return out +} + +func IsEncryptedPEMBlock(b *pem.Block) bool { + _, ok := b.Headers["DEK-Info"] + return ok +} + +var IncorrectPasswordError = errors.New("x509: decryption password incorrect") + +func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { + dek, ok := b.Headers["DEK-Info"] + if !ok { + return nil, errors.New("x509: no DEK-Info header in block") + } + + idx := strings.Index(dek, ",") + if idx == -1 { + return nil, errors.New("x509: malformed DEK-Info header") + } + + mode, hexIV := dek[:idx], dek[idx+1:] + ciph := cipherByName(mode) + if ciph == nil { + return nil, errors.New("x509: unknown encryption mode") + } + iv, err := hex.DecodeString(hexIV) + if err != nil { + return nil, err + } + if len(iv) != ciph.blockSize { + return nil, errors.New("x509: incorrect IV size") + } + + key := ciph.deriveKey(password, iv[:8]) + block, err := ciph.cipherFunc(key) + if err != nil { + return nil, err + } + + if len(b.Bytes)%block.BlockSize() != 0 { + return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size") + } + + data := make([]byte, len(b.Bytes)) + dec := cipher.NewCBCDecrypter(block, iv) + dec.CryptBlocks(data, b.Bytes) + + dlen := len(data) + if dlen == 0 || dlen%ciph.blockSize != 0 { + return nil, errors.New("x509: invalid padding") + } + last := int(data[dlen-1]) + if dlen < last { + return nil, IncorrectPasswordError + } + if last == 0 || last > ciph.blockSize { + return nil, IncorrectPasswordError + } + for _, val := range data[dlen-last:] { + if int(val) != last { + return nil, IncorrectPasswordError + } + } + return data[:dlen-last], nil +} + +func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) { + ciph := cipherByKey(alg) + if ciph == nil { + return nil, errors.New("x509: unknown encryption mode") + } + iv := make([]byte, ciph.blockSize) + if _, err := io.ReadFull(rand, iv); err != nil { + return nil, errors.New("x509: cannot generate IV: " + err.Error()) + } + key := ciph.deriveKey(password, iv[:8]) + block, err := ciph.cipherFunc(key) + if err != nil { + return nil, err + } + enc := cipher.NewCBCEncrypter(block, iv) + pad := ciph.blockSize - len(data)%ciph.blockSize + encrypted := make([]byte, len(data), len(data)+pad) + copy(encrypted, data) + for i := 0; i < pad; i++ { + encrypted = append(encrypted, byte(pad)) + } + enc.CryptBlocks(encrypted, encrypted) + + return &pem.Block{ + Type: blockType, + Headers: map[string]string{ + "Proc-Type": "4,ENCRYPTED", + "DEK-Info": ciph.name + "," + hex.EncodeToString(iv), + }, + Bytes: encrypted, + }, nil +} + +func cipherByName(name string) *rfc1423Algo { + for i := range rfc1423Algos { + alg := &rfc1423Algos[i] + if alg.name == name { + return alg + } + } + return nil +} + +func cipherByKey(key PEMCipher) *rfc1423Algo { + for i := range rfc1423Algos { + alg := &rfc1423Algos[i] + if alg.cipher == key { + return alg + } + } + return nil +} + +func setup(privateKey *big.Int, g, p *big.Int) *big.Int { + publicKey := new(big.Int).Exp(g, privateKey, p) + return publicKey +} + +type PublicKey struct { + G, P, Y *big.Int +} + +type PrivateKey struct { + PublicKey + P *big.Int + G *big.Int + X *big.Int +} + +func encrypt(random io.Reader, pub *PublicKey, msg []byte) (ciphertext string, err error) { + k, err := rand.Int(random, pub.P) + if err != nil { + return "", err + } + + m := new(big.Int).SetBytes(msg) + + a := new(big.Int).Exp(pub.G, k, pub.P) + s := new(big.Int).Exp(pub.Y, k, pub.P) + b := s.Mul(s, m) + b.Mod(b, pub.P) + + aHex := fmt.Sprintf("%0*x", (pub.P.BitLen())/4, a) + bHex := fmt.Sprintf("%0*x", (pub.P.BitLen())/4, b) + + ciphertext = aHex + bHex + + return ciphertext, nil +} + +func decrypt(priv *PrivateKey, ciphertext string) (msg []byte, err error) { + if len(ciphertext)%2 != 0 { + return nil, fmt.Errorf("invalid ciphertext format") + } + + halfLen := len(ciphertext) / 2 + aHex := ciphertext[:halfLen] + bHex := ciphertext[halfLen:] + + a, successA := new(big.Int).SetString(aHex, 16) + b, successB := new(big.Int).SetString(bHex, 16) + if !successA || !successB { + return nil, fmt.Errorf("invalid ciphertext format") + } + + s := new(big.Int).Exp(a, priv.X, priv.P) + s.ModInverse(s, priv.P) + s.Mul(s, b) + s.Mod(s, priv.P) + em := s.Bytes() + + return em, nil +} + +func sign(privateKey *PrivateKey, message []byte, hashFunc func() hash.Hash) (signature string, err error) { + for { + k, err := rand.Int(rand.Reader, new(big.Int).Sub(privateKey.P, big.NewInt(2))) + if err != nil { + return "", fmt.Errorf("failed to generate random number: %v", err) + } + + if k.Sign() == 0 { + k = big.NewInt(1) + } + + if new(big.Int).GCD(nil, nil, k, new(big.Int).Sub(privateKey.P, big.NewInt(1))).Cmp(big.NewInt(1)) == 0 { + rBigInt := new(big.Int).Exp(privateKey.G, k, privateKey.P) + rBigInt.Mod(rBigInt, privateKey.P) + rHex := fmt.Sprintf("%x", rBigInt) + + h := hashFunc() + h.Write(message) + hash := h.Sum(nil) + hashInt := new(big.Int).SetBytes(hash) + + kInv := new(big.Int).ModInverse(k, new(big.Int).Sub(privateKey.P, big.NewInt(1))) + if kInv == nil { + return "", errors.New("failed to calculate modular inverse: k is not invertible") + } + + sBigInt := new(big.Int).Mul(kInv, new(big.Int).Sub(hashInt, new(big.Int).Mul(privateKey.X, rBigInt))) + sBigInt.Mod(sBigInt, new(big.Int).Sub(privateKey.P, big.NewInt(1))) + sHex := fmt.Sprintf("%x", sBigInt) + + rHex = strings.TrimLeft(rHex, "0") + sHex = strings.TrimLeft(sHex, "0") + paddingLen := len(fmt.Sprintf("%x", privateKey.P)) + rPadded := fmt.Sprintf("%0*s", paddingLen, rHex) + sPadded := fmt.Sprintf("%0*s", paddingLen, sHex) + + signature = rPadded + sPadded + return signature, nil + } + } +} + +func verify(publicKey *PublicKey, message []byte, signature string, hashFunc func() hash.Hash) bool { + pLength := len(fmt.Sprintf("%X", publicKey.P)) + if len(signature) != 2*pLength { + return false + } + + rHex := signature[:pLength] + sHex := signature[pLength:] + + r, ok := new(big.Int).SetString(rHex, 16) + if !ok { + fmt.Println("Error converting R string to big.Int") + return false + } + + s, ok := new(big.Int).SetString(sHex, 16) + if !ok { + fmt.Println("Error converting S string to big.Int") + return false + } + + if r.Cmp(big.NewInt(1)) == -1 || r.Cmp(new(big.Int).Sub(publicKey.P, big.NewInt(1))) == 1 { + return false + } + if s.Cmp(big.NewInt(1)) == -1 || s.Cmp(new(big.Int).Sub(publicKey.P, big.NewInt(1))) == 1 { + return false + } + + h := hashFunc() + h.Write(message) + hash := h.Sum(nil) + hashInt := new(big.Int).SetBytes(hash) + ghash := new(big.Int).Exp(publicKey.G, hashInt, publicKey.P) + + yr := new(big.Int).Exp(publicKey.Y, r, publicKey.P) + rs := new(big.Int).Exp(r, s, publicKey.P) + yrrs := new(big.Int).Mul(yr, rs) + yrrs.Mod(yrrs, publicKey.P) + + return ghash.Cmp(yrrs) == 0 +} + +func savePrivateKeyToPEM(fileName string, privKey *PrivateKey) error { + privPEM := &PrivateKey{ + X: privKey.X, + P: privKey.P, + G: privKey.G, + } + + privBytes, err := encodePrivateKeyPEM(privPEM) + if err != nil { + return err + } + + block := &pem.Block{ + Type: "ELGAMAL PRIVATE KEY", + Bytes: privBytes, + } + + return savePEMToFile(fileName, block, *pwd != "") +} + +func encodePrivateKeyPEM(privPEM *PrivateKey) ([]byte, error) { + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + err := enc.Encode(privPEM) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func readPrivateKeyFromPEM(fileName string) (*PrivateKey, error) { + pemData, err := ioutil.ReadFile(fileName) + if err != nil { + return nil, err + } + + block, _ := pem.Decode(pemData) + if block == nil { + return nil, errors.New("failed to decode PEM block") + } + + if block.Type != "ELGAMAL PRIVATE KEY" { + return nil, errors.New("unexpected PEM block type") + } + + if block.Headers["Proc-Type"] == "4,ENCRYPTED" { + if *pwd == "" { + return nil, fmt.Errorf("private key is encrypted, but no decryption key provided") + } + + privBytes, err := decryptBlock(block, deriveKeyFromPassword(*pwd)) + if err != nil { + return nil, err + } + + var privKey PrivateKey + buf := bytes.NewReader(privBytes) + dec := gob.NewDecoder(buf) + err = dec.Decode(&privKey) + if err != nil { + return nil, err + } + + return &privKey, nil + } + + var privKey PrivateKey + buf := bytes.NewReader(block.Bytes) + dec := gob.NewDecoder(buf) + err = dec.Decode(&privKey) + if err != nil { + return nil, err + } + + return &privKey, nil +} + +func savePublicKeyToPEM(fileName string, pub *PublicKey) error { + file, err := os.Create(fileName) + if err != nil { + return err + } + defer file.Close() + + pubBytes, err := publicKeyToBytes(pub) + if err != nil { + return err + } + + block := &pem.Block{ + Type: "ELGAMAL PUBLIC KEY", + Bytes: pubBytes, + } + + err = pem.Encode(file, block) + if err != nil { + return err + } + + return nil +} + +func readPublicKeyFromPEM(fileName string) (*PublicKey, error) { + file, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer file.Close() + + pemData, err := io.ReadAll(file) + if err != nil { + return nil, err + } + + block, _ := pem.Decode(pemData) + if block == nil { + return nil, fmt.Errorf("failed to decode PEM block") + } + + pub, err := bytesToPublicKey(block.Bytes) + if err != nil { + return nil, err + } + + return pub, nil +} + +func publicKeyToBytes(pub *PublicKey) ([]byte, error) { + if pub == nil { + return nil, errors.New("cannot encode nil PublicKey pointer") + } + + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + err := enc.Encode(pub) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func bytesToPublicKey(data []byte) (*PublicKey, error) { + var pub PublicKey + dec := gob.NewDecoder(bytes.NewReader(data)) + + err := dec.Decode(&pub) + if err != nil { + return nil, err + } + + return &pub, nil +} + +func generateRandomX(p *big.Int) (*big.Int, error) { + x, err := rand.Int(rand.Reader, new(big.Int).Sub(p, big.NewInt(2))) + if err != nil { + return nil, err + } + return x, nil +} + +func isPrime(n *big.Int) bool { + return n.ProbablyPrime(20) +} + +func generatePrime(length int) (*big.Int, error) { + for { + randomBits := make([]byte, length/8) + _, err := rand.Read(randomBits) + if err != nil { + return nil, err + } + + randomBits[0] |= 1 + randomBits[len(randomBits)-1] |= 1 + + prime := new(big.Int).SetBytes(randomBits) + + prime.SetBit(prime, length-1, 1) + + if isPrime(prime) && prime.BitLen() == length { + return prime, nil + } + + print(".") + } +} + +func generateSchnorrGroup() (*SchnorrParams, error) { + qSize := *length - 1 + + q, err := generatePrime(256) + if err != nil { + return nil, fmt.Errorf("error generating q: %v", err) + } + + if q.BitLen() != 256 { + return nil, errors.New("generated q does not have the desired length") + } + + p, err := generatePrime(qSize + 1) + if err != nil { + return nil, fmt.Errorf("error generating p: %v", err) + } + + if p.BitLen() != (qSize + 1) { + return nil, errors.New("generated p does not have the desired length") + } + + r := new(big.Int).Div(new(big.Int).Sub(p, big.NewInt(1)), q) + + var h *big.Int + for { + h, _ = rand.Int(rand.Reader, new(big.Int).Sub(p, big.NewInt(2))) + h.Add(h, big.NewInt(1)) + if h.Cmp(big.NewInt(1)) == 1 && h.Cmp(p) == -1 { + break + } + } + + g := new(big.Int).Exp(h, r, p) + + return &SchnorrParams{ + P: p, + Q: q, + G: g, + }, nil +} + +type SchnorrParams struct { + P *big.Int + Q *big.Int + G *big.Int +} - for i := 0; i < len(out); i += len(digest) { - hash.Reset() - hash.Write(digest) - hash.Write(password) - hash.Write(salt) - digest = hash.Sum(digest[:0]) - copy(out[i:], digest) +func init() { + gob.Register(&SchnorrParams{}) +} + +func paramsToBytes(params *SchnorrParams) ([]byte, error) { + if params == nil { + return nil, errors.New("cannot encode nil SchnorrParams pointer") } - return out + + var buf bytes.Buffer + enc := gob.NewEncoder(&buf) + err := enc.Encode(params) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil } -func IsEncryptedPEMBlock(b *pem.Block) bool { - _, ok := b.Headers["DEK-Info"] - return ok +func bytesToParams(data []byte) (*SchnorrParams, error) { + var params SchnorrParams + dec := gob.NewDecoder(bytes.NewReader(data)) + + err := dec.Decode(¶ms) + if err != nil { + return nil, err + } + + return ¶ms, nil } -var IncorrectPasswordError = errors.New("x509: decryption password incorrect") +func saveSchnorrParamsToPEM(fileName string, params *SchnorrParams) error { + var file *os.File + var err error -func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { - dek, ok := b.Headers["DEK-Info"] - if !ok { - return nil, errors.New("x509: no DEK-Info header in block") + print("\n") + if fileName == "" { + file = os.Stdout + } else { + file, err = os.Create(fileName) + if err != nil { + return err + } + defer file.Close() } - idx := strings.Index(dek, ",") - if idx == -1 { - return nil, errors.New("x509: malformed DEK-Info header") + paramsBytes, err := paramsToBytes(params) + if err != nil { + return err } - mode, hexIV := dek[:idx], dek[idx+1:] - ciph := cipherByName(mode) - if ciph == nil { - return nil, errors.New("x509: unknown encryption mode") + err = pem.Encode(file, &pem.Block{ + Type: "SCHNORR PARAMETERS", + Bytes: paramsBytes, + }) + if err != nil { + return err } - iv, err := hex.DecodeString(hexIV) + + return nil +} + +func readSchnorrParamsFromPEM(fileName string) (*SchnorrParams, error) { + file, err := os.Open(fileName) if err != nil { return nil, err } - if len(iv) != ciph.blockSize { - return nil, errors.New("x509: incorrect IV size") - } + defer file.Close() - key := ciph.deriveKey(password, iv[:8]) - block, err := ciph.cipherFunc(key) + pemData, err := io.ReadAll(file) if err != nil { return nil, err } - if len(b.Bytes)%block.BlockSize() != 0 { - return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size") + block, _ := pem.Decode(pemData) + if block == nil { + return nil, errors.New("failed to decode PEM block") } - data := make([]byte, len(b.Bytes)) - dec := cipher.NewCBCDecrypter(block, iv) - dec.CryptBlocks(data, b.Bytes) + return bytesToParams(block.Bytes) +} - dlen := len(data) - if dlen == 0 || dlen%ciph.blockSize != 0 { - return nil, errors.New("x509: invalid padding") +/* +func savePEMToFile(fileName string, block *pem.Block) error { + file, err := os.Create(fileName) + if err != nil { + return err } - last := int(data[dlen-1]) - if dlen < last { - return nil, IncorrectPasswordError + defer file.Close() + + err = pem.Encode(file, block) + if err != nil { + return err } - if last == 0 || last > ciph.blockSize { - return nil, IncorrectPasswordError + + return nil +} + +func readKeyFromPEM(fileName string) ([]byte, error) { + fileData, err := ioutil.ReadFile(fileName) + if err != nil { + return nil, err } - for _, val := range data[dlen-last:] { - if int(val) != last { - return nil, IncorrectPasswordError - } + + block, _ := pem.Decode(fileData) + if block == nil { + return nil, fmt.Errorf("failed to decode PEM block") } - return data[:dlen-last], nil + + return block.Bytes, nil } +*/ -func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) { - ciph := cipherByKey(alg) - if ciph == nil { - return nil, errors.New("x509: unknown encryption mode") +func savePEMToFile(fileName string, block *pem.Block, isPrivateKey bool) error { + file, err := os.Create(fileName) + if err != nil { + return err } - iv := make([]byte, ciph.blockSize) - if _, err := io.ReadFull(rand, iv); err != nil { - return nil, errors.New("x509: cannot generate IV: " + err.Error()) + defer file.Close() + + if isPrivateKey && *pwd != "" { + key := deriveKeyFromPassword(*pwd) + encryptedBlock := encryptBlock(block, key) + block = encryptedBlock } - key := ciph.deriveKey(password, iv[:8]) - block, err := ciph.cipherFunc(key) + + err = pem.Encode(file, block) + if err != nil { + return err + } + + return nil +} + +func readKeyFromPEM(fileName string, isPrivateKey bool) ([]byte, error) { + fileData, err := ioutil.ReadFile(fileName) if err != nil { return nil, err } - enc := cipher.NewCBCEncrypter(block, iv) - pad := ciph.blockSize - len(data)%ciph.blockSize - encrypted := make([]byte, len(data), len(data)+pad) - copy(encrypted, data) - for i := 0; i < pad; i++ { - encrypted = append(encrypted, byte(pad)) + + block, _ := pem.Decode(fileData) + if block == nil { + return nil, fmt.Errorf("failed to decode PEM block") } - enc.CryptBlocks(encrypted, encrypted) - return &pem.Block{ - Type: blockType, + if isPrivateKey && *pwd != "" { + key := deriveKeyFromPassword(*pwd) + bytes, err := decryptBlock(block, key) + if err != nil { + return nil, err + } + return bytes, nil + } + + return block.Bytes, nil +} + +func deriveKeyFromPassword(password string) []byte { + key := pbkdf2.Key([]byte(password), []byte(*salt), 1048576, 32, sha256.New) + return key +} + +/* +func encryptBlock(block *pem.Block, key []byte) *pem.Block { + blockBytes := block.Bytes + + var blockCipher cipher.Block + var err error + + switch strings.ToUpper(*cph) { + case "AES": + blockCipher, err = aes.NewCipher(key) + if err != nil { + panic(err.Error()) + } + case "ANUBIS": + blockCipher, err = anubis.New(key) + if err != nil { + panic(err.Error()) + } + default: + log.Fatal("cipher not supported") + } + + gcm, _ := cipher.NewGCM(blockCipher) + + nonce := make([]byte, gcm.NonceSize()) + if _, err := rand.Read(nonce); err != nil { + panic(err.Error()) + } + + nonceHex := hex.EncodeToString(nonce) + encryptedBytes := gcm.Seal(nil, nonce, blockBytes, nil) + + newBlock := &pem.Block{ + Type: block.Type, + Bytes: encryptedBytes, Headers: map[string]string{ "Proc-Type": "4,ENCRYPTED", - "DEK-Info": ciph.name + "," + hex.EncodeToString(iv), + "DEK-Info": fmt.Sprintf("%s,%s", strings.ToUpper(*cph), nonceHex), }, - Bytes: encrypted, - }, nil + } + + if strings.ToUpper(*alg) == "EC-ELGAMAL" { + newBlock.Headers["Curve"] = strings.ToUpper(*curveFlag) + } + + return newBlock } -func cipherByName(name string) *rfc1423Algo { - for i := range rfc1423Algos { - alg := &rfc1423Algos[i] - if alg.name == name { - return alg +func decryptBlock(block *pem.Block, key []byte) ([]byte, error) { + blockBytes := block.Bytes + + dekInfo, ok := block.Headers["DEK-Info"] + if !ok { + return nil, fmt.Errorf("missing DEK-Info in PEM block header") + } + + dekInfoParts := strings.Split(dekInfo, ",") + if len(dekInfoParts) != 2 { + return nil, fmt.Errorf("invalid DEK-Info format") + } + + cipherName := strings.ToUpper(dekInfoParts[0]) + + var blockCipher cipher.Block + var err error + + switch cipherName { + case "AES": + blockCipher, err = aes.NewCipher(key) + if err != nil { + return nil, err + } + case "ANUBIS": + blockCipher, err = anubis.New(key) + if err != nil { + return nil, err } + default: + return nil, fmt.Errorf("cipher not supported") } - return nil + + gcm, _ := cipher.NewGCM(blockCipher) + + nonceHex := dekInfoParts[1] + nonce, err := hex.DecodeString(nonceHex) + if err != nil { + return nil, fmt.Errorf("failed to decode nonce: %v", err) + } + + decryptedBytes, err := gcm.Open(nil, nonce, blockBytes, nil) + if err != nil { + return nil, fmt.Errorf("failed to decrypt PEM block: %v", err) + } + + return decryptedBytes, nil } +*/ -func cipherByKey(key PEMCipher) *rfc1423Algo { - for i := range rfc1423Algos { - alg := &rfc1423Algos[i] - if alg.cipher == key { - return alg +func encryptBlock(block *pem.Block, key []byte) *pem.Block { + blockBytes := block.Bytes + + var blockCipher cipher.Block + var aead cipher.AEAD + var err error + + switch strings.ToUpper(*cph) { + case "AES": + blockCipher, err = aes.NewCipher(key) + if err != nil { + panic(err.Error()) } + case "ANUBIS": + blockCipher, err = anubis.New(key) + if err != nil { + panic(err.Error()) + } + default: + log.Fatal("cipher not supported") + } + + switch strings.ToUpper(*mode) { + case "GCM": + aead, err = cipher.NewGCM(blockCipher) + case "MGM": + aead, err = mgm.NewMGM(blockCipher, 16) + case "OCB", "OCB1": + aead, err = ocb.NewOCB(blockCipher) + case "OCB3": + aead, err = ocb3.New(blockCipher) + case "EAX": + aead, err = eax.NewEAX(blockCipher) + case "CCM": + aead, err = ccm.NewCCM(blockCipher, 16, 12) + default: + log.Fatal("mode not supported") } - return nil + + if err != nil { + log.Fatal(err) + } + + nonce := make([]byte, aead.NonceSize()) + if _, err := rand.Read(nonce); err != nil { + panic(err.Error()) + } + + nonceHex := hex.EncodeToString(nonce) + encryptedBytes := aead.Seal(nil, nonce, blockBytes, nil) + + newBlock := &pem.Block{ + Type: block.Type, + Bytes: encryptedBytes, + Headers: map[string]string{ + "Proc-Type": "4,ENCRYPTED", + "DEK-Info": fmt.Sprintf("%s-%s,%s", strings.ToUpper(*cph), strings.ToUpper(*mode), nonceHex), + }, + } + + if strings.ToUpper(*alg) == "EC-ELGAMAL" { + newBlock.Headers["Curve"] = strings.ToUpper(*curveFlag) + } + + return newBlock +} + +func decryptBlock(block *pem.Block, key []byte) ([]byte, error) { + blockBytes := block.Bytes + + dekInfo, ok := block.Headers["DEK-Info"] + if !ok { + return nil, fmt.Errorf("missing DEK-Info in PEM block header") + } + + dekInfoParts := strings.Split(dekInfo, ",") + if len(dekInfoParts) != 2 { + return nil, fmt.Errorf("invalid DEK-Info format") + } + + cipherModeParts := strings.Split(dekInfoParts[0], "-") + if len(cipherModeParts) != 2 { + return nil, fmt.Errorf("invalid cipher mode format in DEK-Info") + } + cipherName := cipherModeParts[0] + mode := cipherModeParts[1] + + var blockCipher cipher.Block + var err error + + switch cipherName { + case "AES": + blockCipher, err = aes.NewCipher(key) + if err != nil { + return nil, err + } + case "ANUBIS": + blockCipher, err = anubis.New(key) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("cipher not supported") + } + + var aead cipher.AEAD + + switch strings.ToUpper(mode) { + case "GCM": + aead, err = cipher.NewGCM(blockCipher) + case "MGM": + aead, err = mgm.NewMGM(blockCipher, 16) + case "OCB", "OCB1": + aead, err = ocb.NewOCB(blockCipher) + case "OCB3": + aead, err = ocb3.New(blockCipher) + case "EAX": + aead, err = eax.NewEAX(blockCipher) + case "CCM": + aead, err = ccm.NewCCM(blockCipher, 16, 12) + default: + log.Fatal("mode not supported") + } + + if err != nil { + log.Fatal(err) + } + + nonceHex := dekInfoParts[1] + nonce, err := hex.DecodeString(nonceHex) + if err != nil { + return nil, fmt.Errorf("failed to decode nonce: %v", err) + } + + decryptedBytes, err := aead.Open(nil, nonce, blockBytes, nil) + if err != nil { + return nil, fmt.Errorf("failed to decrypt PEM block: %v", err) + } + + return decryptedBytes, nil } func isHexDump(input string) bool {