// // File : libkvirijndael.cpp // Creation date : Sat Now 4 2000 15:33:12 CEST by Szymon Stefanek // // This file is part of the KVirc irc client distribution // Copyright (C) 1999-2000 Till Bush (buti@geocities.com) // // This program is FREE software. You can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your opinion) any later version. // // This program is distributed in the HOPE that it will be USEFUL, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, write to the Free Software Foundation, // Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #include "libkvirijndael.h" #include "rijndael.h" #include "kvi_module.h" #include "kvi_debug.h" #include "kvi_locale.h" #include "kvi_mirccntrl.h" #include "kvi_time.h" //#warning "Other engines: mircStrip koi2win colorizer lamerizer etc.." /* @doc: rijndael @type: module @short: The Rijndael cryptographic engines @title: The rijndael module @body: The rijndael module exports six [doc:crypt_engines]cryptographic engines[/doc] based on the Advanced Encryptiong Standard algorithm called Rijndael. Rijndael was originally written by Joan Daemen and Vincent Rijmen. The original Rijndael description is available at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/.[br] It is a private key block cipher that has been designed to replace the widely used DES, and it should provide at leas a decent security agains common attacks. Theoretically the best attack that one can perform on this cipher is the "brute force" attack that requires a really massive parallel computation: actually out of the possibilities of a common "hacker".[br] My implementation allows the usage of 128, 192 and 256 bit keys on 128 bit data blocks. The encrypted binary data buffer is then converted into an ascii-string by using the base64 conversion or hex-digit-string rappresentation. The six engines are the six possible combinations of the key lengths and ascii-string conversions. */ #ifdef COMPILE_CRYPT_SUPPORT #include "kvi_memmove.h" #include "kvi_malloc.h" #include "kvi_pointerlist.h" static KviPointerList * g_pEngineList = 0; KviRijndaelEngine::KviRijndaelEngine() : KviCryptEngine() { g_pEngineList->append(this); m_pEncryptCipher = 0; m_pDecryptCipher = 0; } KviRijndaelEngine::~KviRijndaelEngine() { g_pEngineList->removeRef(this); if(m_pEncryptCipher)delete m_pEncryptCipher; if(m_pDecryptCipher)delete m_pDecryptCipher; } bool KviRijndaelEngine::init(const char *encKey,int encKeyLen,const char *decKey,int decKeyLen) { if(m_pEncryptCipher) { delete m_pEncryptCipher; m_pEncryptCipher = 0; } if(m_pDecryptCipher) { delete m_pDecryptCipher; m_pDecryptCipher = 0; } if(encKey && (encKeyLen > 0)) { if(!(decKey && (decKeyLen > 0))) { decKey = encKey; decKeyLen = encKeyLen; } // else all } else { // no encrypt key specified... if(decKey && decKeyLen) { encKey = decKey; encKeyLen = decKeyLen; } else { // both keys missing setLastError(__tr("Missing both encrypt and decrypt key: at least one is needed")); return false; } } int defLen = getKeyLen(); char * encryptKey = (char *)kvi_malloc(defLen); char * decryptKey = (char *)kvi_malloc(defLen); if(encKeyLen > defLen)encKeyLen = defLen; kvi_memmove(encryptKey,encKey,encKeyLen); if(encKeyLen < defLen)kvi_memset(encryptKey + encKeyLen,'0',defLen - encKeyLen); if(decKeyLen > defLen)decKeyLen = defLen; kvi_memmove(decryptKey,decKey,decKeyLen); if(decKeyLen < defLen)kvi_memset(decryptKey + decKeyLen,'0',defLen - decKeyLen); m_pEncryptCipher = new Rijndael(); int retVal = m_pEncryptCipher->init(Rijndael::CBC,Rijndael::Encrypt,(unsigned char *)encryptKey,getKeyLenId()); kvi_free(encryptKey); if(retVal != RIJNDAEL_SUCCESS) { kvi_free(decryptKey); delete m_pEncryptCipher; m_pEncryptCipher = 0; setLastErrorFromRijndaelErrorCode(retVal); return false; } m_pDecryptCipher = new Rijndael(); retVal = m_pDecryptCipher->init(Rijndael::CBC,Rijndael::Decrypt,(unsigned char *)decryptKey,getKeyLenId()); kvi_free(decryptKey); if(retVal != RIJNDAEL_SUCCESS) { delete m_pEncryptCipher; m_pEncryptCipher = 0; delete m_pDecryptCipher; m_pDecryptCipher = 0; setLastErrorFromRijndaelErrorCode(retVal); return false; } return true; } void KviRijndaelEngine::setLastErrorFromRijndaelErrorCode(int errCode) { switch(errCode) { case RIJNDAEL_SUCCESS: setLastError(__tr("Error 0: Success ?")); break; case RIJNDAEL_UNSUPPORTED_MODE: setLastError(__tr("Unsupported crypt mode")); break; case RIJNDAEL_UNSUPPORTED_DIRECTION: setLastError(__tr("Unsupported direction")); break; case RIJNDAEL_UNSUPPORTED_KEY_LENGTH: setLastError(__tr("Unsupported key length")); break; case RIJNDAEL_BAD_KEY: setLastError(__tr("Bad key data")); break; case RIJNDAEL_NOT_INITIALIZED: setLastError(__tr("Engine not initialized")); break; case RIJNDAEL_BAD_DIRECTION: setLastError(__tr("Invalid direction for this engine")); break; case RIJNDAEL_CORRUPTED_DATA: setLastError(__tr("Corrupted message data or invalid decrypt key")); break; default: setLastError(__tr("Unknown error")); break; } } KviCryptEngine::EncryptResult KviRijndaelEngine::encrypt(const char * plainText,KviStr &outBuffer) { if(!m_pEncryptCipher) { setLastError(__tr("Ops...encrypt cipher not initialized")); return KviCryptEngine::EncryptError; } int len = (int)kvi_strLen(plainText); char * buf = (char *)kvi_malloc(len + 16); int retVal = m_pEncryptCipher->padEncrypt((const unsigned char *)plainText,len,(unsigned char *)buf); if(retVal < 0) { kvi_free(buf); setLastErrorFromRijndaelErrorCode(retVal); return KviCryptEngine::EncryptError; } if(!binaryToAscii(buf,retVal,outBuffer)) { kvi_free(buf); return KviCryptEngine::EncryptError; } kvi_free(buf); if(outBuffer.len() > maxEncryptLen()) { if(maxEncryptLen() > 0) { setLastError(__tr("Data buffer too long")); return KviCryptEngine::EncryptError; } } outBuffer.prepend(KVI_TEXT_CRYPTESCAPE); return KviCryptEngine::Encrypted; } KviCryptEngine::DecryptResult KviRijndaelEngine::decrypt(const char * inBuffer,KviStr &plainText) { if(!m_pDecryptCipher) { setLastError(__tr("Ops...decrypt cipher not initialized")); return KviCryptEngine::DecryptError; } if(*inBuffer != KVI_TEXT_CRYPTESCAPE) { plainText = inBuffer; return KviCryptEngine::DecryptOkWasPlainText; } inBuffer++; if(!*inBuffer) { plainText = inBuffer; return KviCryptEngine::DecryptOkWasPlainText; // empty buffer } int len; char * binary; if(!asciiToBinary(inBuffer,&len,&binary))return KviCryptEngine::DecryptError; char * buf = (char *)kvi_malloc(len + 1); int retVal = m_pDecryptCipher->padDecrypt((const unsigned char *)binary,len,(unsigned char *)buf); kvi_free(binary); if(retVal < 0) { kvi_free(buf); setLastErrorFromRijndaelErrorCode(retVal); return KviCryptEngine::DecryptError; } buf[retVal] = '\0'; plainText = buf; kvi_free(buf); return KviCryptEngine::DecryptOkWasEncrypted; } bool KviRijndaelHexEngine::binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer) { outBuffer.bufferToHex(inBuffer,len); return true; } bool KviRijndaelHexEngine::asciiToBinary(const char * inBuffer,int * len,char ** outBuffer) { KviStr hex(inBuffer); char * tmpBuf; *len = hex.hexToBuffer(&tmpBuf,false); if(*len < 0) { setLastError(__tr("The message is not a hexadecimal string: this is not my stuff")); return false; } else { if(len > 0) { *outBuffer = (char *)kvi_malloc(*len); kvi_memmove(*outBuffer,tmpBuf,*len); KviStr::freeBuffer(tmpBuf); } } return true; } bool KviRijndaelBase64Engine::binaryToAscii(const char * inBuffer,int len,KviStr &outBuffer) { outBuffer.bufferToBase64(inBuffer,len); return true; } bool KviRijndaelBase64Engine::asciiToBinary(const char * inBuffer,int * len,char ** outBuffer) { KviStr base64(inBuffer); char * tmpBuf; *len = base64.base64ToBuffer(&tmpBuf,false); if(*len < 0) { setLastError(__tr("The message is not a base64 string: this is not my stuff")); return false; } else { if(len > 0) { *outBuffer = (char *)kvi_malloc(*len); kvi_memmove(*outBuffer,tmpBuf,*len); KviStr::freeBuffer(tmpBuf); } } return true; } static KviCryptEngine * allocRijndael128HexEngine() { return new KviRijndael128HexEngine(); } static KviCryptEngine * allocRijndael192HexEngine() { return new KviRijndael192HexEngine(); } static KviCryptEngine * allocRijndael256HexEngine() { return new KviRijndael256HexEngine(); } static KviCryptEngine * allocRijndael128Base64Engine() { return new KviRijndael128Base64Engine(); } static KviCryptEngine * allocRijndael192Base64Engine() { return new KviRijndael192Base64Engine(); } static KviCryptEngine * allocRijndael256Base64Engine() { return new KviRijndael256Base64Engine(); } static void deallocRijndaelCryptEngine(KviCryptEngine * e) { delete e; } // Mircryption stuff #include "ablowfish.h" KviMircryptionEngine::KviMircryptionEngine() : KviCryptEngine() { g_pEngineList->append(this); } KviMircryptionEngine::~KviMircryptionEngine() { g_pEngineList->removeRef(this); } bool KviMircryptionEngine::init(const char * encKey,int encKeyLen,const char * decKey,int decKeyLen) { if(encKey && (encKeyLen > 0)) { if(!(decKey && (decKeyLen > 0))) { decKey = encKey; decKeyLen = encKeyLen; } // else all } else { // no encrypt key specified... if(decKey && decKeyLen) { encKey = decKey; encKeyLen = decKeyLen; } else { // both keys missing setLastError(__tr("Missing both encrypt and decrypt key: at least one is needed")); return false; } } m_szEncryptKey = KviStr(encKey,encKeyLen); m_szDecryptKey = KviStr(decKey,decKeyLen); if(kvi_strEqualCIN("cbc:",m_szEncryptKey.ptr(),4) && (m_szEncryptKey.len() > 4)) m_szEncryptKey.cutLeft(4); else m_bEncryptCBC = false; if(kvi_strEqualCIN("cbc:",m_szDecryptKey.ptr(),4) && (m_szDecryptKey.len() > 4)) m_szDecryptKey.cutLeft(4); else m_bDecryptCBC = false; return true; } KviCryptEngine::EncryptResult KviMircryptionEngine::encrypt(const char * plainText,KviStr &outBuffer) { KviStr szPlain = plainText; outBuffer = ""; if(m_bEncryptCBC) { if(!doEncryptCBC(szPlain,outBuffer))return KviCryptEngine::EncryptError; } else { if(!doEncryptECB(szPlain,outBuffer))return KviCryptEngine::EncryptError; } outBuffer.prepend("+OK "); if(outBuffer.len() > maxEncryptLen()) { if(maxEncryptLen() > 0) { setLastError(__tr("Data buffer too long")); return KviCryptEngine::EncryptError; } } //outBuffer = MCPS2_STARTTAG; //outBuffer += MCPS2_ENDTAG; return KviCryptEngine::Encrypted; } KviCryptEngine::DecryptResult KviMircryptionEngine::decrypt(const char * inBuffer,KviStr &plainText) { plainText = ""; KviStr szIn = inBuffer; // various old versions if(kvi_strEqualCSN(inBuffer,"mcps ",5)) szIn.cutLeft(5); else if(kvi_strEqualCSN(inBuffer,"+OK ",4)) szIn.cutLeft(4); else { plainText = szIn; return KviCryptEngine::DecryptOkWasPlainText; } if(m_bDecryptCBC)return doDecryptCBC(szIn,plainText) ? KviCryptEngine::DecryptOkWasEncrypted : KviCryptEngine::DecryptError; return doDecryptECB(szIn,plainText) ? KviCryptEngine::DecryptOkWasEncrypted : KviCryptEngine::DecryptError; /* int len1 = kvi_strLen(MCPS2_STARTTAG); int len2 = kvi_strLen(MCPS2_ENDTAG); while(szIn.len() > 0) { int idx = szIn.findFirstIdx(MCPS2_STARTTAG); if(idx == -1) { // no more encrypted stuff plainText += szIn; return true; } if(idx > 0) // a non encrypted block plainText += szIn.left(idx); szIn.cutLeft(idx + len1); idx = szIn.findFirstIdx(MCPS2_ENDTAG); if(idx != -1) { KviStr toDecrypt = szIn.left(idx); if(!doDecrypt(toDecrypt,plainText))return false; } szIn.cutLeft(idx + len2); } */ } static unsigned char fake_base64[]="./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; unsigned int fake_base64dec(unsigned char c) { static char base64unmap[255]; static bool didinit=false; int i; if(!didinit) { // initialize base64unmap for (i=0;i<255;++i)base64unmap[i]=0; for (i=0;i<64;++i)base64unmap[fake_base64[i]]=i; didinit=true; } return base64unmap[c]; } static void byteswap_buffer(unsigned char * p,int len) { while(len > 0) { unsigned char aux = p[0]; p[0] = p[3]; p[3] = aux; aux = p[1]; p[1] = p[2]; p[2] = aux; p += 4; len -= 4; } } bool KviMircryptionEngine::doEncryptECB(KviStr &plain,KviStr &encoded) { // make sure it is a multiple of 8 bytes (eventually pad with zeroes) if(plain.len() % 8) { int oldL = plain.len(); plain.setLength(plain.len() + (8 - (plain.len() % 8))); char * padB = plain.ptr() + oldL; char * padE = plain.ptr() + plain.len(); while(padB < padE)*padB++ = 0; } //byteswap_buffer((unsigned char *)plain.ptr(),plain.len()); unsigned char * out =(unsigned char *)kvi_malloc(plain.len()); // we use this to avoid endiannes problems BlowFish bf((unsigned char *)m_szEncryptKey.ptr(),m_szEncryptKey.len()); bf.ResetChain(); bf.Encrypt((unsigned char *)plain.ptr(),out,plain.len(),BlowFish::ECB); // FIXME: this is probably needed only on LittleEndian machines! byteswap_buffer((unsigned char *)out,plain.len()); // da uglybase64 encoding unsigned char * outb = out; unsigned char * oute = out + plain.len(); int ll = (plain.len() * 3) / 2; encoded.setLength(ll); unsigned char * p = (unsigned char *)encoded.ptr(); while(outb < oute) { TQ_UINT32 * dd1 = (TQ_UINT32 *)outb; outb += 4; TQ_UINT32 * dd2 = (TQ_UINT32 *)outb; outb += 4; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *dd2 >>= 6; *p++ = fake_base64[*dd2 & 0x3f]; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; *dd1 >>= 6; *p++ = fake_base64[*dd1 & 0x3f]; } kvi_free(out); return true; } bool KviMircryptionEngine::doDecryptECB(KviStr &encoded,KviStr &plain) { // encoded is in this strange base64... // make sure its length is multiple of 12 (eventually pad with zeroes) if(encoded.len() % 12) { int oldL = encoded.len(); encoded.setLength(encoded.len() + (12 - (encoded.len() % 12))); char * padB = encoded.ptr() + oldL; char * padE = encoded.ptr() + encoded.len(); while(padB < padE)*padB++ = 0; } // a fake base64 decoding algo, use a different character set // and stuff 6 bytes at a time into a 32 bit long... int ll = (encoded.len() * 2) / 3; unsigned char * buf = (unsigned char *)kvi_malloc(ll); unsigned char * p = (unsigned char *)encoded.ptr(); unsigned char * e = p + encoded.len(); int i; unsigned char * bufp = buf; while(p < e) { TQ_UINT32 * dw1 = (TQ_UINT32 *)bufp; bufp += 4; TQ_UINT32 * dw2 = (TQ_UINT32 *)bufp; bufp += 4; *dw2 = 0; for(i=0;i < 6;i++)*dw2 |= (fake_base64dec(*p++)) << (i * 6); *dw1 = 0; for(i=0;i < 6;i++)*dw1 |= (fake_base64dec(*p++)) << (i * 6); } // FIXME: this is probably needed only on LittleEndian machines! byteswap_buffer((unsigned char *)buf,ll); plain.setLength(ll); BlowFish bf((unsigned char *)m_szDecryptKey.ptr(),m_szDecryptKey.len()); bf.ResetChain(); bf.Decrypt(buf,(unsigned char *)plain.ptr(),ll,BlowFish::ECB); //byteswap_buffer((unsigned char *)plain.ptr(),ll); kvi_free(buf); return true; } bool KviMircryptionEngine::doEncryptCBC(KviStr &plain,KviStr &encoded) { // make sure it is a multiple of 8 bytes (eventually pad with zeroes) if(plain.len() % 8) { int oldL = plain.len(); plain.setLength(plain.len() + (8 - (plain.len() % 8))); char * padB = plain.ptr() + oldL; char * padE = plain.ptr() + plain.len(); while(padB < padE)*padB++ = 0; } int ll = plain.len() + 8; unsigned char * in = (unsigned char *)kvi_malloc(ll); // choose an IV static bool bDidInit = false; int t = (int)kvi_unixTime(); if(!bDidInit) { srand(t); bDidInit = true; } for(int i=0;i<8;i++)in[i] = (unsigned char)(rand() % 256); kvi_fastmove(in+8,plain.ptr(),plain.len()); // encrypt unsigned char * out = (unsigned char *)kvi_malloc(ll); BlowFish bf((unsigned char *)m_szEncryptKey.ptr(),m_szEncryptKey.len()); bf.ResetChain(); bf.Encrypt(in,out,ll,BlowFish::CBC); kvi_free(in); encoded.bufferToBase64((const char *)out,ll); kvi_free(out); encoded.prepend('*'); // prepend the signature return true; } bool KviMircryptionEngine::doDecryptCBC(KviStr &encoded,KviStr &plain) { if(*(encoded.ptr()) != '*') { tqDebug("WARNING: Specified a CBC key but the incoming message doesn't seem to be a CBC one"); return doDecryptECB(encoded,plain); } encoded.cutLeft(1); char * tmpBuf; int len = encoded.base64ToBuffer(&tmpBuf,false); if(len < 0) { setLastError(__tr("The message is not a base64 string: this is not my stuff")); return false; } if((len < 8) || (len % 8)) { setLastError(__tr("The message doesn't seem to be encoded with CBC Mircryption")); if(len > 0)KviStr::freeBuffer(tmpBuf); return false; } plain.setLength(len); BlowFish bf((unsigned char *)m_szDecryptKey.ptr(),m_szDecryptKey.len()); bf.ResetChain(); bf.Decrypt((unsigned char *)tmpBuf,(unsigned char *)plain.ptr(),len,BlowFish::CBC); // kill the first 8 bytes (random IV) plain.cutLeft(8); KviStr::freeBuffer(tmpBuf); return true; } static KviCryptEngine * allocMircryptionEngine() { return new KviMircryptionEngine(); } #endif // ======================================= // module routines // ======================================= static bool rijndael_module_init(KviModule * m) { #ifdef COMPILE_CRYPT_SUPPORT g_pEngineList = new KviPointerList; g_pEngineList->setAutoDelete(false); KviStr format = __tr("Cryptographic engine based on the\n" \ "Advanced Encryption Standard (AES)\n" \ "algorithm called Rijndael.\n" \ "The text is first encrypted with rijndael\n" \ "and then converted to %s notation.\n" \ "The keys used are %d bit long and will be padded\n" \ "with zeros if you provide shorter ones.\n" \ "If only one key is provided, this engine\n" \ "will use it for both encrypting and decrypting.\n" \ "See the rijndael module documentation\n" \ "for more info on the algorithm used.\n"); // FIXME: Maybe convert this repeated code to a function eh ? KviCryptEngineDescription * d = new KviCryptEngineDescription; d->szName = "Rijndael128Hex"; d->szAuthor = "Szymon Stefanek"; d->szDescription.sprintf(format.ptr(),__tr("hexadecimal"),128); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocRijndael128HexEngine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); d = new KviCryptEngineDescription; d->szName = "Rijndael192Hex"; d->szAuthor = "Szymon Stefanek"; d->szDescription.sprintf(format.ptr(),__tr("hexadecimal"),192); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocRijndael192HexEngine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); d = new KviCryptEngineDescription; d->szName = "Rijndael256Hex"; d->szAuthor = "Szymon Stefanek"; d->szDescription.sprintf(format.ptr(),__tr("hexadecimal"),256); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocRijndael256HexEngine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); d = new KviCryptEngineDescription; d->szName = "Rijndael128Base64"; d->szAuthor = "Szymon Stefanek"; d->szDescription.sprintf(format.ptr(),__tr("base64"),128); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocRijndael128Base64Engine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); d = new KviCryptEngineDescription; d->szName = "Rijndael192Base64"; d->szAuthor = "Szymon Stefanek"; d->szDescription.sprintf(format.ptr(),__tr("base64"),192); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocRijndael192Base64Engine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); d = new KviCryptEngineDescription; d->szName = "Rijndael256Base64"; d->szAuthor = "Szymon Stefanek"; d->szDescription.sprintf(format.ptr(),__tr("base64"),256); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocRijndael256Base64Engine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); d = new KviCryptEngineDescription; d->szName = "Mircryption"; d->szAuthor = "Szymon Stefanek"; d->szDescription = __tr("Popular cryptographic engine based on the\n" \ "old Blowfish encryption algorithm.\n" \ "The text is first encrypted with Blowfish \n" \ "and then converted to base64 notation.\n" \ "The keys used have variable length and\n" \ "are specified as character strings.\n" \ "You can specify keys long up to 56 bytes (448 bits).\n" \ "If only one key is provided, this engine\n" \ "will use it for both encrypting and decrypting.\n" \ "This engine works in ECB mode by default:\n" \ "if you want to use CBC mode you must prefix\n" \ "your key(s) with \"cbc:\".\n"); d->iFlags = KVI_CRYPTENGINE_CAN_ENCRYPT | KVI_CRYPTENGINE_CAN_DECRYPT | KVI_CRYPTENGINE_WANT_ENCRYPT_KEY | KVI_CRYPTENGINE_WANT_DECRYPT_KEY; d->allocFunc = allocMircryptionEngine; d->deallocFunc = deallocRijndaelCryptEngine; m->registerCryptEngine(d); return true; #else return false; #endif } static bool rijndael_module_cleanup(KviModule *m) { #ifdef COMPILE_CRYPT_SUPPORT while(g_pEngineList->first())delete g_pEngineList->first(); delete g_pEngineList; g_pEngineList = 0; m->unregisterCryptEngines(); return true; #else return false; #endif } static bool rijndael_module_can_unload(KviModule *) { #ifdef COMPILE_CRYPT_SUPPORT return g_pEngineList->isEmpty(); #else return true; #endif } // ======================================= // plugin definition structure // ======================================= KVIRC_MODULE( "Rijndael crypt engine", "1.0.0", "Szymon Stefanek " , "Exports the rijndael crypt engine", rijndael_module_init , rijndael_module_can_unload, 0, rijndael_module_cleanup ) #ifdef COMPILE_CRYPT_SUPPORT #include "libkvirijndael.moc" #endif