Code le plus court pour sécuriser effacer un disque

9

Écrivons le code le plus court pour effectuer une variante simplifiée de la méthode de nettoyage DoD 5220.22-M avec seulement deux passes d'écriture.

Tout langage de programmation est accepté, mais l'utilisation de bibliothèques orientées sur l'effacement des disques est interdite.

Voici comment nous allons l'implémenter en pseudocode:

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

En d'autres termes, ce code s'exécutera deux fois, avec une passe d'écriture et une passe de vérification pour 0, et une passe d'écriture et une passe de vérification pour 1.

Quelqu'un est-il assez balleux pour l'implémenter comme un golf de code? ;)

MathuSum Mut
la source
6
Je doute que cela obtienne des réponses en raison de la difficulté des tests.
James
12
Sérieusement, que vous a fait votre SSD pour mériter ce type de traitement? Est-ce que cela a tué toute votre collection d'ours en peluche ou quelque chose?
R. Kap
2
Je veux vraiment essayer de résoudre ce problème ... et je ne veux pas vraiment sacrifier mon disque dur pour le tester.
Michelfrancis Bustillos
6
Je vote pour fermer cette question comme hors sujet car ce défi demande du code malveillant.
AdmBorkBork
2
Je dirais le contraire. Ce défi demande un code qui favorise la confidentialité et la sécurité des informations.
MathuSum Mut

Réponses:

1

code machine x86 (Linux), 116 octets

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.

Prend le nom de fichier comme argument

Assemblage (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

Essayez-le en ligne! (Utilise un fichier temporaire)

-11 octets en optimisant les registres en mouvement et en utilisant la pile comme tampon au lieu d'un emplacement constant en mémoire.

Logern
la source
3

Sur un système Linux, aucune manipulation particulière des périphériques n'est nécessaire. Utilisez simplement l'interface de fichier de l'appareil.

Python 3 (chaînes d'octets) - 141 octets

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

C'est assez simple, et pas vraiment optimisé lourdement, mais ça marche. Voici un aperçu de base.

  • Obtenir l'entrée (chemin du fichier de périphérique)
  • Ouvrir le fichier du périphérique
  • Cherchez jusqu'au bout, obtenez la taille du fichier (les périphériques de bloc sont toujours à leur taille réelle)
  • entrer dans la boucle d'écriture et de vérification
  • construire des chaînes de 0 et 1 bit (x)
  • écrire la chaîne de bits
  • sortie de vidage (j'aurais pu définir la mise en mémoire tampon = 0 mais c'est plus court)
  • teste le fichier par rapport à x et incrémente l'étape de la boucle s'il réussit

boucle de sortie lorsque l'incrément est suffisamment élevé

En prime, vous pouvez le modifier pour n'importe quel ensemble et nombre de modèles de modification d'octets, comme 0x55 / 0xaa pour des effets d'écrasement plus forts.

J'ai effectivement testé cela sur un fichier de périphérique, en utilisant le bouclage. Cependant, je ne suis pas sûr à 100% que la vérification fonctionne réellement. Il peut être nécessaire de fermer et de rouvrir le fichier à chaque passage, en raison de comportements de mise en mémoire tampon. J'espère que la chasse d'eau empêchera cela.

* modifié pour incorporer quelques suggestions dans les commentaires

William Shipley
la source
1
Bienvenue sur le site. Vous n'avez certainement pas besoin d'espaces autour d'un =python. Vous pouvez également réduire votre nombre d'octets en utilisant ;pour réduire l'indentation.
Ad Hoc Garf Hunter,
Normalement, nous comptons les soumissions en octets, pas en caractères. Vous pouvez également alias certaines de vos fonctions, par exemple f.seek(0);f.seek(0)(19 octets) peut être s=f.seek;s(0);s(0)(18 octets). En outre, if f.read()==x:i+=1peut être i+=f.read()==x.
Jonathan Frech
Vous ne devriez pas non plus avoir besoin de la chaîne vide comme argument pour entrer.
Quintec
Je pense b'\0'qu'au lieu de b'\x00'devrait fonctionner.
Jason
Je viens de réaliser une caractéristique importante. Ce programme consommera de la RAM égale à la taille de l'appareil effacé.
William Shipley
2

C (clang) , -DZ=lseek(d,0+ 139 = 152 octets

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--);}}

Essayez-le en ligne!

Prend le nom de fichier comme argument

Non golfé:

#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
la source
Hmm ... le TiO effacera-t-il Internet? ;-D
Titus
@Titus Il crée un fichier temporaire et l'efface.
Logern
1

Tcl, 286 octets

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]} {}

Pas vraiment optimisé aussi bien. J'ai essayé ce que j'ai pu, mais je ne sais pas grand-chose sur Tcl.

Enregistrez sous "f.tcl" et exécutez sous Unix avec tclsh f.tcl "your filename". Assurez-vous qu'il y a exactement un argument! J'ai testé cela sur un fichier ordinaire, mais cela devrait également fonctionner sur un fichier de périphérique.

La définition de variables et l'indexation sont plus impliquées dans Tcl, j'ai donc décidé de mettre le code commun entre les passes dans une fonction. Ensuite, je l'appelle d'abord avec "\ 0", et répète pendant qu'il ne parvient pas à vérifier. Je fais la même chose avec "\ xff".

J'ai rougi après les écritures; cela pourrait ne pas être nécessaire. fconfigure -translation binary -buffering noneest plus long.

-2 octets en supprimant les guillemets r+.

Jason
la source