📄 rsa_kgen.cpp
字号:
/*Generate an RSA key of a specified bitlength, and put it into a file. Thepublic key is written in plaintext as a exponent/modulus pair, the private keyis encrypted using CAST-128 in CBC mode, and MACed with HMAC-SHA1-96. For theprivate key, we just store the modulus and the pair of primes, since everythingelse is easily derivable from them.The keys/ivs are derived using OpenPGP's S2K algorithm, with an 8 byte salt(which is written as the first 8 bytes of the private key file), and aniteration count of 8192. The passphrase is prefixed with a string to make surethat each one is different, and hopefully not derivable from one another.The CAST key uses a prefix of "CAST"The HMAC key uses a prefix of "MAC"The IV uses a prefix of "IV"Written by Jack Lloyd (lloyd@randombit.net), June 2-3, 2002This file is in the public domain*/#include <iostream>#include <iomanip>#include <fstream>#include <cstdlib>#include <string>#include <botan/filters.h>#include <botan/cbc.h>#include <botan/rsa.h>#include <botan/pgp_s2k.h>using namespace Botan;std::string b64_encode(const byte[], u32bit);void write_bigint_to_pipe(Pipe&, const BigInt&);int main(int argc, char* argv[]) { try { if(argc != 3) { std::cout << "Usage: rsa_kgen bitsize passphrase" << std::endl; return 1; } u32bit bits = std::atoi(argv[1]); if(bits < 512 || bits > 4096) { std::cout << "Invalid argument for bitsize" << std::endl; return 1; } std::string passphrase(argv[2]); std::ofstream priv("rsakey.priv"); std::ofstream pub("rsakey.pub"); if(!priv || !pub) { std::cout << "Couldn't write output files" << std::endl; return 1; } // Want to make sure the RNG has lots of entropy LibraryInitializer init("seed_rng egd_path=/var/run/egd-pool"); RSA_PrivateKey key(bits); pub << key.get_e() << "\n" << key.get_n() << std::endl; OpenPGP_S2K s2k("SHA-1", 8192, 8); SymmetricKey cast_key = s2k.derive_key("CAST" + passphrase, 16); BlockCipherModeIV iv = s2k.derive_key("IV" + passphrase, 8); SymmetricKey mac_key = s2k.derive_key("MAC" + passphrase, 16); SecureVector<byte> salt = s2k.current_salt(); priv << b64_encode(salt, salt.size()) << std::endl; Pipe pipe(new Fork( new Chain( new CBC_Encryption("CAST-128", "PKCS7", cast_key, iv), new Base64_Encoder(true) ), new Chain( new MAC_Filter("HMAC(SHA-1)", mac_key, 12), new Base64_Encoder ) ) ); pipe.start_msg(); write_bigint_to_pipe(pipe, key.get_e()); write_bigint_to_pipe(pipe, key.get_p()); write_bigint_to_pipe(pipe, key.get_q()); pipe.end_msg(); priv << pipe.read_all_as_string(1) << std::endl; priv << pipe.read_all_as_string(0); } catch(Exception& e) { std::cout << "Exception caught: " << e.what() << std::endl; } catch(std::exception& e) { std::cout << "Standard library exception caught: " << e.what() << std::endl; } catch(...) { std::cout << "Unknown exception caught." << std::endl; } return 0; }std::string b64_encode(const byte in[], u32bit length) { Pipe pipe(new Base64_Encoder); pipe.start_msg(); pipe.write(in, length); pipe.end_msg(); return pipe.read_all_as_string(); }/* Write the length as a 4 byte big endian value, followed up by the number itself (which is also big endian)*/void write_bigint_to_pipe(Pipe& pipe, const BigInt& num) { SecureVector<byte> bits = num.binary_encode(); for(u32bit j = 0; j != 4; j++) pipe.write(get_byte(j, bits.size())); pipe.write(bits, bits.size()); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -