Можно ли перехватить Matlab save () bytestream - PullRequest
6 голосов
/ 26 января 2011

В Matlab можно записывать объекты Matlab или даже все рабочее пространство в файл с помощью вызова Matlab save ().Я хотел бы перехватить поток и обработать его до того, как он перейдет в файл, возможно ли это?В качестве альтернативы, можно ли указать файловый дескриптор, в который записывается байтовый поток, вместо имени файла, которое обычно входит в вызов save () в качестве аргумента.

Обратите внимание, что я не ищу альтернативный способнаписать файл в Matlab, я знаю, я могу fopen () файл и писать все, что я хочу, но дело в том, что я хочу (повторно) использовать сериализацию объекта, которая является внутренней для вызова сохранения, а не изобретать свою собственную снова.

Аналогичный вопрос, конечно, возникнет для вызова load (), но в этом случае он перехватывает поток данных до того, как он перейдет в процесс десериализации, но я думаю, возможно ли для save () найти решение дляпроблема load () будет следовать естественным образом.

Несколько уточнений:

  1. Я не смотрю на новый способ сериализации данных Matlab, они уже существуют и в целомсмысл упражнения - использовать существующую сериализацию в вызове save (), чтобы 1) мне не нужно было начинать обновление кода сериализации дляновые типы объектов в более новых версиях matlab, или небеса запрещают людям начинать использовать пользовательские объекты ООП, и 2) я все еще могу легко использовать существующий код для чтения в файлах матов, например, поддержку scipy для файлов матов.

  2. Перед постобработкой поток не должен передаваться в файл или что-либо еще. Идея заключается в шифровании для безопасности, запись потока в файл в файл полностью подрывает эту цель.

Осложнения:

  • Кажется, что функциональность, используемая в функции save в matlab, - это не просто обычная последовательная запись.Изучая объектный код библиотек, кажется, что функция сохранения реализована с использованием matPutVariable (ранее называвшегося matPutArray), который записывает данную переменную типа mxArray* в файл типа MATFile*, открытый с помощью matOpen,Проблема здесь заключается в следующем тексте в описании matPutVariable:

    Если mxArray не существует в файле MAT, функция добавляет его в конец.Если в файле существует mxArray с тем же именем, функция заменяет существующий mxArray новым mxArray, переписав файл.

    Это означает, что функция matPutVariableпридется искать через файл, очевидно, что поиск будет невозможен при использовании каналов, поэтому использование каналов для реализации нашей обработки потокового потока невозможно при использовании этой существующей функциональности сериализации.

Ответы [ 10 ]

5 голосов
/ 07 июня 2011

Как насчет использования виртуальной файловой системы? В Windows есть коммерческая библиотека BoxedAPP SDK, которая позволяет создавать виртуальные файлы, которые видны только процессу создания (возможно, также дочерним). Возможно, вам придется создать MEX для взаимодействия с библиотекой. Сначала вы должны создать виртуальный файл, а затем вы можете использовать команду сохранения в Matlab с тем же именем файла. Затем вы можете читать сериализованный поток .mat, используя обычные функции fopen / fread в matlab, и делать с ним все, что пожелаете. Это по крайней мере предотвратит создание файла на жестком диске. Однако я не уверен, что файл или его части могут попасть в файл подкачки в некоторой ситуации, поскольку файл фактически создается в памяти.

В libmx есть также недокументированные функции mxSerialize и mxDeserialize, которые вы можете использовать, например. функциями loadlibrary / calllib непосредственно из matlab или программой-оболочкой mex. Немного Googling показал, что подпись для этих функций должна быть

mxArray* mxSerialize(const mxArray*);
mxArray* mxDeserialize(const void*, size_t);

и некоторые тесты показали, что mxSerialize () получает переменную matlab в качестве аргумента и возвращает сериализованные байты в виде массива uint8. MxDeserialize () преобразует этот массив uint8 (1-й аргумент) обратно в объект Matlab в качестве возвращаемого значения. Второй аргумент для mxDeserialize - это количество элементов в первом аргументе. Использование этих недокументированных функций, тем не менее, не гарантирует работоспособность в будущем, поскольку TMW может изменить API.

2 голосов
/ 27 октября 2015

Используйте getByteStreamFromArray и getArrayFromByteStream для сериализации / десериализации.Вы можете изменить полученные байты, прежде чем записать их в файл

% A cell array of several data types
>> byteStream = getByteStreamFromArray({pi, 'abc', struct('a',5)});  % 1x312 uint8 array
>> getArrayFromByteStream(byteStream)
ans = 
    [3.14159265358979]    'abc'    [1x1 struct]

Как описано в http://undocumentedmatlab.com/blog/serializing-deserializing-matlab-data

2 голосов
/ 31 января 2011

Не могли бы вы вместо этого зашифровать содержимое переменных?

С whos вы получите список всех ваших переменных в алфавитном порядке. Для каждого из них вы генерируете маску одинакового размера с вашим алгоритмом шифрования, и вы заменяете «истинное» значение самим собой, или вместо маски. Чтобы закончить, вы сохраняете зашифрованные переменные, используя save. Имя и размер ваших переменных видны, но это, вероятно, не критично (при необходимости вы можете также зашифровать имена).

Выполните загрузку таким же образом.

2 голосов
/ 27 января 2011

Лучше всего, вероятно, записать файл mat на диск tmpfs / ramdisk, а затем зашифровать его перед сохранением на диск.Вы жертвуете переносимостью и полагаетесь на то, что ОС обеспечивает безопасную виртуальную память, но если вы даже не можете доверять локальному диску, вы, вероятно, не сможете добиться удовлетворительной безопасности.

Кстати,почему вы вообще не можете доверять локальному диску, даже если вы не можете поместить ваш временный файл в каталог с разрешениями, которые разрешают доступ только для пользователя, владеющего процессом matlab (и root)?Вы пытаетесь внедрить систему DRM?

2 голосов
/ 26 января 2011

Для объектов HG вы можете перехватить обработку сохранения через внутренние (изменяемые) файлы * .m, которые описаны здесь: http://undocumentedmatlab.com/blog/handle2struct-struct2handle-and-matlab-8/

2 голосов
/ 26 января 2011

РЕДАКТИРОВАТЬ: (на основе комментариев) Хм, я думаю, мой старый ответ не очень помогает тогда. Я не знаю, как бы вы перехватили этот поток, но я полагаю, что у вас есть один вариант (который, по общему признанию, немного клудж) - просто let SAVE Функция создает файл, затем сразу считывает данные из файла побайтно, обрабатывает их и записывает обратно в файл. Что-то вроде:

save('workspace.mat');
fid = fopen('workspace.mat','r');
byteData = fread(fid,inf,'*uint8');
fclose(fid);
%# ... Process byteData here ...
fid = fopen('workspace.mat','w');
fwrite(fid,byteData,'uint8');
fclose(fid);

Старый ответ:

Я полагаю, что для пользовательских объектов класса то, что вы ищете, воплощено в перегруженных методах SAVEOBJ и LOADOBJ , которые вызываются для объекта перед сохранением или загрузить его из файла. При сохранении или загрузке объектов в или из файлов .MAT вы можете использовать эти методы, чтобы изменить процесс сохранения / загрузки , чтобы объекты могли быть отформатированы различными способами. Однако я не думаю, что вы можете сделать это для встроенных типов данных, только для пользовательских объектов.

1 голос
/ 01 февраля 2011

Меня тоже интересует эта проблема. Я нашел некоторые вещи, но ничего не работает:

  • matlab save stdio вы найдете эту скрытую функцию, но она не работает
  • engGetArray / engPutArray "Эта подпрограмма позволяет копировать переменную из рабочей области."

Посмотрите спецификацию файлов MAT, возможно, мы сможем воспроизвести сериализацию Matlab с помощью файла Mex:

Обновление:

Я нашел кое-что очень интересное: запустите в консоли Matlab эту команду

edit([matlabroot '/extern/examples/eng_mat/matcreat.c']);

или это

edit([matlabroot '/extern/examples/eng_mat/matcreat.cpp']);

Это документация, как ее скомпилировать: http://www.mathworks.com/help/techdoc/matlab_external/f14500.html

По моему мнению, целесообразно использовать STDOUT в команде pmat = matOpen(file, "w");.

1 голос
/ 27 января 2011

Может быть, вы могли бы сделать что-то вроде следующего:

%# serialize objects into a byte array using Java
bout = java.io.ByteArrayOutputStream();
out = java.io.ObjectOutputStream(bout);
out.writeObject( rand(3) )                %# MATLAB matrix
out.writeObject( num2cell(rand(3)) )      %# MATLAB cell array
out.flush()
out.close()
bout.close()
b = bout.toByteArray();                   %# vector of type int8

%# perform processing on `b` ...

%# write byte[] stream to file
save file.mat b

Затем в обратном направлении вы просто загружаете сохраненный MAT-файл, полностью изменяете любую выполненную вами обработку и десериализуете поток байтов для восстановления исходных объектов.

%# load MAT-file
load file.mat b
b = typecast(b,'int8');                   %# cast as int8 just to be sure

%# undo any processing on `b`...

%# deserialize
in = java.io.ObjectInputStream( java.io.ByteArrayInputStream(b) );
X1 = double( in.readObject() )            %# recover matrix
X2 = cell( in.readObject() )              %# recover cell array
in.close()

Обратите внимание, что вам придется самостоятельно хранить метаинформацию переменных, например, их количество и тип (возможно, вы можете как-то сохранить ее в одном и том же файле MAT), и использовать пользовательские функции-обертки для обеспечения маршалинга , но вы поняли ...


Я также натолкнулся на пару предложений на FEX, которые помогают в сериализации / десериализации типов MATLAB:

0 голосов
/ 26 апреля 2011

После нескольких месяцев размышлений над этим я скажу: нет, это невозможно. По крайней мере, не без хардкорного непереносимого взлома двоичных файлов / ELF.

0 голосов
/ 06 февраля 2011

Шаг 1: mkfifo /tmp/fifo - это создает FIFO, имя файла, которое представляет канал.Все, что записано в канал, остается там до тех пор, пока процесс не прочитает его обратно из канала.Данные никогда не попадают на диск.

Шаг 2: В одном терминале запустите: openssl enc -aes-256-cbc -a -e -in fifo -out safe - запускается программа OpenSSL для шифрования с использованием AES, 256-битный ключ, режим CBC (openssl поддерживает гораздо большетипы и параметры шифров, выберите тот, который вам подходит, это безопасное значение по умолчанию);-a Base64 кодирует вывод (что хорошо для тестирования, но вы, вероятно, можете его отключить, когда вы действительно его используете, Base64 вызывает увеличение размера на 4/3);-e работает в режиме шифрования, -in fifo указывает, что входной файл имеет имя fifo (возможно, используйте полный путь);-out safe указывает, что выходной файл имеет имя safe (опять же, возможно, используйте полный путь).OpenSSL будет находиться в спящем режиме до тех пор, пока данные не поступят в канал.

OpenSSL предложит вам ввести ключевую фразу, когда некоторые данные поступят в канал.

Проверьте это: запустите "echo foo> / tmp / fifo"в другом терминале.Посмотрите запрос пароля в первом терминале, введите пароль и подтвердите пароль, затем посмотрите на содержимое файла «safe»:

$ openssl enc -aes-256-cbc -a -e -in fifo -out safe
# (in another terminal, "echo foo > fifo")
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password:
$ cat safe
U2FsdGVkX18aWBw0Uz8N3SfrRg4PigL609F+HQPuc6o=

Проверьте другое направление:

$ openssl enc -aes-256-cbc -a -d -in safe
enter aes-256-cbc decryption password:
foo

Теперь повторно запустите команду OpenSSL, начиная с шага 2: openssl enc -aes-256-cbc -a -e -in fifo -out safe, запустите ваш Matlab и передайте /tmp/fifo команде SAVE().

Там равно aвероятность того, что Matlab сделает что-то глупое, например, удалит любой существующий файл с заданным именем файла, и в этом случае вы найдете незашифрованные данные в обычном файле с именем /tmp/fifo.Поэтому, пожалуйста, сначала проверьте некоторые неважные данные.Но я надеюсь, что Matlab написан с учетом инструментов Unix и просто запишет в именованный канал, который вы ему дадите.

...