I’m looking for a way to invert all bits in a file, preferably using Windows-integrated tools. How do I go about doing that?
In essence, a file with contents 1100101 would become 0011010.
I’m looking for a way to invert all bits in a file, preferably using Windows-integrated tools. How do I go about doing that?
In essence, a file with contents 1100101 would become 0011010.
I've heard it said that "so-called operating systems are just bootloaders for Firefox/Chrome, which is your real operating system"...
preferably using Windows-integrated tools
Paste this into Notepad, Save As Type: All Documents, name it invert_file.html, and open it in Edge version 15 or newer (Firefox and Chrome also work):
<script>
function _invert_arrbuf(arrbuf) {
// Takes in an ArrayBuffer
// and synchronously inverts every bit of it in-place
// (it also returns it anyway, for convenience)
let view = new Uint8Array(arrbuf);
let len = view.length;
if ( len > Number.MAX_SAFE_INTEGER ) throw {error: File too large (${len} > Number.MAX_SAFE_INTEGER).}; // https://stackoverflow.com/q/72807979
for ( let i = 0 ; i < len ; i++ ) {
view[i] ^= -1;
}
return arrbuf;
}
function to_async(f) {
// Converts long-running synchronous or CPU-bound
// function or eval-able string
// into an asynchronous WebWorker-based function
// to avoid blocking the UI
if ( !('Worker' in window) ) return f;
let src = f.toString();
let src_worker = [
"self.addEventListener('message', async m => { ",
"let arguments = m.data.arguments, result; ",
"try { ",
"result = await (\n",
src,
"\n)(...arguments); ",
"self.postMessage({result: result}, [result].filter(x => typeof x === 'object')); ",
"} catch (error) { self.postMessage({error: error}, arguments.filter(x => typeof x === 'object')); } ",
"}, {once: true});"
];
let src_worker_url;
if ('FinalizationRegistry' in window) {
src_worker_url = URL.createObjectURL(new Blob(src_worker, {type: 'application/javascript'}));
} else {
src_worker_url = 'data:application/javascript,' + encodeURIComponent(src_worker.join(String()));
}
async function g() {
let w = new Worker(src_worker_url);
let p = new Promise((resolve, reject) => w.addEventListener('message', m => m.data.hasOwnProperty('result') ? resolve(m.data.result) : reject(m.data.error), {once: true}));
w.postMessage({arguments: Array.from(arguments)}, Array.from(arguments).filter(x => typeof x === 'object'));
let result = await p;
return result;
}
if ( src_worker_url.startsWith('blob:') ) new FinalizationRegistry(URL.revokeObjectURL).register(g, src_worker_url);
return g;
}
var invert_arrbuf = to_async(_invert_arrbuf);
function create_download_link(file, linktext) {
// Takes in a File (or Blob) object
// and returns a "self-destructing" one-use link to it
// as a DOM element
let a = document.createElement('a');
let u = URL.createObjectURL(file);
console.debug(u);
a.href = u;
if ( file.name ) {
a.setAttribute('download', file.name);
}
if (linktext === undefined) {
linktext = Download ${file.name} (${file.size} bytes);
}
a.textContent = linktext;
a.addEventListener('click', ev => setTimeout(() => {ev.target.parentNode.removeChild(ev.target); URL.revokeObjectURL(ev.target.href);}, 1));
return a;
}
async function main(file) {
// Takes in a File,
// and returns a File with contents bit-flipped
// and a name with .not.bin stripped if not present and appended if present
let [basename, suffix] = file.name.match(/(.*?)(\.not\.bin)?$/).slice(1);
let new_filename = basename + (suffix ? '' : '.not.bin');
let new_arrbuf = await file.arrayBuffer();
delete file; // pray to the gods of garbage collection...
new_arrbuf = await invert_arrbuf(new_arrbuf);
let new_file = new File([new_arrbuf], new_filename);
delete new_arrbuf; // ...that we might use less than 3x the necessary RAM
// -- If you intend to manipulate files larger than about half the available RAM,
// see https://stackoverflow.com/questions/39682465
// or consider using 3rd-party software like Python or Elixir
// via RAM-friendly APIs like Iterators or Streams
return new_file;
}
async function form_handler(ev) {
// Takes in a Submit event,
// clears the form's file input,
// feeds the input file to main(),
// and appends to the document body
// a self-destructing link to the result.
// If main() errors out, a red warning message
// will be appended instead.
let form = ev.target;
let input = form.elements.file;
let file = input.files[0];
input.value = null;
let e = document.createElement('div');
let e1 = document.createElement('span');
e1.textContent = `Processing ${file.name}\u2026`;
e.appendChild(e1);
document.body.appendChild(e);
let new_file;
try {
new_file = await main(file);
} catch (err) {
e1.textContent = `Failed processing ${file.name}!`;
e1.classList.add('error');
e1.addEventListener('click', () => e.parentNode.removeChild(e));
throw err;
}
let a = create_download_link(new_file);
a.addEventListener('click', () => e.parentNode.removeChild(e));
e.replaceChild(a, e1);
}
</script>
<style>span.error { color: red; }</style>
<form action="javascript:{form_handler({target: document.getElementById('main_form')});}" id="main_form">
<input type="file" name="file" />
<input type="submit" name="submit" value="Encrypt (ECB with blocksize ⅛B)" />
</form>
You can try with the following powershell line :
[byte[]](gc in.bin -Encoding Byte| % {$_ -bxor 0xFF })|sc out.bin -Encoding Byte
Think to replace 'in.bin' and 'out.bin' by your input and output filename.
A more explicit version (without alias):
[byte[]](Get-Content in.bin -Encoding Byte| ForEach {$_ -bxor 0xFF })| Set-Content out.bin -Encoding Byte
The command do a XOR with each byte one by one to invert bit in file.
In powershell version 6 and more, you need to replace "-Enconding Byte" by "-AsByteStream"
[byte[]](Get-Content in.bin -AsByteStream| ForEach {$_ -bxor 0xFF })| Set-Content out.bin -AsByteStream