static void Main(string[] args) { ParsecsParser parser = new ParsecsParser(); parser.AddOption('?', "help", default); var parser_gen = parser.AddCommand("gen", "generate PEM asymmetric public+private key pair file"); var parser_pub = parser.AddCommand("pub", "extract a PEM public key file from key pair file"); var parser_pwd = parser.AddCommand("pwd", "generate a random password BASE64 file"); var parser_ecc = parser.AddCommand("ecc", "generate an ECDH 'shared secret' password file"); var parser_rsa = parser.AddCommand("rsa", "RSA-encrypt or decrypt small files (e.g. password file)"); var parser_aes = parser.AddCommand("aes", "AES-cipher or decipher with password file"); parser_gen.AddOption('?', "help", default); parser_pub.AddOption('?', "help", default); parser_pwd.AddOption('?', "help", default); parser_ecc.AddOption('?', "help", default); parser_rsa.AddOption('?', "help", default); parser_aes.AddOption('?', "help", default); var gen_output = parser_gen.AddString('o', "output", "output file path"); var gen_keysize = parser_gen.AddString('l', "length", $"key bit-length (default RSA={rsa_key_size} EC={ecc_key_size})"); var gen_choice = parser_gen.AddChoice('r', "asymmetric cryptosystem algorithm (default RSA)"); gen_choice.AddItem('r', "rsa", "RSA (Rivest-Shamir-Adleman)"); gen_choice.AddItem('e', "ecc", "Elliptic Curve Cryptography"); var pub_input = parser_pub.AddString('i', "input", "input key pair file path"); var pub_output = parser_pub.AddString('o', "output", "output public key file path"); var pwd_output = parser_pwd.AddString('o', "output", "output BASE64 password file path"); var pwd_length = parser_pwd.AddString('l', "length", $"password byte-length (default {password_length})"); var sec_skey_prv = parser_ecc.AddString('y', "yours", "your ECC private key file path"); var sec_skey_pub = parser_ecc.AddString('t', "theirs", "the other part's ECC public key file path"); var sec_output = parser_ecc.AddString('o', "output", "'shared-secret' BASE64 password file path"); var rsa_akey_pub = parser_rsa.AddString('k', "public", "input public PEM file path"); var rsa_akey_prv = parser_rsa.AddString('K', "private", "input public+private pair PEM file path"); var rsa_input = parser_rsa.AddString('i', "input", "input data file path"); var rsa_output = parser_rsa.AddString('o', "output", "output data file path"); var rsa_choice = parser_rsa.AddChoice('e', "operation mode (default: encrypt)"); rsa_choice.AddItem('e', "encrypt", "RSA-encrypt with a public key"); rsa_choice.AddItem('d', "decrypt", "RSA-decrypt with a private key or key pair"); var aes_pwd_file = parser_aes.AddString('p', "passfile", "input BASE64 password file path"); var aes_pwd_b64 = parser_aes.AddString('b', "base64", "input BASE64 password string"); var aes_pwd_str = parser_aes.AddString('a', "ascii", "input plain ASCII 7-bit password string"); var aes_input = parser_aes.AddString('i', "input", "input data file path"); var aes_output = parser_aes.AddString('o', "output", "output data file path"); var aes_gzip = parser_aes.AddOption('z', "gzip", "enable GZIP compression/decompression"); var aes_choice = parser_aes.AddChoice('e', "operation mode (default: encrypt)"); aes_choice.AddItem('e', "encrypt", "AES-256 cipher"); aes_choice.AddItem('d', "decrypt", "AES-256 decipher"); Console.OutputEncoding = Encoding.ASCII; if (parser.Parse(args)) { if ((args.Length == 0) || parser['?'] || (parser.Command == parser)) { Console.WriteLine("PARAMETERS: <command> <command-options>|--help\r\n"); Console.WriteLine(parser.HelpTextBuilder(4, false).ToString()); Console.WriteLine($">>> passing a '{file_std}' char for a file name means standard input/output"); Console.WriteLine(); Console.WriteLine("RSA ENCRYPTION EXAMPLE:"); Console.WriteLine("$ gen --output=PRIVATE.pem"); Console.WriteLine("$ pub --input=PRIVATE.pem --output=PUBLIC.pem"); Console.WriteLine("$ pwd --output=PASSWORD.txt"); Console.WriteLine("$ aes --encrypt --passfile=PASSWORD.txt --input=PLAIN.txt --output=CIPHERED.bin"); Console.WriteLine("$ rsa --encrypt --public=PUBLIC.PEM --input=PASSWORD.txt --output=PASSWORD.bin"); Console.WriteLine("DECRYPTION:"); Console.WriteLine("$ rsa --decrypt --private=PRIVATE.PEM --input=PASSWORD.bin --output=PASSWORD.txt"); Console.WriteLine("$ aes --decrypt --passfile=PASSWORD.txt --input=CIPHERED.bin --output=PLAIN.txt"); Console.WriteLine(); Console.WriteLine("ECC ENCRYPTION EXAMPLE:"); Console.WriteLine("$ gen --ecc --output=PRIVATE-A.pem"); Console.WriteLine("$ pub --input=PRIVATE-A.pem --output=PUBLIC-A.pem"); Console.WriteLine("$ gen --ecc --output=PRIVATE-B.pem"); Console.WriteLine("$ pub --input=PRIVATE-B.pem --output=PUBLIC-B.pem"); Console.WriteLine("$ ecc --yours=PRIVATE-A.pem --theirs=PUBLIC-B.pem --output=PASSWORD.txt"); Console.WriteLine("$ aes --encrypt --passfile=PASSWORD.txt --input=PLAIN.txt --output=CIPHERED.bin"); Console.WriteLine("DECRYPTION:"); Console.WriteLine("$ ecc --yours=PRIVATE-B.pem --theirs=PUBLIC-A.pem --output=PASSWORD.txt"); Console.WriteLine("$ aes --decrypt --passfile=PASSWORD.txt --input=CIPHERED.bin --output=PLAIN.txt"); } else if ((parser.Command != parser) && (parser.Command['?'])) { switch (parser.Command.Name) { case "gen": Console.WriteLine($"PARAMETERS: {parser.Command.Name} --rsa|--ecc --output=<private-key-file> [--length=<key-length>]\r\n"); Console.WriteLine(parser.Command.HelpTextBuilder(4, false).ToString()); Console.WriteLine("OPENSSL EQUIVALENCE:"); Console.WriteLine($"RSA -> $ openssl genrsa <key-length> -out <private-key-file>"); Console.WriteLine($"ECC -> $ openssl ecparam -name <e.g. prime256v1> -genkey -noout -out <private-key-file>"); break; case "pub": Console.WriteLine($"PARAMETERS: {parser.Command.Name} --input=<private-key-file> --output=<public-key-file>\r\n"); Console.WriteLine(parser.Command.HelpTextBuilder(4, false).ToString()); Console.WriteLine("OPENSSL EQUIVALENCE:"); Console.WriteLine($"$ openssl rsa -in <private-key-file> -pubout -out <public-key-file>"); break; case "pwd": Console.WriteLine($"PARAMETERS: {parser.Command.Name} --output=<password-file> [--length=<password-length>]\r\n"); Console.WriteLine(parser.Command.HelpTextBuilder(4, false).ToString()); Console.WriteLine("OPENSSL EQUIVALENCE:"); Console.WriteLine($"$ openssl rand -base64 <password-length> > <password-file>"); break; case "ecc": Console.WriteLine($"PARAMETERS: {parser.Command.Name} --yours=<private-key-file> --theirs=<public-key-file> --output=<password-file>\r\n"); Console.WriteLine(parser.Command.HelpTextBuilder(4, false).ToString()); Console.WriteLine("OPENSSL EQUIVALENCE:"); Console.WriteLine("$ openssl pkeyutl -derive -inkey <private-key-file> -peerkey <public-key-file> | base64 > <password-file>"); break; case "rsa": Console.WriteLine($"PARAMETERS: {parser.Command.Name} --encrypt|--decrypt --public=<public-key-file>|--private=<key-pair-file> --input=<input-file> --output=<output-file>\r\n"); Console.WriteLine(parser.Command.HelpTextBuilder(4, false).ToString()); Console.WriteLine("OPENSSL EQUIVALENCE:"); Console.WriteLine($"ENCRYPT -> $ openssl rsautl -encrypt -oaep -inkey <public-key-file> -pubin -in <plain-file> -out <ciphered-file>"); Console.WriteLine($"DECRYPT -> $ openssl rsautl -decrypt -oaep -inkey <private-key-file> -in <ciphered-file> -out <plain-file>"); break; case "aes": Console.WriteLine($"PARAMETERS: {parser.Command.Name} --encrypt|--decrypt --passfile=<password-file>|--base64=<BASE64-string>|--ascii=<ASCII-string> --input=<input-file> --output=<output-file>\r\n"); Console.WriteLine(parser.Command.HelpTextBuilder(4, false).ToString()); Console.WriteLine("OPENSSL EQUIVALENCE:"); Console.WriteLine($"ENCRYPT -> $ openssl aes-256-cbc -e -md sha256 -in <plain-data> -out <ciphered-data> -kfile <password-file>"); Console.WriteLine($"DECRYPT -> $ openssl aes-256-cbc -d -md sha256 -in <ciphered-data> -out <plain-data> -kfile <password-file>"); break; } } else { try { switch (parser.Command.Name) { case "gen": int size; if (gen_choice.Value == 'r') { if (!Int32.TryParse(gen_keysize.String, out size)) { size = rsa_key_size; } RSAGenKey(gen_output.String, size); } else { if (!Int32.TryParse(gen_keysize.String, out size)) { size = ecc_key_size; } ECCGenKey(gen_output.String, size); } break; case "pub": Export(pub_input.String, pub_output.String); break; case "pwd": int length; if (!Int32.TryParse(pwd_length.String, out length)) { length = password_length; } GenPassword(pwd_output.String, length); break; case "ecc": ECCAgreement(sec_skey_pub.String, sec_skey_prv.String, sec_output.String); break; case "rsa": RSAEncrypt(rsa_akey_pub.String, rsa_akey_prv.String, rsa_input.String, rsa_output.String, rsa_choice.Value == 'd'); break; case "aes": if (aes_choice.Value == 'e') { AESEncrypt(aes_pwd_file.String, aes_pwd_b64.String, aes_pwd_str.String, aes_input.String, aes_output.String, aes_gzip.Switched); } else { AESDecrypt(aes_pwd_file.String, aes_pwd_b64.String, aes_pwd_str.String, aes_input.String, aes_output.String, aes_gzip.Switched); } break; } } catch (Exception e) { using (Stream error_stream = Console.OpenStandardError()) using (StreamWriter stream_writer = new StreamWriter(error_stream)) { Exception inner = e; while (inner != null) { stream_writer.WriteLine($"<{inner.ToString()}> {inner.Message}"); inner = inner.InnerException; } } } } } else { using (Stream error_stream = Console.OpenStandardError()) using (StreamWriter stream_writer = new StreamWriter(error_stream)) { stream_writer.WriteLine("wrong parameter"); } } }
static void Main(string[] args) { var clp = new ParsecsParser(); clp.AddOption('h', "help"); var clp_xml = clp.AddCommand("xml", "XML formatting"); var clp_json = clp.AddCommand("json", "Json formatting"); var clp_url = clp.AddCommand("url", "URL decoding"); var clp_b64 = clp.AddCommand("b64", "Base64 decoding"); if (clp.Parse(args)) { if (clp['h']) { Console.Write(clp.HelpText()); } else { using var stdin = Console.OpenStandardInput(); using var stdout = Console.OpenStandardOutput(); switch (clp.Command.Name) { case "xml": { using var xml_text_writer = new XmlTextWriter(stdout, Encoding.UTF8); xml_text_writer.Formatting = Formatting.Indented; var xml_document = new XmlDocument(); xml_document.Load(stdin); xml_document.WriteContentTo(xml_text_writer); } break; case "json": { using var utf8_json_writer = new Utf8JsonWriter(stdout, new JsonWriterOptions() { Indented = true }); using var json_document = JsonDocument.Parse(stdin); json_document.WriteTo(utf8_json_writer); } break; case "url": { using var stream_reader = new StreamReader(stdin, Encoding.UTF8); using var stream_writer = new StreamWriter(stdout, Encoding.UTF8); var url_string = stream_reader.ReadToEnd(); stream_writer.Write(Uri.UnescapeDataString(url_string.Replace('+', '\x20'))); } break; case "b64": { using var stream_reader = new StreamReader(stdin, Encoding.UTF8); using var stream_writer = new StreamWriter(stdout, Encoding.UTF8); var b64_string = stream_reader.ReadToEnd(); stream_writer.Write(Convert.FromBase64String(b64_string)); } break; } } } }