15 version = ver[0].toInt() * qPow(2, 16) + ver[1].toInt() * qPow(2, 8) + ver[2].toInt();
17 ver_byte = bytes(ver[0].toInt()) +
18 bytes(ver[1].toInt()) +
19 bytes(ver[2].toInt());
26 return ModelPC().encrypt(data, image, _mode, key, _bitsUsed, _error);
31 return ModelPC().inject(encr_data, image, _mode, _bitsUsed, _error);
36 return ModelPC().decrypt(image, key, _mode, _error);
51 QImage *
ModelPC::encrypt(QByteArray data, QImage * image,
int _mode, QString key,
int _bitsUsed, QString *_error)
57 _error =
new QString();
61 if(data ==
nullptr || data.isEmpty()) {
65 if(data.size() > pow(2, 24)) {
69 if(image ==
nullptr || image->isNull()) {
73 if(image->width() * image->height() > pow(10, 9)) {
77 if(_bitsUsed < 1 || _bitsUsed > 8) {
81 if(key ==
nullptr || key.isEmpty()) {
85 else if(key.size() > 255) {
89 if(mode == CryptMode::Unspecified) {
90 fail(
"undefined_mode");
93 long long usedBytes = data.size() + 14 + key.size();
94 long long size = image->width() * image->height();
95 if(usedBytes * 100 / (size * 3) * 8 / _bitsUsed > 70) {
104 QByteArray zipped_data =
zip(data, key.toUtf8());
105 QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Sha256);
106 QByteArray encr_data = hash + zipped_data;
108 return inject(encr_data, image, _mode, _bitsUsed,
error);
114 bitsUsed = _bitsUsed;
139 QImage *
ModelPC::inject(QByteArray encr_data, QImage * image,
int _mode,
int _bitsUsed, QString *_error)
144 if(_error ==
nullptr)
145 _error =
new QString();
149 bitsUsed = _bitsUsed;
151 if(encr_data ==
nullptr || encr_data.isEmpty()) {
155 if(encr_data.size() > pow(2, 24)) {
159 if(image ==
nullptr || image->isNull()) {
163 if(image->width() * image->height() > pow(10, 9)) {
167 if(_bitsUsed < 1 || _bitsUsed > 8) {
171 if(mode == CryptMode::Unspecified) {
172 fail(
"undefined_mode");
176 encr_data = ver_byte + encr_data;
177 long long int countBytes = encr_data.size();
181 circuit(image, &encr_data, countBytes);
184 jphs(image, &encr_data);
217 if(_error ==
nullptr)
218 _error =
new QString();
221 if(image ==
nullptr || image->isNull()) {
225 if(image->width() * image->height() > pow(10, 9)) {
229 if(key ==
nullptr || key.isEmpty()) {
267 fail(
"all_modes_fail");
288 alert(message,
true);
290 qDebug() <<
"[Debug] !!! fail() - " << message;
306 bool isEncrypt = !data->isEmpty();
307 QString targetEXE =
defaultJPHSDir + (isEncrypt ?
"/jphide.exe" :
"/jpseek.exe");
308 if(!fileExists(targetEXE))
316 for(
int i = 0; i < 10; i++)
317 randomFileName.append(97 + qrand() % 25);
318 image->save(randomFileName +
".jpg");
320 QFile file(randomFileName +
".pc");
321 if(!file.open(QFile::WriteOnly)) {
322 fail(
"save_file_fail");
329 args << (randomFileName +
".jpg") << (randomFileName +
"_out.jpg") << (randomFileName +
".pc");
331 prog.start(targetEXE, args);
332 prog.waitForStarted();
333 prog.write(
"test\n");
334 prog.waitForBytesWritten();
335 prog.write(
"test\n");
336 prog.waitForBytesWritten();
337 prog.waitForReadyRead();
338 QByteArray bytes = prog.readAll();
339 prog.waitForFinished();
364 bool isEncrypt = !data->isEmpty();
367 int w = image->width();
368 int h = image->height();
371 QVector <QPoint> were;
372 were.push_back(QPoint(0, 0));
373 were.push_back(QPoint(0, h - 1));
374 were.push_back(QPoint(w - 1, 0));
375 were.push_back(QPoint(w - 1, h - 1));
377 long long int offset = 0;
381 circuitImage = image;
382 circuitCountBytes = countBytes;
387 for(
int i = 1; i < h - 1 && mustGoOn(isEncrypt); i++) {
392 if(mustGoOn(isEncrypt))
394 for(
int i = h - 2; i >= 1 && mustGoOn(isEncrypt); i--){
395 QPoint pos(w - 1, i);
401 while(mustGoOn(isEncrypt))
404 for(
int i = offset; i < h - offset && mustGoOn(isEncrypt); i++){
405 QPoint pos(w - offset - 2, i);
409 for(
int i = offset + 1; i < w - offset - 2 && mustGoOn(isEncrypt); i++){
410 QPoint pos(i, offset);
414 for(
int i = w - 3 - offset; i >= offset + 2 && mustGoOn(isEncrypt); i--){
415 QPoint pos(i, h - offset - 1);
419 for(
int i = offset + 1; i < h - offset && mustGoOn(isEncrypt); i++){
420 QPoint pos(offset + 1, i);
431 QColor colUL = image->pixelColor(0, 0).toRgb();
432 QColor colUR = image->pixelColor(w - 1, 0).toRgb();
433 QColor colDL = image->pixelColor(0, h - 1).toRgb();
434 QColor colDR = image->pixelColor(w - 1, h - 1).toRgb();
440 red = (colUL.red() & 224) + (countBytes >> 19);
441 green = (colUL.green() & 224) + (countBytes >> 14) % 32;
442 blue = (colUL.blue() & 224) + (countBytes >> 9) % 32;
443 image->setPixelColor(0, 0, QColor(red, green, blue));
446 red = (colUR.red() & 224) + (countBytes >> 4) % 32;
447 green = (colUR.green() & 224) + ((countBytes % 16) << 1) + 1;
448 blue = (colUR.blue() & 224) + 9;
449 image->setPixelColor(w - 1, 0, QColor(red, green, blue));
452 while(cur < countBytes)
453 push(mod(circuitData->at(cur++)), 8);
454 if(bitsBuffer.size() > 20) {
455 fail(
"bitsBufferFail");
459 long extraData = pop(-2);
462 red = (colDL.red() & 224) + (extraData >> 15);
463 green = (colDL.green() & 224) + (extraData >> 10) % 32;
464 blue = (colDL.blue() & 224) + (extraData >> 5) % 32;
465 image->setPixelColor(0, h - 1, QColor(red, green, blue));
468 red = (colDR.red() & 224) + extraData % 32;
469 green = (colDR.green() & 224);
470 blue = (colDR.blue() & 224) + ((bitsUsed - 1) << 2) + 2;
471 image->setPixelColor(w - 1, h - 1, QColor(red, green, blue));
476 QColor colDL = image->pixelColor(0, h - 1).toRgb();
477 QColor colDR = image->pixelColor(w - 1, h - 1).toRgb();
480 long extraData = ((colDL.red() % 32) << 15) + ((colDL.green() % 32) << 10);
481 extraData += ((colDL.blue() % 32) << 5) + colDR.red() % 32;
484 push(extraData, (countBytes - cur) * 8 - bitsBuffer.size());
487 while(!bitsBuffer.isEmpty())
488 data->append(pop(8));
505 if(were->contains(pos)){
506 fail(
"point_visited_twice");
510 were->push_back(pos);
514 while(bitsBuffer.size() < 3 * bitsUsed)
515 push(mod(circuitData->at(cur++)), 8);
517 QColor pixelColor = circuitImage->pixelColor(pos);
518 int red = pixelColor.red();
519 int green = pixelColor.green();
520 int blue = pixelColor.blue();
523 red += pop() - red % (int) qPow(2, bitsUsed);
524 green += pop() - green % (int) qPow(2, bitsUsed);
525 blue += pop() - blue % (int) qPow(2, bitsUsed);
527 circuitImage->setPixelColor(pos, QColor(red, green, blue));
531 QColor read_color = circuitImage->pixelColor(pos).toRgb();
533 int red = read_color.red();
534 int green = read_color.green();
535 int blue = read_color.blue();
538 red %= (int) qPow(2, bitsUsed);
539 green %= (int) qPow(2, bitsUsed);
540 blue %= (int) qPow(2, bitsUsed);
548 while(bitsBuffer.size() >= 8) {
549 circuitData->append(pop(8));
563 if(data.size() + 98 > image->height() * image->width() * 3) {
567 QTime st = QTime::currentTime();
568 QByteArray rand_master = GetRandomBytes(32);
569 QByteArray pass = QCryptographicHash::hash(key.toUtf8() + rand_master + QByteArray(
"hi"), QCryptographicHash::Sha3_384);
570 QByteArray noise = GetRandomBytes(data.size() / 10 + 32);
571 QByteArray bytes_key = GetRandomBytes(32);
572 QByteArray pass_rand = QCryptographicHash::hash(pass + bytes_key, QCryptographicHash::Sha3_512);
573 QByteArray zipped =
zip(data, pass_rand);
574 QByteArray heavy_data = zipped + noise;
576 QByteArray verification = QCryptographicHash::hash(pass + bytes_key, QCryptographicHash::Sha3_256);
577 QByteArray given_key = bytes_key.left(30);
578 QByteArray heavy_data_size;
580 long long raw_size = zipped.size();
581 for(
int i = 0; i < 4; i++) {
582 int ch = raw_size % 256;
584 heavy_data_size.push_front(ch);
586 QByteArray mid_data = verification + given_key + rand_master + heavy_data_size;
588 QVector <QPair<QPoint, QPair<int, int>>> *were =
new QVector <QPair<QPoint, QPair<int, int>>>();
593 QTime
final = QTime::currentTime();
594 qDebug() <<
"[Debug] Finished encrypting in " << st.msecsTo(
final) <<
" msecs.";
605 QTime st = QTime::currentTime();
606 QByteArray mid_data, heavy_data;
607 QVector <QPair<QPoint, QPair<int, int>>> *were =
new QVector <QPair<QPoint, QPair<int, int>>>();
610 QByteArray verification = mid_data.left(32);
611 QByteArray given_key = mid_data.mid(32, 30);
612 QByteArray rand_master = mid_data.mid(62, 32);
613 QByteArray heavy_data_size = mid_data.right(4);
615 QByteArray pass = QCryptographicHash::hash(key.toUtf8() + rand_master + QByteArray(
"hi"), QCryptographicHash::Sha3_384);
619 QByteArray bytes_key;
620 for(
long long i = 0; i < pow(2, 16); i++) {
621 QByteArray guess_part;
623 for(
int q = 0; q < 2; q++) {
626 guess_part.push_front(ch);
629 QByteArray guess = given_key + guess_part;
630 QByteArray check = QCryptographicHash::hash(pass + guess, QCryptographicHash::Sha3_256);
631 if(check == verification) {
636 if(bytes_key.isEmpty()) {
641 QByteArray pass_rand = QCryptographicHash::hash(pass + bytes_key, QCryptographicHash::Sha3_512);
643 long long raw_size = mod(heavy_data_size[3]) +
644 mod(heavy_data_size[2]) * pow(2, 8) +
645 mod(heavy_data_size[1]) * pow(2, 16) +
646 mod(heavy_data_size[0]) * pow(2, 24);
649 QByteArray unzipped =
unzip(heavy_data, pass_rand);
651 QTime
final = QTime::currentTime();
652 qDebug() <<
"[Debug] Finished decrypting in " << st.msecsTo(
final) <<
" msecs.";
664 void ModelPC::proccessPixelsv1_4(QImage *image, QByteArray* data, QByteArray key,
bool isEncrypt, QVector <QPair<QPoint, QPair<int, int>>> *were,
long long size)
666 long w = image->width();
667 long h = image->height();
668 auto seed_hex = QCryptographicHash::hash(key, QCryptographicHash::Sha3_256).toHex().left(8).toUpper();
669 auto seed = seed_hex.toLongLong(
nullptr, 16);
670 QRandomGenerator foo(seed);
673 long long left = (size == -1 ? data->size() : size) * 8;
674 long long all = left;
679 if(bitsBuffer.empty())
680 push(mod(data->at(cur++)), 8);
681 quint64 g = foo.generate64() % (w * h);
684 int c = foo.generate64() % 3;
685 int b = foo.generate64() % 24;
697 auto piece = qMakePair(QPoint(x, y), qMakePair(c, bit));
698 if(were->contains(piece))
704 QColor pixel = image->pixelColor(piece.first);
705 int red = pixel.red();
706 int green = pixel.green();
707 int blue = pixel.blue();
715 dif |= 1 << (7 - bit);
716 dif ^= (wr ^ 1) << (7 - bit);
723 image->setPixelColor(piece.first, QColor(red, green, blue));
728 while (bitsBuffer.size() >= 8)
729 data->push_back(pop(8));
730 quint64 g = foo.generate64() % (w * h);
733 int c = foo.generate64() % 3;
734 int b = foo.generate64() % 24;
746 auto piece = qMakePair(QPoint(x, y), qMakePair(c, bit));
747 if(were->contains(piece))
752 QColor pixel = image->pixelColor(piece.first);
753 int red = pixel.red();
754 int green = pixel.green();
755 int blue = pixel.blue();
763 dif &= 1 << (7 - bit);
767 while (bitsBuffer.size() >= 8)
768 data->push_back(pop(8));
781 int w = image->width();
782 int h = image->height();
785 QColor colUL = image->pixelColor(0, 0).toRgb();
786 QColor colUR = image->pixelColor(w - 1, 0).toRgb();
787 QColor colDR = image->pixelColor(w - 1, h - 1).toRgb();
791 int verifCode = (((colUR.green() % 2) << 5) + colUR.blue() % 32) << 2;
792 verifCode += colDR.blue() % 4;
793 if(verifCode != 166){
798 long long int countBytes = (colUL.blue() % 32 + ((colUL.green() % 32) << 5) + ((colUL.red() % 32) << 10)) << 9;
799 countBytes += ((colUR.red() % 32) << 4) + (colUR.green() >> 1) % 16;
801 bitsUsed = (colDR.blue() >> 2) % 8 + 1;
806 circuit(image, &data, countBytes);
818 long long int _ver = mod(data.at(0)) * qPow(2, 16);
819 _ver += mod(data.at(1)) * qPow(2, 8);
820 _ver += mod(data.at(2));
831 QByteArray hash = data.left(32);
835 QByteArray unzipped_data =
unzip(data, key.toUtf8());
836 QByteArray our_hash = QCryptographicHash::hash(unzipped_data, QCryptographicHash::Sha256);
837 if(our_hash != hash) {
839 return QByteArray(
"");
841 return unzipped_data;
843 long ModelPC::pop(
int bits)
847 int poppedBits = bits == -1 ? bitsUsed : bits;
849 poppedBits = bitsBuffer.size();
850 for(
int i = 0; i < poppedBits; i++)
851 res += bitsBuffer[i] * qPow(2, poppedBits - i - 1);
852 bitsBuffer.remove(0, poppedBits);
856 void ModelPC::push(
int data,
int bits)
859 int buf_size = bitsBuffer.size();
860 int extraSize = bits == -1 ? bitsUsed : bits;
861 bitsBuffer.resize(buf_size + extraSize);
862 for(
int i = bitsBuffer.size() - 1; i >= buf_size; i--, data >>= 1)
863 bitsBuffer[i] = data % 2;
866 bool ModelPC::mustGoOn(
bool isEncrypt)
868 return success && (isEncrypt ? (circuitCountBytes - cur) * 8 + bitsBuffer.size() >= bitsUsed * 3 :
869 circuitData->size() * 8 + bitsBuffer.size() <
870 circuitCountBytes * 8 - (circuitCountBytes * 8)% (bitsUsed * 3));
883 QByteArray hashKey = QCryptographicHash::hash(key, QCryptographicHash::Sha256);
885 QByteArray new_data = encryption.
decode(data, hashKey);
887 return qUncompress(new_data);
900 QByteArray c_data = qCompress(data, 9);
902 QByteArray hashKey = QCryptographicHash::hash(key, QCryptographicHash::Sha256);
906 bool ModelPC::fileExists(QString path)
908 QFileInfo check_file(path);
909 return check_file.exists() && check_file.isFile();
918 QByteArray ModelPC::bytes(
long long n)
920 return QByteArray::fromHex(QByteArray::number(n, 16));
928 unsigned int ModelPC::mod(
int input)
931 return (
unsigned int) (256 + input);
933 return (
unsigned int) input;
950 QColor ModelPC::RGBbytes(
long long byte)
952 int blue = byte % 256;
953 int green = (byte / 256) % 256;
954 int red = byte / qPow(2, 16);
955 return QColor(red, green, blue);
958 QString ModelPC::generateVersionString(
long ver)
960 return QString::number((
int)( ver / qPow(2, 16))) +
"." + QString::number(((
int) (ver / 256)) % 256) +
"." + QString::number(ver % 256);
963 uint ModelPC::randSeed()
965 QTime time = QTime::currentTime();
966 uint randSeed = time.msecsSinceStartOfDay() % 55363 + time.minute() * 21 + time.second() * 2 + 239;
968 uint randSeed_2 = qrand() % 72341 + qrand() % 3 + qrand() % 2 + 566;
971 QByteArray ModelPC::GetRandomBytes(
long long count)
974 for(
int i = 0; i < count; i++)
975 res.append(qrand() % 256);
static QByteArray Crypt(QAESEncryption::Aes level, QAESEncryption::Mode mode, const QByteArray &rawText, const QByteArray &key, const QByteArray &iv=NULL, QAESEncryption::Padding padding=QAESEncryption::ISO)
Crypt Static encode function.
QByteArray decryptv1_4(QImage *image, QString key)
ModelPC::decryptv1_4 Decrypts data from image in v1.4+.
QByteArray zip(QByteArray data, QByteArray key)
ModelPC::zip Zip function, copy of EncryptDialog::zip Used for ModelPC in custom projects, other than PictureCrypt.
QString versionString
versionString Version as string
The QAESEncryption class Small and portable AES encryption class for Qt. Supports all key sizes - 128...
QByteArray decode(const QByteArray &rawText, const QByteArray &key, const QByteArray &iv=NULL)
decode Decodes data with AES
long version
version Version of the class
ModelPC()
ModelPC::ModelPC Constructor Unit tests are run here.
void alertView(QString messageCode, bool isWarning)
alertView Signal to be called to create MessageBox.
void proccessPixelsv1_4(QImage *image, QByteArray *data, QByteArray key, bool isEncrypt, QVector< QPair< QPoint, QPair< int, int > > > *were, long long size=-1)
ModelPC::proccessPixelsv1_4 Hides (or retrieves) data to/from pixels.
QString defaultJPHSDir
defaultJPHSDir Default JPHS directory
QImage * encrypt(QByteArray data, QImage *image, int _mode, QString key="", int _bitsUsed=8, QString *_error=nullptr)
ModelPC::encrypt Slot to zip and inject data and provide it with some extra stuff After completion st...
void saveData(QByteArray data)
saveData Signal to be called to save data from ModelPC::decrypt.
QByteArray decrypt(QImage *image, QString key, int _mode=Unspecified, QString *_error=nullptr)
ModelPC::decrypt Slot to be called when decrypt mode in ViewPC is selected and started.
void jphs(QImage *image, QByteArray *data)
ModelPC::jphs JPHS function to use jphide and jpseek (currently under development) ...
void circuit(QImage *image, QByteArray *data, long long int countBytes)
ModelPC::circuit The brain of the app. Via special circuit stores data in image.
QString * error
error Current error
void encryptv1_4(QImage *image, QByteArray data, QString key)
ModelPC::encryptv1_4 Encrypts and injects data to image used in v1.4+.
QImage * inject(QByteArray encr_data, QImage *image, int _mode, int _bitsUsed=8, QString *_error=nullptr)
ModelPC::inject Slot to be called when encrypt mode in ViewPC is selected and started.
void alert(QString message, bool isWarning=false)
ModelPC::alert Function emits signal ModelPC::alertView and calls ViewPC::alert.
void setProgress(int val)
setProgress Signal to be called to set progress of ProgressDialog.
QByteArray decryptv1_3(QImage *image, QString key)
ModelPC::decryptv1_3 Decrytps data from image in v1.3.
void fail(QString message)
ModelPC::fail Slot to stop execution of cryption.
static QImage * Inject(QByteArray encr_data, QImage *image, CryptMode _mode, int _bitsUsed=8, QString *_error=nullptr)
bool success
success Flag that true by default, but in case of error or cancelling of ProgressDialog it turns to f...
QByteArray unzip(QByteArray data, QByteArray key)
ModelPC::unzip Unzip data from ModelPC::decrypt. Just mirrored EncryptDialog::zip.
void saveImage(QImage *image)
saveImage Signal to be called to save image from ModelPC::encrypt.
static QByteArray Decrypt(QImage *image, QString key, CryptMode _mode=Unspecified, QString *_error=nullptr)
static QImage * Encrypt(QByteArray data, QImage *image, CryptMode _mode, QString key="", int _bitsUsed=8, QString *_error=nullptr)
void processPixel(QPoint pos, QVector< QPoint > *were, bool isEncrypt)
ModelPC::processPixel Processes every pixel. Reads its contains or writes data.