-1

I have 2 old 160GB WD drives that do not have "Security-Delete" option when querying with hdparm.

I understand the current acceptance of the mechanism overwriting entire disks with zeros.

REF: Does filling up disk with dd removes files securely?

But that leaves me wanting.

Wouldn't having a mechanism, such as /dev/one, to create a stream of ones be better?

Wouldn't max magnetization on the track be better than trying to remove that magnetization? Or is that like trying to reach the 6-sigma level, when 3/4-sigma is all current technology can measure?

To that end, how do I formulate my command to generate an "all-bits-on" stream to fill a 512-byte wide block?

  • 2
    The 0 and 1 is done with polarity, not by degaussing. Plus, it's more Hollywood than science that you can recover data from a zeroed disk. – Halfgaar Jan 25 '21 at 19:39
  • 1
    Probably better asked on securty.stackexchange.com than here. I'd encrypt the entire volume, and then delete the key. – Synchro Jan 25 '21 at 19:39
  • BTW, if you really want to write such patterns, you can use `badblocks -w` (linux). You can also specify the pattern yourself with `-t`. – Halfgaar Jan 25 '21 at 19:54
  • Hard drives use some form of RLL encoding of the data (see pages 5 and 6 [here](https://www.tomshardware.com/reviews/hard-drive-magnetic-storage-hdd,3005-5.html)), so neither all-zero or all-one bit patterns correspond to all-anything patterns on disk, and neither is more secure than the other. If you're really worried about it, write all-zeroes, then random data, then all-zeroes again, then read it back to make sure it actually all got written. (Note: that's for HDs. For SSDs, the situation is much messier.) – Gordon Davisson Jan 26 '21 at 01:46
  • To Gordon Davisson, thank you for that reference. I always like to get at the deeper understanding of inner workings. However the process will take far longer than I wanted already and did not want to add additional time to handle a dynamic random value generation. – Eric Marceau Jan 26 '21 at 04:21
  • Thank you, Synchro. I tried to pursue your suggestion, but having never done disk encryption (not partition), what I came across from various sources did not make me feel "master" enough of the process, so I backed away from that and followed the "badblocks" method to achieve my goal. I will revisit that at later date for when I have a faster computer and my next round of disk wiping. – Eric Marceau Jan 26 '21 at 04:26
  • 1
    @Synchro Encrypting the volume (after having used it without encryption) is no better than overwriting with random data, and may be much worse if you fail to completely destroy the key, or if the encryption format you use only encrypts blocks that contain files (leaving "empty" blocks containing residual data unencrypted), or... – Gordon Davisson Jan 26 '21 at 04:40

2 Answers2

0

Thank you to Halfgaar for directing me to badblocks. That was the ideal path to what I wanted to achieve.

For my home desktop context, this task done this way would take about 54+ hours, non-stop.

I include here the script I built to address my needs. Explanations as to the WHYs are included in the script.

#!/bin/sh

BASE=`basename "$0" ".sh" `
TRACKER=./${BASE}.last

SLICE=`expr 4096 \* 16 `

echo "\n\t This utility will overwrite the full disk with all data bits ON\n\t using '0xFFFF' as test pattern for destructive badblocks scan ..."
echo "\n\t This utility will begin at the last sector and work its way towards the first sector\n\t on the disk, doing slices of ${SLICE} sectors at one time ..."
echo "\n\t The design concept is based on fact that some older USB-attached devices\n\t have both slow interface and slow disk I/O, as well as taking into account\n\t the End-User context of a Desktop computer which cannot remain up and running\n\t for 2-3 days non-stop.  The process can be interrupted at any time and\n\t the script will be able to restart at the last known completed segment\n\t to continue from there."

if [ "$1" != "--force" ]
then
        echo "\n\n\t As a security precaution, you MUST review the script to ensure proper\n\t understanding of DANGERS AND RISKS before proceeding.\n Bye!\n" ; exit 1
fi

echo "\n\t Enter disk (block) device path (i.e. /dev/sdb) => \c" ; read DISK

if [ -z "${DISK}" ] ; then  echo "\n\t No path entered for a block device. Cannot proceed.\n Bye!\n" ; exit 1 ; fi
if [ ! -b "${DISK}" ] ; then  echo "\n\t '${DISK}' is not an existing block device file. Cannot proceed.\n Bye!\n" ; exit 1 ; fi

testor=`df | grep ${DISK} | head -1 `
if [ -n "${testor}" ] ; then  echo "\n\t Mounted partitions for that device:" ; echo "${testor}" | awk '{ printf("\t\t %s\n", $0 ) ; }' ; echo " Bye!\n" ; exit 1 ; fi


### Disk /dev/sdd: 149.5 GiB, 160041885696 bytes, 312581808 sectors
SECTORS_LGCL=`fdisk -l ${DISK} | grep '^Disk '${DISK} | awk '{ print $7 }' `
echo "${SECTORS_LGCL}" | awk '{ printf("\t SECTORS_LOGICAL  = %12s\n", $0 ) ; }'

### Sector size (logical/physical): 512 bytes / 4096 bytes
SECT_SIZE_LGCL=`fdisk -l ${DISK} | grep '^Sector size' | awk '{ print $4 }' `
SECT_SIZE_PSCL=`fdisk -l ${DISK} | grep '^Sector size' | awk '{ print $7 }' `

CLUMPING=`expr ${SECT_SIZE_PSCL} / ${SECT_SIZE_LGCL} `
SECTORS_PSCL=`expr ${SECTORS_LGCL} / ${CLUMPING} `
echo "${SECTORS_PSCL}" | awk '{ printf("\t SECTORS_PHYSICAL = %12s\n", $0 ) ; }'


LAST_TODO=0

LAST=`expr ${SECTORS_PSCL} - 1 `
ITERATION=`expr ${LAST} - ${SLICE} + 1 `

COUNT=`expr ${SECTORS_PSCL} / ${SLICE} `


if [ -s ${TRACKER} ]
then
    read ITERATION <${TRACKER} 
    ITERATION=`expr ${ITERATION} - ${SLICE} `
    echo "\t Using last known good ITERATION captured before last abandon ..."
    COUNT=`expr ${ITERATION} - 1 ` ; COUNT=`expr ${COUNT} / ${SLICE} `
fi

echo "\t Iteration countdown from $COUNT ..."

while [ ${ITERATION} -ge ${LAST_TODO} ]
do
    echo "${COUNT} ${ITERATION} ${SECTORS_PSCL}" | awk '{ printf("\n\n[%s] Slice 1st sector = %12s / %s ...\n", $1, $2, $3 ) ; }'

    ITERATION_LAST=`expr ${ITERATION} + ${SLICE} - 1 `
    if [ ${ITERATION_LAST} -gt ${SECTORS_PSCL} ]
    then
        ITERATION_LAST=`expr ${SECTORS_PSCL} - 1 `
        ITERATION=`expr ${ITERATION_LAST} - ${SLICE} `
    fi

    echo "${ITERATION_LAST}"  | awk '{ printf("\tITERATION_LAST  = %12s\n", $0 ) ; }'
    echo "${SLICE}"           | awk '{ printf("\tSLICE           = %12s\n", $0 ) ; }'
    echo "${ITERATION}"       | awk '{ printf("\tITERATION       = %12s\n", $0 ) ; }'

    badblocks -v -s -w -b ${SECT_SIZE_PSCL} -p 0 -e 0 -t 0xFFFF /dev/sdd ${ITERATION_LAST} ${ITERATION}
    echo "${ITERATION}" >${TRACKER} 

    if [ ${ITERATION} -eq ${LAST_TODO} ]
    then
        break
    else
        ITERATION=`expr ${ITERATION} - ${SLICE} `
        if [ ${ITERATION} -lt ${LAST_TODO} ]
        then
            ITERATION=${LAST_TODO}
        fi
    fi

    COUNT=`expr ${COUNT} - 1 `
done

exit

The session output (after re-starting) looks like this:

     This utility will overwrite the full disk with all data bits ON
     using '0xFFFF' as test pattern for destructive badblocks scan ...

     This utility will begin at the last sector and work its way towards the first sector
     on the disk, doing slices of 65536 sectors at one time ...

     The design concept is based on fact that some older USB-attached devices
     have both slow interface and slow disk I/O, as well as taking into account
     the End-User context of a Desktop computer which cannot remain up and running
     for 2-3 days non-stop.  The process can be interrupted at any time and
     the script will be able to restart at the last known completed segment
     to continue from there.

     Enter disk (block) device path (i.e. /dev/sdb) => /dev/sdd
     SECTORS_LOGICAL  =    312581808
     SECTORS_PHYSICAL =    312581808

     Using last known good ITERATION captured before last abandon ...
     Iteration countdown from 4712 ...


[4712] Slice 1st sector =    308846247 / 312581808 ...
    ITERATION_LAST  =    308911782
    SLICE           =        65536
    ITERATION       =    308846247
Checking for bad blocks in read-write mode
From block 308846247 to 308911782
Testing with pattern 0xffff: done                                                 
Reading and comparing: done                                                 
Pass completed, 0 bad blocks found. (0/0/0 errors)


[4711] Slice 1st sector =    308780711 / 312581808 ...
    ITERATION_LAST  =    308846246
    SLICE           =        65536
    ITERATION       =    308780711
Checking for bad blocks in read-write mode
From block 308780711 to 308846246
Testing with pattern 0xffff: done                                                 
Reading and comparing: done                                                 
Pass completed, 0 bad blocks found. (0/0/0 errors)

***
0

I came up with a more direct method using the basic dd command, hoping that would speed up the process. Unfortunately, timing both shows they are pretty much equivalent, both ranging in the 54+ hours.

Here is the script for the 'dd' method:

#!/bin/sh

BASE=`basename "$0" ".sh" `
SEEDlocn="/site/DB003_F1"
TMP="${SEEDlocn}/${BASE}.bitsON"

ROOTlocn=`df / | grep '/dev/sd' | awk '{ print $1 }' `
testor=`df ${SEEDlocn} | grep '/dev/sd' | awk '{ print $1 }' `
if [ "${testor}" = "${ROOTlocn}" ] ; then  echo "\n\t Disk for ${SEEDlocn} is not mounted.  Unable to proceed.\n Bye!\n" ; exit 1 ; fi

echo "\n\t Following block devices have been identified:\n"
lsblk -l | awk '{ if( length($1) == 3 ){ print $0 } ; }' | awk '{ printf("\t\t %s\n", $0 ) ; }'

echo "\n\t Enter the block device's full path => \c" ; read DISK
if [ -z "${DISK}" ] ; then  echo "\n\t Empty string.\n Bye!\n" ; exit 1 ; fi

echo "\n\t Enter the LABEL for the block device => \c" ; read LABEL
if [ -z "${LABEL}" ] ; then  echo "\n\t Empty string.  Need proper LABEL for unique tracking and safe/correct restart.\n Bye!\n" ; exit 1 ; fi
TRACKER="./${BASE}.${LABEL}.last"

testor=`df | grep ${DISK} `
if [ -n "${testor}" ] ; then  echo "\n\t Drive is mounted on ${DISK} ...  Cannot proceed.\n Bye!\n" ; exit 1 ; fi

testor=`stat ${TMP}.binaryBLOB | grep '^  Size:' | awk '{ print $2 }' `
if [ -z "${testor}" ] ; then  testor="0" ; fi

if [ ${testor} -eq 1073741824 ]
then
    echo "\n\t Using existing seed file '${TMP}.binaryBLOB' ..."
else
    echo "\n\t Creating input to create 512 byte seed file with all bits ON ..."

    ### Seed file size = 512 * 8 = 4096 bytes
    cat <<-EOF_EOF >${TMP}.seed
00000000: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000010: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000020: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000030: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000040: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000050: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000060: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000070: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000080: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000090: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000000a0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000000b0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000000c0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000000d0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000000e0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000000f0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000100: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000110: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000120: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000130: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000140: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000150: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000160: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000170: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000180: ffff ffff ffff ffff ffff ffff ffff ffff  ################
00000190: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000001a0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000001b0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000001c0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000001d0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000001e0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
000001f0: ffff ffff ffff ffff ffff ffff ffff ffff  ################
EOF_EOF

    cat ${TMP}.seed
    ls -l ${TMP}.seed

    echo "\n\t Creating  512 byte seed file with all bits ON ..."
    xxd -revert ${TMP}.seed >${TMP}.seedbinary

    hexdump ${TMP}.seedbinary
    ls -l ${TMP}.seedbinary

    echo "\n\t Creating 2 Mbyte seed file ..."

    i=4096      ### iterations will create 2 Mbyte file
    while [ true ]
    do
        if [ ${i} -eq 0 ]
        then
            break
        fi

        cat ${TMP}.seedbinary
        echo ".\c" >&2

        i=`expr ${i} - 1 `
    done >${TMP}.seedbinary2
    echo ""

    hexdump -n 512 ${TMP}.seedbinary2
    ls -l ${TMP}.seedbinary2

    echo "\n\t Creating 1 Gbyte seed file ..."

    i=512       ### iterations will create 1 Gbyte file
    while [ true ]
    do
        if [ ${i} -eq 0 ]
        then
            break
        fi

        cat ${TMP}.seedbinary2
        echo ".\c" >&2

        i=`expr ${i} - 1 `
    done >${TMP}.binaryBLOB
    echo ""

    hexdump -n 512 ${TMP}.binaryBLOB
    ### 2097152 bytes
fi
ls -l ${TMP}.binaryBLOB

BS="1048576"                    ### 512 * 2048 bytes = 1 MByte
BLOB_SIZE="1073741824"              ### 1 GBytes
SLICE_BLOCKS=`expr ${BLOB_SIZE} / ${BS} `   ### count of ${BS}-byte blocks for 1 GB file

MAX="160"

if [ -s ${TRACKER} ]
then
    read SLICE <${TRACKER}
    echo "\n\t TRACKER file indicates last completed slice was # ${SLICE}.  Continuing with the next slice ..."
    SLICE=`expr ${SLICE} + 1 `
else
    SLICE=1
fi

REMAIN=`expr ${MAX} - ${SLICE} `
while [ true ]
do
    START_BLOCK=`expr ${SLICE} - 1 `
    START_BLOCK=`expr ${START_BLOCK} \* ${SLICE_BLOCKS} `

    echo "\n\t [${REMAIN}]  Doing slice ${SLICE} of ${MAX} ..."

    COM="dd status=progress bs=${BS} if=${TMP}.binaryBLOB count=${SLICE_BLOCKS} seek=${START_BLOCK} of=${DISK} iflag=fullblock conv=notrunc,fdatasync oflag=dsync"  
    echo "\t ${COM} ..."
    ${COM}
    RC=$?
    date

    if [ ${RC} -ne 0 ] ; then  echo "\n\t ERROR encounted.  RC = ${RC} ...\n Bye!\n" ; exit 1 ; fi
    echo "${SLICE}" >${TRACKER}

    SLICE=`expr ${SLICE} + 1 `
    REMAIN=`expr ${REMAIN} - 1 `
done