From dac1f42ef81ac1119430fd294a6b35b0b8cd6837 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 25 Jan 2015 17:45:10 +0000 Subject: - class KeyStream extracted to the separate module; - xml attributes redesigned to produce efficient code; - many small improvements git-svn-id: http://svn.miranda-ng.org/main/trunk@11905 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp | 89 +++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp (limited to 'protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp') diff --git a/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp new file mode 100644 index 0000000000..f4741729a7 --- /dev/null +++ b/protocols/WhatsApp/src/WhatsAPI++/KeyStream.cpp @@ -0,0 +1,89 @@ +/* + * WALogin.cpp + * + * Created on: 26/06/2012 + * Author: Antonio + */ + +#include "../common.h" // #TODO Remove Miranda-dependency + +#include "WALogin.h" +#include "ByteArray.h" +#include "ProtocolTreeNode.h" +#include "WAException.h" + +using namespace Utilities; + +KeyStream::KeyStream(unsigned char* _key, unsigned char* _keyMac) : + seq(0) +{ + memcpy(key, _key, 20); + memcpy(keyMac, _keyMac, 20); + + RC4_set_key(&this->rc4, 20, this->key); + + unsigned char drop[768]; + RC4(&this->rc4, sizeof(drop), drop, drop); + + HMAC_CTX_init(&hmac); +} + +KeyStream::~KeyStream() +{ + HMAC_CTX_cleanup(&hmac); +} + +void KeyStream::keyFromPasswordAndNonce(const std::string& pass, const std::vector& nonce, unsigned char *out) +{ + size_t cbSize = nonce.size(); + + uint8_t *pNonce = (uint8_t*)_alloca(cbSize + 1); + memcpy(pNonce, nonce.data(), cbSize); + + for (int i = 0; i < 4; i++) { + pNonce[cbSize] = i + 1; + PKCS5_PBKDF2_HMAC_SHA1(pass.data(), (int)pass.size(), pNonce, (int)cbSize+1, 2, 20, out + i*20); + } +} + +void KeyStream::decodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) +{ + unsigned char digest[20]; + this->hmacsha1(buffer + offset, length, digest); + + if (memcmp(&buffer[macOffset], digest, 4)) + throw WAException("invalid MAC", WAException::CORRUPT_STREAM_EX, 0); + + unsigned char* out = (unsigned char*)_alloca(length); + RC4(&this->rc4, length, buffer + offset, out); + memcpy(buffer + offset, out, length); +} + +void KeyStream::encodeMessage(unsigned char* buffer, int macOffset, int offset, const int length) +{ + unsigned char* out = (unsigned char*)_alloca(length); + RC4(&this->rc4, length, buffer + offset, out); + memcpy(buffer + offset, out, length); + + unsigned char digest[20]; + this->hmacsha1(buffer + offset, length, digest); + memcpy(buffer + macOffset, digest, 4); +} + +void KeyStream::hmacsha1(unsigned char* text, int textLength, unsigned char *out) +{ + HMAC_Init(&hmac, this->keyMac, 20, EVP_sha1()); + HMAC_Update(&hmac, text, textLength); + + unsigned char hmacInt[4]; + hmacInt[0] = (this->seq >> 24); + hmacInt[1] = (this->seq >> 16); + hmacInt[2] = (this->seq >> 8); + hmacInt[3] = (this->seq); + HMAC_Update(&hmac, hmacInt, sizeof(hmacInt)); + + unsigned int mdLength; + HMAC_Final(&hmac, out, &mdLength); + + this->seq++; +} -- cgit v1.2.3