├── COPYING ├── README.md ├── genlicense.cpp ├── genmasterpair.cpp ├── gensecondarypair.cpp ├── genxmllicense.cpp ├── makefile ├── verifylicense.cpp ├── verifyxmllicense.cpp └── winwebcheck.cpp /COPYING: -------------------------------------------------------------------------------- 1 | 2 | rsa-license-key 3 | Copyright 2013 Tim Sheerman-Case. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, are 6 | permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | of conditions and the following disclaimer in the documentation and/or other materials 13 | provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR 18 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | The views and conclusions contained in the software and documentation are those of the 26 | authors and should not be interpreted as representing official policies, either expressed 27 | or implied, of the copyright holders. 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rsa-license-key 2 | =============== 3 | 4 | Key management tools for software licensing and activation. C++ and BSD license. Based on crypto++. 5 | 6 | On debian/ubuntu/mint: 7 | 8 | sudo apt-get install libcrypto++-dev libxml2-dev 9 | 10 | Compile using "make" 11 | 12 | genmasterpair - to generate master keys. Keep the private master key in an ultra secure place. 13 | 14 | gensecondarypair - to generate a secondary key that is signed by the master key. Keep the secondary master key secure, but if it is compromised, it can be revoked. 15 | 16 | genxmllicense and genlicense - generate license files that are signed by the secondary key (which is in turn signed by the master key) 17 | 18 | verifyxmllicense and verifylicense - verify signatures in the license file 19 | 20 | Adapt the license generation and verification to your own needs. 21 | 22 | -------------------------------------------------------------------------------- /genlicense.cpp: -------------------------------------------------------------------------------- 1 | //g++ genlicense.cpp -lcrypto++ -o genlicense 2 | 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace CryptoPP; 13 | 14 | void SignLicense(AutoSeededRandomPool &rng, string strContents, string pass) 15 | { 16 | 17 | //Read private key 18 | string encPrivKey; 19 | StringSink encPrivKeySink(encPrivKey); 20 | FileSource file("secondary-privkey-enc.txt", true, new Base64Decoder); 21 | file.CopyTo(encPrivKeySink); 22 | 23 | //Read initialization vector 24 | byte iv[AES::BLOCKSIZE]; 25 | CryptoPP::ByteQueue bytesIv; 26 | FileSource file2("secondary-privkey-iv.txt", true, new Base64Decoder); 27 | file2.TransferTo(bytesIv); 28 | bytesIv.MessageEnd(); 29 | bytesIv.Get(iv, AES::BLOCKSIZE); 30 | 31 | //Hash the pass phrase to create 128 bit key 32 | string hashedPass; 33 | RIPEMD128 hash; 34 | StringSource(pass, true, new HashFilter(hash, new StringSink(hashedPass))); 35 | 36 | //Decrypt private key 37 | byte test[encPrivKey.length()]; 38 | CFB_Mode::Decryption cfbDecryption((const unsigned char*)hashedPass.c_str(), hashedPass.length(), iv); 39 | cfbDecryption.ProcessData(test, (byte *)encPrivKey.c_str(), encPrivKey.length()); 40 | StringSource privateKeySrc(test, encPrivKey.length(), true, NULL); 41 | 42 | //Decode key 43 | RSA::PrivateKey privateKey; 44 | privateKey.Load(privateKeySrc); 45 | 46 | //Sign message 47 | RSASSA_PKCS1v15_SHA_Signer privkey(privateKey); 48 | SecByteBlock sbbSignature(privkey.SignatureLength()); 49 | privkey.SignMessage( 50 | rng, 51 | (byte const*) strContents.data(), 52 | strContents.size(), 53 | sbbSignature); 54 | 55 | //Save result 56 | FileSink out("license.txt"); 57 | out.Put((byte const*) strContents.data(), strContents.size()); 58 | 59 | //Save result 60 | Base64Encoder enc(new FileSink("license-sig.txt")); 61 | enc.Put(sbbSignature, sbbSignature.size()); 62 | enc.MessageEnd(); 63 | } 64 | 65 | int main() 66 | { 67 | cout << "Enter existing secondary key password" << endl; 68 | string pass; 69 | cin >> pass; 70 | 71 | AutoSeededRandomPool rng; 72 | SignLicense(rng, "Licensed to BOB", pass); 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /genmasterpair.cpp: -------------------------------------------------------------------------------- 1 | //g++ genmasterpair.cpp -lcrypto++ -o genmasterpair 2 | 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace CryptoPP; 13 | 14 | void GenKeyPair() 15 | { 16 | cout << "Enter new master key password" << endl; 17 | string pass; 18 | cin >> pass; 19 | 20 | // InvertibleRSAFunction is used directly only because the private key 21 | // won't actually be used to perform any cryptographic operation; 22 | // otherwise, an appropriate typedef'ed type from rsa.h would have been used. 23 | AutoSeededRandomPool rng; 24 | InvertibleRSAFunction privkey; 25 | privkey.Initialize(rng, 1024*8); 26 | 27 | // With the current version of Crypto++, MessageEnd() needs to be called 28 | // explicitly because Base64Encoder doesn't flush its buffer on destruction. 29 | string privKeyDer; 30 | StringSink privKeyDerSink(privKeyDer); 31 | privkey.DEREncode(privKeyDerSink); 32 | 33 | //Hash the pass phrase to create 128 bit key 34 | string hashedPass; 35 | RIPEMD128 hash; 36 | StringSource(pass, true, new HashFilter(hash, new StringSink(hashedPass))); 37 | 38 | // Generate a random IV 39 | byte iv[AES::BLOCKSIZE]; 40 | rng.GenerateBlock(iv, AES::BLOCKSIZE); 41 | 42 | //Encrypt private key 43 | CFB_Mode::Encryption cfbEncryption((const unsigned char*)hashedPass.c_str(), hashedPass.length(), iv); 44 | byte encPrivKey[privKeyDer.length()]; 45 | cfbEncryption.ProcessData(encPrivKey, (const byte*)privKeyDer.c_str(), privKeyDer.length()); 46 | string encPrivKeyStr((char *)encPrivKey, privKeyDer.length()); 47 | 48 | //Save private key to file 49 | StringSource encPrivKeySrc(encPrivKeyStr, true); 50 | Base64Encoder sink(new FileSink("master-privkey-enc.txt")); 51 | encPrivKeySrc.CopyTo(sink); 52 | sink.MessageEnd(); 53 | 54 | //Save initialization vector key to file 55 | StringSource ivStr(iv, AES::BLOCKSIZE, true); 56 | Base64Encoder sink2(new FileSink("master-privkey-iv.txt")); 57 | ivStr.CopyTo(sink2); 58 | sink2.MessageEnd(); 59 | 60 | // Suppose we want to store the public key separately, 61 | // possibly because we will be sending the public key to a third party. 62 | RSAFunction pubkey(privkey); 63 | 64 | Base64Encoder pubkeysink(new FileSink("master-pubkey.txt")); 65 | pubkey.DEREncode(pubkeysink); 66 | pubkeysink.MessageEnd(); 67 | 68 | 69 | 70 | } 71 | 72 | int main() 73 | { 74 | GenKeyPair(); 75 | } 76 | 77 | 78 | -------------------------------------------------------------------------------- /gensecondarypair.cpp: -------------------------------------------------------------------------------- 1 | //g++ gensecondarypair.cpp -lcrypto++ -o gensecondarypair 2 | 3 | #include 4 | using namespace std; 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace CryptoPP; 13 | 14 | string GenKeyPair(AutoSeededRandomPool &rng, string pass) 15 | { 16 | // InvertibleRSAFunction is used directly only because the private key 17 | // won't actually be used to perform any cryptographic operation; 18 | // otherwise, an appropriate typedef'ed type from rsa.h would have been used. 19 | InvertibleRSAFunction privkey; 20 | privkey.Initialize(rng, 1024*4); 21 | 22 | // With the current version of Crypto++, MessageEnd() needs to be called 23 | // explicitly because Base64Encoder doesn't flush its buffer on destruction. 24 | string privKeyStr; 25 | StringSink privKeyStrSink(privKeyStr); 26 | //Base64Encoder privkeysink(new FileSink("secondary-privkey.txt")); 27 | privkey.DEREncode(privKeyStrSink); 28 | privKeyStrSink.MessageEnd(); 29 | 30 | //Hash the pass phrase to create 128 bit key 31 | string hashedPass; 32 | RIPEMD128 hash; 33 | StringSource(pass, true, new HashFilter(hash, new StringSink(hashedPass))); 34 | 35 | // Generate a random IV 36 | byte iv[AES::BLOCKSIZE]; 37 | rng.GenerateBlock(iv, AES::BLOCKSIZE); 38 | 39 | //Encrypt private key 40 | CFB_Mode::Encryption cfbEncryption((const unsigned char*)hashedPass.c_str(), hashedPass.length(), iv); 41 | byte encPrivKey[privKeyStr.length()]; 42 | cfbEncryption.ProcessData(encPrivKey, (const byte*)privKeyStr.c_str(), privKeyStr.length()); 43 | string encPrivKeyStr((char *)encPrivKey, privKeyStr.length()); 44 | 45 | //Save private key to file 46 | StringSource encPrivKeySrc(encPrivKeyStr, true); 47 | Base64Encoder sink(new FileSink("secondary-privkey-enc.txt")); 48 | encPrivKeySrc.CopyTo(sink); 49 | sink.MessageEnd(); 50 | 51 | //Save initialization vector key to file 52 | StringSource ivStr(iv, AES::BLOCKSIZE, true); 53 | Base64Encoder sink2(new FileSink("secondary-privkey-iv.txt")); 54 | ivStr.CopyTo(sink2); 55 | sink2.MessageEnd(); 56 | 57 | // Suppose we want to store the public key separately, 58 | // possibly because we will be sending the public key to a third party. 59 | RSAFunction pubkey(privkey); 60 | 61 | Base64Encoder pubkeysink(new FileSink("secondary-pubkey.txt")); 62 | pubkey.DEREncode(pubkeysink); 63 | pubkeysink.MessageEnd(); 64 | 65 | string pubkeyStr; 66 | Base64Encoder pubkeysink2(new StringSink(pubkeyStr)); 67 | pubkey.DEREncode(pubkeysink2); 68 | pubkeysink2.MessageEnd(); 69 | 70 | return pubkeyStr; 71 | } 72 | 73 | void SignSecondaryKey(AutoSeededRandomPool &rng, string strContents, string pass) 74 | { 75 | //Read private key 76 | string encMasterPrivKey; 77 | StringSink encMasterPrivKeySink(encMasterPrivKey); 78 | FileSource file("master-privkey-enc.txt", true, new Base64Decoder); 79 | file.CopyTo(encMasterPrivKeySink); 80 | 81 | //Read initialization vector 82 | byte iv[AES::BLOCKSIZE]; 83 | CryptoPP::ByteQueue bytesIv; 84 | FileSource file2("master-privkey-iv.txt", true, new Base64Decoder); 85 | file2.TransferTo(bytesIv); 86 | bytesIv.MessageEnd(); 87 | bytesIv.Get(iv, AES::BLOCKSIZE); 88 | 89 | //Hash the pass phrase to create 128 bit key 90 | string hashedPass; 91 | RIPEMD128 hash; 92 | StringSource(pass, true, new HashFilter(hash, new StringSink(hashedPass))); 93 | 94 | //Decrypt master key 95 | byte test[encMasterPrivKey.length()]; 96 | CFB_Mode::Decryption cfbDecryption((const unsigned char*)hashedPass.c_str(), hashedPass.length(), iv); 97 | cfbDecryption.ProcessData(test, (byte *)encMasterPrivKey.c_str(), encMasterPrivKey.length()); 98 | StringSource masterKey(test, encMasterPrivKey.length(), true, NULL); 99 | 100 | RSA::PrivateKey privateKey; 101 | privateKey.Load(masterKey); 102 | 103 | //Sign message 104 | RSASSA_PKCS1v15_SHA_Signer privkey(privateKey); 105 | SecByteBlock sbbSignature(privkey.SignatureLength()); 106 | privkey.SignMessage( 107 | rng, 108 | (byte const*) strContents.data(), 109 | strContents.size(), 110 | sbbSignature); 111 | 112 | //Save result 113 | Base64Encoder enc(new FileSink("secondary-pubkey-sig.txt")); 114 | enc.Put(sbbSignature, sbbSignature.size()); 115 | enc.MessageEnd(); 116 | } 117 | 118 | int main() 119 | { 120 | cout << "Enter existing master key password" << endl; 121 | string pass; 122 | cin >> pass; 123 | 124 | cout << "Enter new secondary key password" << endl; 125 | string pass2; 126 | cin >> pass2; 127 | 128 | AutoSeededRandomPool rng; 129 | string pubkey = GenKeyPair(rng, pass2); 130 | SignSecondaryKey(rng, pubkey, pass); 131 | } 132 | 133 | 134 | -------------------------------------------------------------------------------- /genxmllicense.cpp: -------------------------------------------------------------------------------- 1 | //g++ genxmllicense.cpp -lcrypto++ -o genxmllicense 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | using namespace CryptoPP; 18 | 19 | string SignLicense(AutoSeededRandomPool &rng, string strContents, string pass) 20 | { 21 | //Read private key 22 | string encPrivKey; 23 | StringSink encPrivKeySink(encPrivKey); 24 | FileSource file("secondary-privkey-enc.txt", true, new Base64Decoder); 25 | file.CopyTo(encPrivKeySink); 26 | 27 | //Read initialization vector 28 | byte iv[AES::BLOCKSIZE]; 29 | CryptoPP::ByteQueue bytesIv; 30 | FileSource file2("secondary-privkey-iv.txt", true, new Base64Decoder); 31 | file2.TransferTo(bytesIv); 32 | bytesIv.MessageEnd(); 33 | bytesIv.Get(iv, AES::BLOCKSIZE); 34 | 35 | //Hash the pass phrase to create 128 bit key 36 | string hashedPass; 37 | RIPEMD128 hash; 38 | StringSource(pass, true, new HashFilter(hash, new StringSink(hashedPass))); 39 | 40 | //Decrypt private key 41 | byte test[encPrivKey.length()]; 42 | CFB_Mode::Decryption cfbDecryption((const unsigned char*)hashedPass.c_str(), hashedPass.length(), iv); 43 | cfbDecryption.ProcessData(test, (byte *)encPrivKey.c_str(), encPrivKey.length()); 44 | StringSource privateKeySrc(test, encPrivKey.length(), true, NULL); 45 | 46 | //Decode key 47 | RSA::PrivateKey privateKey; 48 | privateKey.Load(privateKeySrc); 49 | 50 | //Sign message 51 | RSASSA_PKCS1v15_SHA_Signer privkey(privateKey); 52 | SecByteBlock sbbSignature(privkey.SignatureLength()); 53 | privkey.SignMessage( 54 | rng, 55 | (byte const*) strContents.data(), 56 | strContents.size(), 57 | sbbSignature); 58 | 59 | //Save result 60 | string out; 61 | Base64Encoder enc(new StringSink(out)); 62 | enc.Put(sbbSignature, sbbSignature.size()); 63 | enc.MessageEnd(); 64 | 65 | return out; 66 | } 67 | 68 | void myReplace(std::string& str, const std::string& oldStr, const std::string& newStr) 69 | { 70 | //From http://stackoverflow.com/a/1494435 71 | size_t pos = 0; 72 | while((pos = str.find(oldStr, pos)) != std::string::npos) 73 | { 74 | str.replace(pos, oldStr.length(), newStr); 75 | pos += newStr.length(); 76 | } 77 | } 78 | 79 | string SerialiseKeyPairs(vector > &info) 80 | { 81 | string out; 82 | for(unsigned int pairNum = 0;pairNum < info.size();pairNum++) 83 | { 84 | out.append(""); 91 | } 92 | 93 | return out; 94 | } 95 | 96 | string GetFileContent(string filename) 97 | { 98 | ifstream fi(filename.c_str()); 99 | if(!fi) 100 | { 101 | runtime_error("Could not open file"); 102 | } 103 | 104 | // get length of file: 105 | fi.seekg (0, fi.end); 106 | int length = fi.tellg(); 107 | fi.seekg (0, fi.beg); 108 | 109 | stringstream test; 110 | test << fi.rdbuf(); 111 | 112 | return test.str(); 113 | } 114 | 115 | int main() 116 | { 117 | cout << "Enter existing secondary key password" << endl; 118 | string pass; 119 | cin >> pass; 120 | 121 | vector > info; 122 | 123 | vector pair; 124 | pair.push_back("licensee"); 125 | pair.push_back("John Doe, Big Institute, Belgium"); 126 | info.push_back(pair); 127 | 128 | pair.clear(); 129 | pair.push_back("functions"); 130 | pair.push_back("feature1, feature2"); 131 | info.push_back(pair); 132 | 133 | string serialisedInfo = SerialiseKeyPairs(info); 134 | 135 | AutoSeededRandomPool rng; 136 | string infoSig = SignLicense(rng, serialisedInfo, pass); 137 | 138 | //Encode as xml 139 | string xml=""; 140 | xml.append(""); 141 | xml.append(serialisedInfo); 142 | xml.append(""); 143 | xml.append(""); 144 | xml.append(infoSig); 145 | xml.append(""); 146 | xml.append(""); 147 | xml.append(GetFileContent("secondary-pubkey.txt")); 148 | xml.append(""); 149 | xml.append(""); 150 | xml.append(GetFileContent("secondary-pubkey-sig.txt")); 151 | xml.append(""); 152 | xml.append(""); 153 | 154 | //cout << xml << endl; 155 | 156 | ofstream out("xmllicense.xml"); 157 | out << xml; 158 | } 159 | 160 | 161 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ genlicense.cpp -lcrypto++ -o genlicense 3 | g++ genmasterpair.cpp -lcrypto++ -o genmasterpair 4 | g++ gensecondarypair.cpp -lcrypto++ -o gensecondarypair 5 | g++ verifylicense.cpp -lcrypto++ -o verifylicense 6 | g++ genxmllicense.cpp -lcrypto++ -o genxmllicense 7 | g++ -I/usr/include/libxml2 verifyxmllicense.cpp -lcrypto++ -lxml2 -o verifyxmllicense 8 | 9 | -------------------------------------------------------------------------------- /verifylicense.cpp: -------------------------------------------------------------------------------- 1 | //g++ verifylicense.cpp -lcrypto++ -o verifylicense 2 | #include 3 | using namespace std; 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace CryptoPP; 9 | 10 | int VerifyLicense() 11 | { 12 | //Read public key 13 | CryptoPP::ByteQueue bytes; 14 | FileSource file("secondary-pubkey.txt", true, new Base64Decoder); 15 | file.TransferTo(bytes); 16 | bytes.MessageEnd(); 17 | RSA::PublicKey pubKey; 18 | pubKey.Load(bytes); 19 | 20 | RSASSA_PKCS1v15_SHA_Verifier verifier(pubKey); 21 | 22 | //Read signed message 23 | string signedTxt; 24 | FileSource("license.txt", true, new StringSink(signedTxt)); 25 | CryptoPP::ByteQueue sig; 26 | FileSource sigFile("license-sig.txt", true, new Base64Decoder); 27 | string sigStr; 28 | StringSink sigStrSink(sigStr); 29 | sigFile.TransferTo(sigStrSink); 30 | 31 | string combined(signedTxt); 32 | combined.append(sigStr); 33 | 34 | //Verify signature 35 | try 36 | { 37 | StringSource(combined, true, 38 | new SignatureVerificationFilter( 39 | verifier, NULL, 40 | SignatureVerificationFilter::THROW_EXCEPTION 41 | ) 42 | ); 43 | cout << "License Signature OK" << endl; 44 | 45 | } 46 | catch(SignatureVerificationFilter::SignatureVerificationFailed &err) 47 | { 48 | cout << err.what() << endl; 49 | return 0; 50 | } 51 | return 1; 52 | } 53 | 54 | int VerifySecondaryKey() 55 | { 56 | //Read public key 57 | CryptoPP::ByteQueue bytes; 58 | FileSource file("master-pubkey.txt", true, new Base64Decoder); 59 | file.TransferTo(bytes); 60 | bytes.MessageEnd(); 61 | RSA::PublicKey pubKey; 62 | pubKey.Load(bytes); 63 | 64 | RSASSA_PKCS1v15_SHA_Verifier verifier(pubKey); 65 | 66 | //Read signed message 67 | string signedTxt; 68 | FileSource("secondary-pubkey.txt", true, new StringSink(signedTxt)); 69 | CryptoPP::ByteQueue sig; 70 | FileSource sigFile("secondary-pubkey-sig.txt", true, new Base64Decoder); 71 | string sigStr; 72 | StringSink sigStrSink(sigStr); 73 | sigFile.TransferTo(sigStrSink); 74 | 75 | string combined(signedTxt); 76 | combined.append(sigStr); 77 | 78 | //Verify signature 79 | try 80 | { 81 | StringSource(combined, true, 82 | new SignatureVerificationFilter( 83 | verifier, NULL, 84 | SignatureVerificationFilter::THROW_EXCEPTION 85 | ) 86 | ); 87 | cout << "Secondary Key OK" << endl; 88 | 89 | } 90 | catch(SignatureVerificationFilter::SignatureVerificationFailed &err) 91 | { 92 | cout << err.what() << endl; 93 | return 0; 94 | } 95 | return 1; 96 | } 97 | 98 | int main() 99 | { 100 | int ret1 = VerifySecondaryKey(); 101 | int ret2 = VerifyLicense(); 102 | 103 | } 104 | 105 | 106 | -------------------------------------------------------------------------------- /verifyxmllicense.cpp: -------------------------------------------------------------------------------- 1 | //g++ -I/usr/include/libxml2 verifyxmllicense.cpp -lcrypto++ -lxml2 -o verifyxmllicense 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace CryptoPP; 16 | 17 | vector > ParseInfo(xmlNode *el) 18 | { 19 | vector > info; 20 | for (xmlNode *el2 = el->children; el2; el2 = el2->next) 21 | { 22 | map data; 23 | if (el2->type != XML_ELEMENT_NODE) continue; 24 | xmlElement *el2t = (xmlElement *)el2; 25 | xmlAttribute *attributes = el2t->attributes; 26 | unsigned int i=0; 27 | xmlAttribute *attr = &attributes[i]; 28 | while(attr!=NULL) 29 | { 30 | xmlChar* value = xmlNodeListGetString(el2t->doc, attr->children, 1); 31 | data[(const char *)attr->name] = (const char *)value; 32 | xmlFree(value); 33 | attr = (xmlAttribute *)attr->next; 34 | } 35 | 36 | vector pair; 37 | pair.push_back(data["k"]); 38 | pair.push_back(data["v"]); 39 | info.push_back(pair); 40 | } 41 | 42 | return info; 43 | } 44 | 45 | void myReplace(std::string& str, const std::string& oldStr, const std::string& newStr) 46 | { 47 | //From http://stackoverflow.com/a/1494435 48 | size_t pos = 0; 49 | while((pos = str.find(oldStr, pos)) != std::string::npos) 50 | { 51 | str.replace(pos, oldStr.length(), newStr); 52 | pos += newStr.length(); 53 | } 54 | } 55 | 56 | string SerialiseKeyPairs(vector > &info) 57 | { 58 | string out; 59 | for(unsigned int pairNum = 0;pairNum < info.size();pairNum++) 60 | { 61 | out.append(""); 68 | } 69 | 70 | return out; 71 | } 72 | 73 | int VerifyLicense(string signedTxt, string sigIn, string pubKeyEnc) 74 | { 75 | //Read public key 76 | CryptoPP::ByteQueue bytes; 77 | StringSource file(pubKeyEnc, true, new Base64Decoder); 78 | file.TransferTo(bytes); 79 | bytes.MessageEnd(); 80 | RSA::PublicKey pubKey; 81 | pubKey.Load(bytes); 82 | 83 | RSASSA_PKCS1v15_SHA_Verifier verifier(pubKey); 84 | 85 | //Read signed message 86 | CryptoPP::ByteQueue sig; 87 | StringSource sigFile(sigIn, true, new Base64Decoder); 88 | string sigStr; 89 | StringSink sigStrSink(sigStr); 90 | sigFile.TransferTo(sigStrSink); 91 | 92 | string combined(signedTxt); 93 | combined.append(sigStr); 94 | 95 | //Verify signature 96 | try 97 | { 98 | StringSource(combined, true, 99 | new SignatureVerificationFilter( 100 | verifier, NULL, 101 | SignatureVerificationFilter::THROW_EXCEPTION 102 | ) 103 | ); 104 | } 105 | catch(SignatureVerificationFilter::SignatureVerificationFailed &err) 106 | { 107 | cout << err.what() << endl; 108 | return 0; 109 | } 110 | return 1; 111 | } 112 | 113 | string GetFileContent(string filename) 114 | { 115 | ifstream fi(filename.c_str()); 116 | if(!fi) 117 | { 118 | runtime_error("Could not open file"); 119 | } 120 | 121 | // get length of file: 122 | fi.seekg (0, fi.end); 123 | int length = fi.tellg(); 124 | fi.seekg (0, fi.beg); 125 | 126 | stringstream test; 127 | test << fi.rdbuf(); 128 | 129 | return test.str(); 130 | } 131 | 132 | int Verify(const char *filename) 133 | { 134 | //parse the file and get the DOM 135 | xmlDoc *doc = xmlReadFile(filename, NULL, 0); 136 | 137 | if (doc == NULL) 138 | { 139 | cout << "error: could not parse file" << endl; 140 | return 0; 141 | } 142 | 143 | //Get the root element node 144 | xmlNode *root_element = xmlDocGetRootElement(doc); 145 | map data; 146 | vector > info; 147 | 148 | //Iterate over xml elements 149 | for (xmlNode *rootEl = root_element; rootEl; rootEl = rootEl->next) 150 | { 151 | if (rootEl->type != XML_ELEMENT_NODE) continue; 152 | for (xmlNode *el = rootEl->children; el; el = el->next) 153 | { 154 | if(el->type != XML_ELEMENT_NODE) continue; 155 | //cout << "node type: Element, name: "<< el->name << endl; 156 | if(string((const char*)el->name) == string("info")) 157 | { 158 | info = ParseInfo(el); 159 | } 160 | else 161 | { 162 | xmlChar* value = xmlNodeListGetString(el->doc, el->children, 1); 163 | data[(char *)el->name] = (char *)value; 164 | xmlFree(value); 165 | } 166 | } 167 | } 168 | 169 | //Print found elements 170 | cout << SerialiseKeyPairs(info) << endl; 171 | map::iterator it; 172 | for(it = data.begin(); it != data.end(); it++) 173 | { 174 | cout << it->first << endl; 175 | } 176 | 177 | string masterPubKey = GetFileContent("master-pubkey.txt"); 178 | 179 | 180 | cout << "Info signature ret:" << VerifyLicense(SerialiseKeyPairs(info), data["infosig"], data["key"]) << endl; 181 | cout << "Key signature ret:" << VerifyLicense(data["key"], data["keysig"], masterPubKey) << endl; 182 | 183 | //free the document 184 | xmlFreeDoc(doc); 185 | 186 | return 1; 187 | 188 | } 189 | 190 | 191 | int main() 192 | { 193 | 194 | Verify("xmllicense.xml"); 195 | 196 | } 197 | -------------------------------------------------------------------------------- /winwebcheck.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #pragma comment(lib, "WinINet.lib") 9 | 10 | std::string replaceAll(std::string subject, const std::string& search, 11 | const std::string& replace) { 12 | size_t pos = 0; 13 | while ((pos = subject.find(search, pos)) != std::string::npos) { 14 | subject.replace(pos, search.length(), replace); 15 | pos += replace.length(); 16 | }; 17 | return subject; 18 | }; 19 | 20 | std::string DownloadURL(std::string URL) { 21 | HINTERNET interwebs = InternetOpenA("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, NULL); 22 | HINTERNET urlFile; 23 | std::string rtn; 24 | if (interwebs) { 25 | urlFile = InternetOpenUrlA(interwebs, URL.c_str(), NULL, NULL, NULL, NULL); 26 | if (urlFile) { 27 | char buffer[2000]; 28 | DWORD bytesRead; 29 | do { 30 | InternetReadFile(urlFile, buffer, 2000, &bytesRead); 31 | rtn.append(buffer, bytesRead); 32 | memset(buffer, 0, 2000); 33 | } while (bytesRead); 34 | InternetCloseHandle(interwebs); 35 | InternetCloseHandle(urlFile); 36 | std::string p = replaceAll(rtn, "|n", "\r\n"); 37 | return p; 38 | }; 39 | }; 40 | InternetCloseHandle(interwebs); 41 | std::string p = replaceAll(rtn, "|n", "\r\n"); 42 | return p; 43 | }; 44 | 45 | std::string keychecker() { 46 | std::string key; 47 | std::cout << "Enter Key: "; 48 | std::cin >> key; 49 | return key; 50 | }; 51 | 52 | void auth() { 53 | std::string hostfile = ""; //Hwid check site [Pastebin etc.] 54 | std::string hot = keychecker(); 55 | std::string result = DownloadURL(hostfile += hot); 56 | if (result == "1") { 57 | std::cout << "Whitelisted Key: " + hot, +"\n"; //Success message. 58 | } 59 | else { 60 | std::cout << "Key Not Found\n" << hot.c_str(); 61 | Sleep(10000); 62 | exit(10); 63 | }; 64 | }; 65 | --------------------------------------------------------------------------------