@BulaevInc

Как перенести объект из JS в другие языки?

В общем, сразу к делу
Существует такой код:
for (var i = CryptoJS.SHA512("hello"), n = 0; n < 10; n++) {
    i = CryptoJS.SHA512(i);
}

Не сложно понять что он делает: каждая новая итерация хеширует хеш предыдущего.. хэша.
И если CryptoJS.SHA512("hello") возвращает корректный хэш строки "hello", то уже i = CryptoJS.SHA512(i) хэширует не строку hello, а инстанс объекта CryptoJS. И такой метод был использован в строке, которую я хотел бы найти используя не JavaScript, а например C++.
Теперь поясню более подробно:
Вот JS код который я уже показывал завернутый в функцию:
function encodeManyTimes(str){
for (var i = CryptoJS.SHA512(str), n = 0; n < 5; n++) {
    console.log(i.toString()); 
    i = CryptoJS.SHA512(i);
    }
}

encodeManyTimes("hello")


И вот что он выводит:
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
0592a10584ffabf96539f3d780d776828c67da1ab5b169e9e8aed838aaecc9ed36d49ff1423c55f019e050c66c6324f53588be88894fef4dcffdb74b98e2b200
6d9f8ed2218b64d92f5e09788f29c56e3a7c3ff7bd5b2677b452ac1e3e5f9cbacf0f67cb9e27da424b4d3c325c27e5a6f8b563ae26972e47f0bfe4012f0474fe
a530df680b53b3f1ddd68947a3af8c686d59f7df65642e40d4ef65512dd295f58d50c4040d51ca3c5af43055d9b2ff4aca7bdba5bef077a92568554b50174d3f
5ab743e5b9704b2ae1584c7b768aba17d98388c1cb56b7c7240a0636157e21251ecb636baff93da58db7ea849c1f8717649a6963162ee8fe66fc9b391a2aa94c


Вот "этот же" алгоритм реализованный на C++:
void encodeManyTimes(std::string str){
       std::string i = CryptoC.SHA512(str);
       for(int n = 0; n < 5; n++){
         std::cout << i << std::endl;
         i = CryptoC.SHA512(str);
       }
    }

int main(){
encodeManyTimes("hello");
return 0;
}


И вывод уже такой:
9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
66c6a0830f3e5e4460d3ff64a23705e600e5d369ad3bda4a77ae9c0328115b813c2f7e6354add00cbad31c758bb9a122e4a4d84d52741b113908e8d735a9ac79
f48b46195cf8a8fbe2797a04a28c49e4d4f1c1aabfd6e96ca78133435c295096e03e1be39a42b4abe4505d22cef0646aad3f4012c408aae9dfc218cc90a67138
bff6d385a80adeda27cd26537d7abb54a26b39a1772f0b5d1fc5c8f2a46105464fe0d75765ad565da3181933231037ab93d2416ca1c6df2e25cf63c688d39f11
5f4b0c5db1bb5c26af9ce41fdbc1716120a5155c2d2b365f464e610bebc62ef34f2c487a87fae04952b9b2bd50c9b24fdd8b31a5fc6739893bf9597c31eeb4e2


Ну и сформулирую вопрос более широко: как мне добиться того, чтобы результат кода исполняемого на C++ был идентичен результату кода исполненного на JS НЕ трогая код на JS?
Может есть метод по которому можно как-то узнать в каком виде CryptoJS принимает в себя инстанс объекта самого себя и что он хеширует, чтобы повторить этот метод используя другие инструменты?

З.ы вот что я получаю если вывожу инстанс i (из первого кода) в какой-то из итераций в console.log, но как бы я не бился нельзя превратить это в хэш другими средствами, кроме JS
console.log(i)
{
  init: [Function (anonymous)],
  '$super': {
    init: [Function: init],
    toString: [Function: toString],
    concat: [Function: concat],
    clamp: [Function: clamp],
    clone: [Function: clone],
    random: [Function: random],
    '$super': {
      extend: [Function: extend],
      create: [Function: create],
      init: [Function: init],
      mixIn: [Function: mixIn],
      clone: [Function: clone]
    }
  },
  words: [
      93495557,  2231348217,
    1698296791,  2161604226,
    2355616282,  3048303081,
    3903772728,  2867644909,
     919904241,  1111250416,
    4729098438,  1818436853,
     898154120,  2303717197,
    3489511243, -1729973760
  ],
  sigBytes: 64
}
  • Вопрос задан
  • 688 просмотров
Решения вопроса 1
@GrayHorse
в каком виде CryptoJS принимает в себя инстанс объекта самого себя и что он хеширует, чтобы повторить этот метод используя другие инструменты


Все криптографические алгоритмы работают с байтами. CryptoJS используется абстракцию в виде класса "WordArray" для представления байтов, т.к. это старая библиотека, написанная, когда не было "ArrayBuffer".

мне надо чтобы оно НЕ РАБОТАЛО также как и НЕ РАБОТАЕТ в js,

Оно работает. Причем правильно.

неужели по Вашему я могу переместиться во времени и пространстве к программисту, который когда-то захешировал слово таким методом и сказать ему "эй, ты хешируешь объект, не надо, хешируй строку" и дать ему этот код?

На что тот программист бы ответил: "Не неcи чушь".
И будет прав.

Т.к. в его случает программа берет байты из строки и хешерует их, потом опять хеширует их же и т.д:
SHA512(
        SHA512(
                SHA512("hello".getBytes()) 
        )
).toString("hex");

Для вывода в консоль предстaвляет их в виде хекс строки.

---

Хеши же от вывода якобы той программы на C++:
SHA512(
        SHA512(
                SHA512("hello".getBytes()).toString("hex").getBytes()
        ).toString("hex").getBytes()
).toString("hex");

Ничего не смущает? Что здесь cчитается не то же самое.

---

чтобы повторить этот метод используя другие инструменты


Другие инструменты в виде Java:

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.*;

public class Main {
    public static void main(String[] args) throws NoSuchAlgorithmException {
        byte[] bytesOfMessage = "hello".getBytes(StandardCharsets.UTF_8);
        MessageDigest SHA512 = MessageDigest.getInstance("SHA512");

        byte[] digest = SHA512.digest(bytesOfMessage);
        Main.log(digest);
        for (int i = 0; i < 4; i++) {
            digest = SHA512.digest(digest);
            Main.log(digest);
        }
    }
    private static void log(byte[] digest) {
        var hex = new BigInteger(1, digest).toString(16);
        if (hex.length() % 2 == 1) {
            hex = "0" + hex;
        }
        System.out.println(hex);
    }
}


Шок! Вывод такой же и у "неправильного" CryptoJS. Банковские приложения в опасносте!

---

Тема — кринж.
Ответ написан
Пригласить эксперта
Ответы на вопрос 5
DollyPapper
@DollyPapper
И если CryptoJS.SHA512("hello") возвращает корректный хэш строки "hello", то уже i = CryptoJS.SHA512(i) хэширует не строку hello, а инстанс объекта CryptoJS.

Ну и сформулирую вопрос более широко: как мне добиться того, чтобы результат кода исполняемого на C++ был идентичен результату кода исполненного на JS?

- Никак. Если каждая новая итерация хеширует не строку, а обьект, то и результат в жс и крестах будет разный, потому что хешируют они разные вещи. Если хотите добиться одинакового результата, хешируйте не обьект а строку.
Ответ написан
shurshur
@shurshur
Сисадмин, просто сисадмин...
Не трогая уже заранее кривую реализацию на js, сделать это невозможно. Увы. Хеш может вообще зависеть от движка js и его версии, от аппаратно-програмной платформы, так как структура объекта не факт что одинакова в разных реализациях, что может давать неодиаковые конечные результаты.

Теоретически, если поборость последнее, то есть неодинаковый результат в разных условиях (путём запуска кода в предсказуемо одинаковых), то можно, например, оформить хеширующий микросервис, который будет получать данные и хешировать их по кривому алгоритму. Но лучше бы, конечно, этой фигнёй не страдать, а исправить изначальную проблему. Это как заболевания генетического происхождения: лечить их практически невозможно, потому что у человека уже миллиарды неверных копий ДНК в организме, которые поздно исправлять.
Ответ написан
samodum
@samodum
Какой вопрос - такой и ответ
Хэшировать на каждой итерации надо не объект, а хэш, полученный на предыдущей итерации, строку.
Тогда не будет разницы в языках
Ответ написан
profesor08
@profesor08 Куратор тега JavaScript
У тебя в С++ CryptoC.SHA512(str) возвращает hex строку. В js CryptoJS.SHA512(str) принимает строку, но возвращает объект. А потом ты снова в нее пихаешь уже объект. И удивляешься, а почему же оно не работает.

const hash = async (str) => {
  const msgUint8 = new TextEncoder().encode(str);
  const hashBuffer = await crypto.subtle.digest("SHA-512", msgUint8);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
  return hashHex;
}
Ответ написан
Noizefan
@Noizefan
Что значит "как бы я не бился"?)
берём библу, читаем как формируется
words: [
      93495557,  2231348217,
    1698296791,  2161604226,
    2355616282,  3048303081,
    3903772728,  2867644909,
     919904241,  1111250416,
    4729098438,  1818436853,
     898154120,  2303717197,
    3489511243, -1729973760
  ],
  sigBytes: 64

остальное изменяемым не кажется.
Делаем то же самое на крестах и все работает.
Вместо траты времени на разъяснение тут людям своего вопроса, эффективнее было бы потратить время на изучение библы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы