void decode(KviCString & szText, unsigned char ** buf, int *len) { // make sure its length is multiple of 12 (eventually pad with zeroes) if(szText.len() % 12) { int oldL = szText.len(); szText.setLen(szText.len() + (12 - (szText.len() % 12))); char * padB = szText.ptr() + oldL; char * padE = szText.ptr() + szText.len(); while(padB < padE)*padB++ = 0; } *len = (int)(szText.len() * 2) / 3; *buf = (unsigned char *)KviMemory::allocate(*len); unsigned char * p = (unsigned char *)szText.ptr(); unsigned char * e = p + szText.len(); int i; unsigned char * bufp = *buf; while(p < e) { quint32 * dw1 = (quint32 *)bufp; bufp += 4; quint32 * dw2 = (quint32 *)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(*buf,*len); }
bool KviMircryptionEngine::doEncryptCBC(KviCString & plain, KviCString & encoded) { // make sure it is a multiple of 8 bytes (eventually pad with zeroes) if(plain.len() % 8) { int oldL = plain.len(); plain.setLen(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 *)KviMemory::allocate(ll); InitVectorEngine::fillRandomIV(in, 8); KviMemory::copy(in + 8, plain.ptr(), plain.len()); // encrypt unsigned char * out = (unsigned char *)KviMemory::allocate(ll); BlowFish bf((unsigned char *)m_szEncryptKey.ptr(), m_szEncryptKey.len()); bf.ResetChain(); bf.Encrypt(in, out, ll, BlowFish::CBC); KviMemory::free(in); encoded.bufferToBase64((const char *)out, ll); KviMemory::free(out); encoded.prepend('*'); // prepend the signature return true; }
bool KviFile::load(KviCString & szData) { kvi_u32_t iLen; if(!load(iLen)) return false; szData.setLen(iLen); return (read((char *)(szData.ptr()), iLen) == iLen); }
bool KviMircryptionEngine::doDecryptECB(KviCString & encoded, KviCString & plain) { unsigned char * buf = nullptr; int len; UglyBase64::decode(encoded, &buf, &len); plain.setLen(len); BlowFish bf((unsigned char *)m_szDecryptKey.ptr(), m_szDecryptKey.len()); bf.ResetChain(); bf.Decrypt(buf, (unsigned char *)plain.ptr(), len, BlowFish::ECB); KviMemory::free(buf); return true; }
bool KviMircryptionEngine::doEncryptECB(KviCString & plain, KviCString & encoded) { // make sure it is a multiple of 8 bytes (eventually pad with zeroes) if(plain.len() % 8) { int oldL = plain.len(); plain.setLen(plain.len() + (8 - (plain.len() % 8))); char * padB = plain.ptr() + oldL; char * padE = plain.ptr() + plain.len(); while(padB < padE) *padB++ = 0; } unsigned char * out = (unsigned char *)KviMemory::allocate(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); UglyBase64::encode(out, plain.len(), encoded); KviMemory::free(out); return true; }
bool KviMircryptionEngine::doDecryptCBC(KviCString & encoded, KviCString & plain) { if(*(encoded.ptr()) != '*') { qDebug("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(__tr2qs("The message is not a base64 string: this is not my stuff")); return false; } if((len < 8) || (len % 8)) { setLastError(__tr2qs("The message doesn't seem to be encoded with CBC Mircryption")); if(len > 0) KviCString::freeBuffer(tmpBuf); return false; } plain.setLen(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); KviCString::freeBuffer(tmpBuf); return true; }