Compare commits

...

2 Commits

Author SHA1 Message Date
bacf0f8d99 add the answer 2025-09-02 15:41:39 +09:00
d2954f92be Add the source code 2025-09-02 15:35:49 +09:00
8 changed files with 651 additions and 1 deletions

2
.gitignore vendored
View File

@@ -15,4 +15,4 @@ target/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/

256
Cargo.lock generated Normal file
View File

@@ -0,0 +1,256 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "aead"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
dependencies = [
"crypto-common",
"generic-array",
]
[[package]]
name = "aes"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
]
[[package]]
name = "aes-gcm"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "bf-macro"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "cfg-if"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"rand_core",
"typenum",
]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "ghash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "inout"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
dependencies = [
"generic-array",
]
[[package]]
name = "libc"
version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "polyval"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "reverse-engineer-is-stupid"
version = "0.1.0"
dependencies = [
"aes-gcm",
"bf-macro",
"hex",
"smallvec",
]
[[package]]
name = "smallvec"
version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "typenum"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "universal-hash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
"crypto-common",
"subtle",
]
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"

21
Cargo.toml Normal file
View File

@@ -0,0 +1,21 @@
[workspace]
resolver = "3"
members = ["bf-macro"]
[package]
name = "reverse-engineer-is-stupid"
version = "0.1.0"
edition = "2024"
[dependencies]
smallvec = { version = "1.15", features = ["union", "const_generics", "const_new"] }
bf-macro = { path = "./bf-macro" }
hex = "0.4"
aes-gcm = "0.10"
[profile.release]
lto = true
opt-level = 3
codegen-units = 1
panic = "abort"
debug = false

View File

@@ -1,2 +1,25 @@
# script-kiddies-know-nothing
A simple CTF problem, the flag is.
```
728a1ab8d1f43450884108c82404633051bd3f30224a0a7e640b16da9f991832
```
This is the hex encoding of the AES key.
## Variations
### English Variation
The encrypted text is:
```
6dc4d2238942706e05a20ebd503aef92aeea742b25290685eba0ce723bb5455695de36a68a0d191f2871c8cb2bfe09e9e363cbcb29595da178a53060e27c99a94a4c50e7f4bdb52d5341eab809f7e774a2cdceaa8426790337b92646ffab9cab553fab9e92f6a84702be2a1ed1d591de72da233bd65d32dec65adf13e783668c
```
The plaintext is
```
As I said, a simple Brainfuck VM is enough to block most of the script kiddies. How stupid they are!
```

12
bf-macro/Cargo.toml Normal file
View File

@@ -0,0 +1,12 @@
[package]
name = "bf-macro"
version = "0.1.0"
edition = "2024"
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["full"] }

39
bf-macro/src/lib.rs Normal file
View File

@@ -0,0 +1,39 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, LitStr};
/// Usage: brainfuck!("++>-[].,")
#[proc_macro]
pub fn brainfuck(input: TokenStream) -> TokenStream {
let lit = parse_macro_input!(input as LitStr);
let s = lit.value();
// Map characters -> OpCode tokens
let mut ops = Vec::new();
for ch in s.chars() {
let token = match ch {
'>' => Some(quote! { OpCode::IncrementPointer }),
'<' => Some(quote! { OpCode::DecrementPointer }),
'+' => Some(quote! { OpCode::Increment }),
'-' => Some(quote! { OpCode::Decrement }),
'.' => Some(quote! { OpCode::Write }),
',' => Some(quote! { OpCode::Read }),
'[' => Some(quote! { OpCode::LoopBegin }),
']' => Some(quote! { OpCode::LoopEnd }),
_ => None, // ignore comments/whitespace
};
if let Some(t) = token {
ops.push(t);
}
}
let n = ops.len();
// Expand to a const array; the caller gets a [OpCode; N]
let expanded = quote! {
{
const __BF_OPS: [OpCode; #n] = [ #(#ops),* ];
__BF_OPS
}
};
expanded.into()
}

36
src/main.rs Normal file
View File

@@ -0,0 +1,36 @@
use aes_gcm::aead::{Aead, OsRng};
use aes_gcm::{AeadCore, Aes256Gcm, KeyInit};
use smallvec::SmallVec;
mod vm;
const RANDOM_ARRAY: [u8; 32] = [
93, 138, 183, 130, 184, 174, 181, 180, 177, 40, 8, 118, 67, 100, 224, 1, 63, 249, 113, 89, 117,
86, 254, 40, 44, 89, 105, 185, 183, 115, 179, 177,
];
fn main() {
let Some(input) = std::env::args().nth(1) else {
eprintln!("Need a input");
return;
};
let mut tape = SmallVec::<[u8; 32]>::from_slice(&RANDOM_ARRAY);
let mut ptr = 0;
vm::run(&vm::parse(vm::KEY), &mut tape, &mut ptr);
let tape_slice = &tape[0..32];
let encrypted = encrypt(tape_slice, &input);
println!("{}", encrypted);
}
fn encrypt(key: &[u8], plaintext: &str) -> String {
let cipher = Aes256Gcm::new_from_slice(key).expect("Invalid key");
let iv = Aes256Gcm::generate_nonce(&mut OsRng);
let ct = cipher
.encrypt(&iv, plaintext.as_bytes())
.expect("Invalid plaintext");
let mut out = SmallVec::<[u8; 16]>::with_capacity(iv.len() + ct.len());
out.extend_from_slice(&iv);
out.extend_from_slice(&ct);
hex::encode(out)
}

263
src/vm.rs Normal file
View File

@@ -0,0 +1,263 @@
use bf_macro::brainfuck;
use smallvec::SmallVec;
use std::io::Read;
#[allow(dead_code)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum OpCode {
IncrementPointer,
DecrementPointer,
Increment,
Decrement,
Write,
Read,
LoopBegin,
LoopEnd,
}
#[allow(dead_code)]
#[derive(Clone)]
pub enum Instruction {
IncrementPointer,
DecrementPointer,
Increment,
Decrement,
Write,
Read,
Loop(Vec<Instruction>),
}
pub fn parse(opcodes: &[OpCode]) -> SmallVec<[Instruction; 16]> {
let mut program: SmallVec<[Instruction; 16]> = SmallVec::new();
let mut loop_stack = 0;
let mut loop_start = 0;
for (i, op) in opcodes.iter().enumerate() {
if loop_stack == 0 {
let instr = match op {
OpCode::IncrementPointer => Some(Instruction::IncrementPointer),
OpCode::DecrementPointer => Some(Instruction::DecrementPointer),
OpCode::Increment => Some(Instruction::Increment),
OpCode::Decrement => Some(Instruction::Decrement),
OpCode::Write => Some(Instruction::Write),
OpCode::Read => Some(Instruction::Read),
OpCode::LoopBegin => {
loop_start = i;
loop_stack += 1;
None
}
OpCode::LoopEnd => panic!("failed to parse"),
};
match instr {
Some(instr) => program.push(instr),
None => (),
}
} else {
match op {
OpCode::LoopBegin => {
loop_stack += 1;
}
OpCode::LoopEnd => {
loop_stack -= 1;
if loop_stack == 0 {
program.push(Instruction::Loop(
parse(&opcodes[loop_start + 1..i]).to_vec(),
))
}
}
_ => (),
}
}
}
if loop_stack != 0 {
panic!("failed to parse");
}
program
}
pub fn run<const N: usize>(instructions: &[Instruction], tape: &mut SmallVec<[u8; N]>, ptr: &mut usize) {
for instr in instructions {
match instr {
Instruction::IncrementPointer => {
*ptr += 1;
if *ptr >= tape.len() {
tape.push(0);
}
}
Instruction::DecrementPointer => *ptr -= 1,
Instruction::Increment => {
let added = tape[*ptr].checked_add(1).unwrap_or(0);
tape[*ptr] = added;
}
Instruction::Decrement => {
let subtracted = tape[*ptr].checked_sub(1).unwrap_or(0);
tape[*ptr] = subtracted;
}
Instruction::Write => {}
Instruction::Read => {
let mut input: [u8; 1] = [0; 1];
std::io::stdin()
.read_exact(&mut input)
.expect("failed to read stdin");
tape[*ptr] = input[0];
}
Instruction::Loop(nested_instructions) => {
while tape[*ptr] != 0 {
run(&nested_instructions, tape, ptr)
}
}
}
}
}
pub const KEY: &[OpCode] = &brainfuck!(
r#"
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
++
>[-]<[->+>+<<]>>[<<+>>-]<
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]< ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++
>[-]<[->+>+<<]>>[<<+>>-]<
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
"#
);
#[cfg(test)]
mod tests {
use crate::RANDOM_ARRAY;
use crate::vm::{KEY, OpCode, parse, run};
use bf_macro::brainfuck;
use smallvec::SmallVec;
const H: &[OpCode] = &brainfuck!(
"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
);
#[test]
fn test_h() {
let mut tape = SmallVec::<[u8; 173]>::from_slice(&[0; 17]);
let mut ptr = 0;
run(&parse(H), &mut tape, &mut ptr);
assert_eq!(tape[0], 97);
}
#[test]
fn test_real_key() {
let mut tape = SmallVec::<[u8; 173]>::from_slice(&RANDOM_ARRAY);
let mut ptr = 0;
run(&parse(KEY), &mut tape, &mut ptr);
let key = &tape[0..32];
let encoded_tape = hex::encode(key);
println!("{:?}", encoded_tape);
}
}