Кратчайший код для безопасного стирания диска

9

Давайте напишем кратчайший код для выполнения упрощенного варианта метода вытеснения DoD 5220.22-M всего за два прохода записи.

Разрешен любой язык программирования, но использование ориентированных на очистку диска библиотек запрещено.

Вот как мы должны реализовать это в псевдокоде:

Set x to 0

[Start]
'Write Pass
For each sector in disk write the content of x
'Verification Pass
For each sector in disk {
    If sector does not contain the content of x then goto [Start]
}
'Check whether we already did the pass with 1
If x is not 1 then {
    Set x to 1
    GoTo [Start]
}
Else end

Другими словами, этот код будет выполняться дважды, с проходом записи и проверкой для 0, а также проходом записи и проверкой для 1.

Кто-нибудь достаточно смелый, чтобы реализовать его в стиле «код-гольф»? ;)

MathuSum Mut
источник
6
Я сомневаюсь, что это даст какие-либо ответы из-за того, как трудно будет проверить.
Джеймс
12
Серьезно, что сделал тебе SSD, чтобы заслужить такое лечение? Это убило всю вашу коллекцию плюшевых мишек или что-то?
Р. Кап
2
Очень хочу попробовать и заняться этим ... также не хочу жертвовать своим жестким диском, чтобы протестировать его.
Мишельфрансис Бустильос
6
Я голосую, чтобы закрыть этот вопрос как не по теме, потому что этот запрос требует вредоносного кода.
AdmBorkBork
2
Я бы сказал иначе. Эта задача требует кода, который способствует конфиденциальности и информационной безопасности.
MathuSum Mut

Ответы:

1

машинный код x86 (Linux), 116 байт

00000000: 89cb 6a02 5931 d289 4c24 f4b0 05cd 8050  ..j.Y1..L$.....P
00000010: 5b53 6a02 5a31 c9b0 13cd 8089 c65b 5331  [Sj.Z1.......[S1
00000020: d231 c9b0 13cd 8089 f75b 53b2 018d 4c24  .1.......[S...L$
00000030: f8b0 04cd 804e 09f6 75ef 5b53 31d2 31c9  .....N..u.[S1.1.
00000040: b013 cd80 89fe 5b53 8d4c 24f4 b201 b003  ......[S.L$.....
00000050: cd80 4e09 f674 0c8a 4424 f838 4424 f474  ..N..t..D$.8D$.t
00000060: e5eb ad89 fe8a 4424 f8c6 4424 f801 3c01  ......D$..D$..<.
00000070: 759e 58c3                                u.X.

Принимает имя файла в качестве аргумента

Сборка (NASM):

section .text
	global func
func:			;this function uses fastcall conventions
	;seems like no enter instr needed

	;open file
	mov ebx, ecx	;first argument to func (filename)
	push 0x2	;flag O_RDWR
	pop ecx		;pushing a constant is shorter than mov
	xor edx, edx	;mode=0
	mov [esp-12], ecx ;set first byte (msg) to write to 0. msg later in esp-8, buf in esp-12
	mov al, 5	;using 8 bit regs is smaller
	int 0x80	;syscall open
	push eax	;save file descriptor

	write_verify:

	;get file size
	pop ebx		;get fd
	push ebx
	push 0x2	;flag SEEK_END
	pop edx
	xor ecx, ecx 	;offset 0
	mov al, 0x13
	int 0x80	;syscall lseek
	mov esi, eax	;save file byte count in esi
	

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	xor edx, edx	;flag SEEK_SET=0
	xor ecx, ecx	;ecx=0
	mov al, 0x13
	int 0x80	;syscall lseek

	;***write pass***
	mov edi, esi
	write_loop:	;for each byte in byte count, write [msg]
		;write to file
		pop ebx		;file descriptor
		push ebx
		mov dl, 1	;bytes to write
		lea ecx, [esp-8] ;buffer to write from
		mov al, 4
		int 0x80	;syscall write
		dec esi	;decrement esi (byte count) to 0
		or esi, esi	;cmp esi to 0
		jne write_loop	;while esi!=0, keep looping

	;reset index of file to 0
	pop ebx		;get fd
	push ebx
	xor edx, edx	;flag SEEK_SET=0
	xor ecx, ecx	;ecx=0
	mov al, 0x13
	int 0x80	;syscall lseek

	
	;***verification pass***
	mov esi, edi
	verify_loop:	;for each byte in byte count, verify written byte
		pop ebx		;get fd
		push ebx
		lea ecx, [esp-12] ;buffer to store read byte
		mov dl, 1	;read 1 byte
		mov al, 3
		int 0x80	;syscall read
		dec esi
		or esi, esi	;cmp esi to 0 
		je end_verify	;at final byte, end verification
		mov al, [esp-8]
		cmp byte [esp-12],al
		je verify_loop	 ;keep looping if expected value found
		jmp write_verify ;if byte!=expected value, restart

	end_verify:
	mov esi, edi
	mov al, [esp-8]
	mov byte [esp-8],0x1	;set new byte to write to 1
	cmp al, 0x1
	jne write_verify	;if old byte to write!=1, goto start
	
	pop eax			;reset stack
	ret

Попробуйте онлайн! (Использует временный файл)

-11 байт за счет оптимизации движущихся регистров и использования стека в качестве буфера вместо постоянного расположения в памяти.

Logern
источник
3

В системе Linux нет необходимости в специальной обработке устройств. Просто используйте интерфейс файла устройства.

Python 3 (байтовые строки) - 141 байт

d=input()
f=open(d,'r+b')
z=f.seek
z(0,2)
s=f.tell()
i=0
while i<2:
 z(0);f.write([b'\0',b'\xff'][i]*s);f.flush();z(0)
 if f.read()==x:i+=1

Это довольно просто и не сильно оптимизировано, но работает. Вот краткое изложение.

  • Получить ввод (путь к файлу устройства)
  • Открыть файл устройства
  • Искать до конца, получить размер файла (блочные устройства всегда имеют свой реальный размер)
  • войти в цикл записи и проверки
  • построить 0-битные и 1-битные строки (x)
  • написать цепочку
  • сбросить вывод (я мог бы установить буфер = 0, но это короче)
  • проверить файл на x и увеличить шаг цикла, если он прошел

выходной цикл, когда приращение достаточно велико

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

Я действительно проверял это на файле устройства, используя loopback. Однако я не уверен на 100%, что проверка действительно работает. Может потребоваться закрыть и снова открыть файл при каждом проходе из-за поведения буферизации. Я надеюсь, что флеш предотвращает это.

* отредактировано для включения некоторых предложений в комментарии

Уильям Шипли
источник
1
Добро пожаловать на сайт. Вам, конечно, не нужно пробелов вокруг =в Python. Вы также можете уменьшить количество байтов, используя ;для уменьшения отступов.
Специальный охотник на Гарф
Обычно мы учитываем отправку в байтах, а не в символах. Вы также можете использовать псевдоним некоторых своих функций, например f.seek(0);f.seek(0)(19 байт) может быть s=f.seek;s(0);s(0)(18 байт). Кроме того, if f.read()==x:i+=1может быть i+=f.read()==x.
Джонатан Фрех
Вам также не нужно вводить пустую строку в качестве аргумента.
Quintec
Я думаю, b'\0'вместо того, b'\x00'чтобы работать.
Джейсон
Просто понял важную особенность. Эта программа будет потреблять оперативную память, равную размеру стираемого устройства.
Уильям Шипли
2

C (лязг) , -DZ=lseek(d,0+ 139 = 152 байта

g,j,x,d,s,i,c;f(n){x=0;d=open(n,2);s=Z,2);for(j=2;j--;x++){Z,0);for(i=s;i--;write(d,&x,1));Z,0);for(i=s;i--;read(d,&c,1),c!=x&&x--&&j--);}}

Попробуйте онлайн!

Принимает имя файла в качестве аргумента

Ungolfed:

#include <unistd.h>
int g,j,x,d,s,i,c;
void f(char*n){
	x=0; /*Byte to write*/
	d=open(n,O_RDWR);
	s=lseek(d,0,SEEK_END); /*Get size of file*/
	j=0;
	for(j=0;j<2;j++){
		/*Write Pass*/
		lseek(d,0,SEEK_SET); /*Start writing from start of file*/
		for(i=0;i<s;i++){
			write(d,&x,1);
		}
		
		/*Verification Pass*/
		lseek(d,0,SEEK_SET);
		for(i=0;i<s;i++){
			read(d,&c,1);
			if(c!=x)x--,j--; /*If verification fails, repeat loop with the same value*/
		}
		x++;
	}
}
Logern
источник
Хм ... TiO сотрет интернет? ;-D
Тит
@Titus Создает временный файл и стирает его.
Логерн
1

Tcl, 286 байт

proc f {o i l} {seek $o 0
set s [string repeat $i $l]
puts -nonewline $o $s
flush $o
seek $o 0
return [string equal [read $o $l] $s]}
set n [open $argv r+]
fconfigure $n -translation binary
seek $n 0 end
set m [tell $n]
while {![f $n "\0" $m]} {}
while {![f $n "\xff" $m]} {}

Не очень хорошо оптимизирован. Я пытался, что мог, но я не так много знаю о Tcl.

Сохранить как "f.tcl" и запустить на Unix с tclsh f.tcl "your filename". Убедитесь, что есть только один аргумент! Я проверил это на простом файле, но он должен работать и на файле устройства.

Настройка переменных и индексация более важны в Tcl, поэтому я решил поместить общий код между проходами в функцию. Затем я вызываю его сначала с "\ 0" и повторяю, пока он не может проверить. Я делаю то же самое с "\ xff".

Я покраснел после записи; это может быть не нужно. fconfigure -translation binary -buffering noneдлиннее

-2 байта, удаляя кавычки вокруг r+.

Джейсон
источник