Ошибки кодирования и байтов в Ruby с использованием OpenSSL?
Я получаю эту ошибку:
incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string)
при попытке передать переменную из Rails в JavaScript через эту строку:
window.nonce = '<%= j @nonce %>';
мой @nonce
Переменная - это открытый ключ шифрования OpenSSL RSA, созданный:
@nonce = Rails.rsaEncUsingPublic(pubKey, randomStr)
def self.rsaEncUsingPublic(key, msg)
return key.public_encrypt msg
end
Затем я попытался добавить force_encoding("UTF-8")
до конца rsaEncUsingPublic
функция, которая изменила ошибку на:
invalid byte sequence in UTF-8
Теперь я явно не хочу удалять символы из зашифрованной переменной, однако та же самая функция шифрования работает везде, пока я не передам ее в JavaScript.
Распечатка @nonce
(с принудительным кодированием или без) дает много толку:
#??7:A}p[?ͼg/?%ŋ??=????h9?jg? W?V?j ?}??G???t?7?i?:"???"#HM?0?L?????*r:ɦYaB&v&?5mǓŌ,???[U?Dt??G???Tև?&~??6f???????P??<GKV?`? p?K??B???????[?yj6?=?;?
???p?j=?Z?? ?[?5i??i?t?!???^?L{;??,??Ma\_mg?|??]A?????"??X:??;??? ?y??\纘???# ]?M" ?
?N
@nonce.encoding
распечатывает UTF-8
,
@nonce.inspect
выводит:
"\u0015\xC0jn\xE7\xBC\xE4\u0016gV\x84&-ˌ+ŚA:4\xB1(\xC0\xEAv\x91\xE8>\u001D\x92ږ\xF6\xDC\xEE\x9A)\xC7&O\u001A\x90fเ\e\x9Bb*\xF2\xE2\u001E\xB9V\x9E\xBB\x9AUЕcU\u001E~\u0011\u0001$մ\xF8J\xED\xFE^\"\u001EC\xBD8\u0002\xBA\xDC\xDFIЊ, KU\u0000\u0014\u0015\x92_w\x95\x89\xD0-OfG\xB5\xF8LC\x9BO\\0j<ƥ\xA5\u001Dw(t?\xA4\xA2\u00174\xB5Š\xE3\x91s\xDA\u0002i\xB3\u0003Q\u000F\xF4\xDB5\x80\xD8\xE0./\x8B\x8A߳0\u0001\x91=$T\xCB\bLh\xF3\u001C\xFD\xBF\x95I%=gQ\u000F}\x8F_w\xFAn\x90\x81\xFC\b4\x9E\xC1\xD7y\xBC\xE8\xA4cQY\xB2@s1\xD7\xC9+\xA7\xEA>\xA5\xBC\xCF\xC81:TG\xFD\x88\xCCS\x90\xB1\x9Cv\xA3ݘ,\xA1;\xA5\xEE\xE4q9\u0000w\xB9\xB3\u0014\xD9\u0015\x8B\x82nw\ej\x82xkm)\x9Aa\xF1\xDD۬\xA2"
Вся помощь будет оценена!
1 ответ
Итак, причина, по которой это происходит, находится внутри j
метод, именно в этой строке:
result = javascript.gsub(/(\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] }
Обратите внимание на прекрасный u
в конце регулярного выражения Это заставило Ruby потерпеть неудачу в совпадении, если данная строка не совместима с UTF-8.
Теперь, когда вы кодируете строку, результат не должен представлять собой какую-либо форму читаемой человеком строки - он является чисто двоичным, и никакое кодирование не отобразит ничего полезного. По умолчанию Ruby пытается отобразить его с помощью "UTF-8", но эта строка не совместима с "UTF-8", поскольку она может содержать последовательности, отличные от UTF-8 (поскольку она может содержать буквально все, что угодно).
Теперь решение будет непростым, поскольку эта строка вообще не является допустимой строкой JavaScript. Кроме того, даже если вам удалось преобразовать его так, чтобы JavaScript, JavaScript мог сохранять строковое представление по-другому, и важно сохранить двоичную информацию неизменной. Возможно, самый простой способ - преобразовать зашифрованную строку в число:
window.nonce = '<%= @nonce.unpack('B*').first.to_i(2) %>';
Это приведет к числу, которое имеет двоичное представление, точно такое же, как и для зашифрованной строки. Вам нужно только быть уверенным, что с ним обращаются правильно везде.
Вопрос: как эту строку использовать в JavaScript?