Command-Line Shell & File Encryption Engine (Classical DES)
This repository implements the 32-bit x86 MASM assembly assignment: a command-line shell and DES file-encryption engine based on FIPS 46-3. DES is included for coursework compatibility and must not be used for modern security systems.
DCS-CLS/
|-- DES_Shell.asm # Main entry point and shared application state
|-- module_A.inc # Public PROTO declarations for Module A
|-- module_A.asm # Module A variables and implementation
|-- module_B.inc # Public PROTO declarations for Module B
|-- module_B.asm # Module B variables and implementation
|-- module_C.inc # Public PROTO declarations for Module C
|-- module_C.asm # Module C variables and implementation
|-- module_D.inc # Public PROTO declarations for Module D
|-- module_D.asm # Module D variables and implementation
|-- build.bat # Assemble, link, and run the project
|-- test.bat # Clean-build and run automated tests
|-- readme.txt # Plain-text submission information
|-- README.md # English documentation
|-- README.th.md # Thai translation
|-- LICENSE
Each .inc file is a public interface containing PROTO declarations. Each corresponding .asm file owns its variables, procedure bodies, and internal helpers. DES_Shell.asm contains only the entry point and genuinely shared application state.
MASM assembles every .asm file into a separate .obj. The linker then combines all object files into one executable.
The assignment PDF explicitly requires only these procedure names:
DisplayHexDumpComputeBufferStats
All other names are interfaces proposed by this template. The team may change them, but every caller, callee, PROTO, and interface document must be updated together.
Files: module_A.inc, module_A.asm
Responsibilities:
- Run the REPL until the user enters
EXIT. - Parse
KEYGEN,ENCRYPT,DECRYPT,DUMP,STATS,CLEAR,HELP, andEXITwith an FSM. - Validate command syntax, filenames, and keys.
- Report invalid input without terminating the REPL.
- Perform file I/O through the permitted Win32 API or Irvine32 procedures.
Command forms:
ENCRYPT "<input-path>" <key>
ENCRYPT "<input-path>" "<output-path>" <key>
DECRYPT "<input-path>" <key>
DECRYPT "<input-path>" "<output-path>" <key>
When output is omitted, ENCRYPT appends .enc and DECRYPT appends .dec to the input path.
| Procedure | Responsibility | Uses modules |
|---|---|---|
ShellMain |
Run the main REPL | B, C, D |
ReadCommandLine |
Read a command into the input buffer | - |
ParseCommandFSM |
Parse the command, filename, and key | - |
ValidateCommand |
Validate syntax and argument count | - |
DispatchCommand |
Dispatch a parsed command | B, C, D |
ReadWholeFile |
Read a file into a buffer | - |
WriteWholeFile |
Write a buffer to a file | - |
PrintShellError |
Display a non-fatal shell error | - |
HELP command |
Display command names, syntax, and descriptions | - |
Files: module_B.inc, module_B.asm
Responsibilities:
- Accept a 64-bit DES key containing 56 effective bits and 8 parity bits.
- Apply PC-1, rotate the 28-bit C/D halves, and apply PC-2.
- Produce sixteen 48-bit subkeys, K1 through K16.
| Procedure | Responsibility | Visibility |
|---|---|---|
GenerateKeySchedule |
Generate K1-K16 | Public |
DisplayKeySchedule |
Display K1-K16 for KEYGEN |
Public |
ApplyPC1 |
Convert the 64-bit key to C0/D0 | Internal |
RotateKeyHalves |
Rotate C/D left by one or two bits | Internal |
ApplyPC2 |
Produce one 48-bit subkey | Internal |
Required shift schedule:
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
Files: module_C.inc, module_C.asm
Responsibilities:
- Apply IP and inverse IP.
- Execute 16 Feistel rounds.
- Perform E expansion, subkey XOR, S-box lookup, and P permutation.
- Process data in ECB mode with PKCS#7 padding for an 8-byte block.
- Decrypt by applying subkeys from K16 back to K1.
| Procedure | Responsibility | Visibility |
|---|---|---|
EncryptBufferECB |
Encrypt a buffer in ECB mode with padding | Public |
DecryptBufferECB |
Decrypt and validate/remove padding | Public |
EncryptDESBlock |
Encrypt one 64-bit block | Public |
DecryptDESBlock |
Decrypt one 64-bit block | Public |
ApplyInitialPermutation |
Apply IP | Internal |
RunFeistelRounds |
Execute 16 rounds in the selected key order | Internal |
FeistelFunction |
Calculate f(R, K) | Internal |
ExpandRightHalf |
Expand 32 bits to 48 bits | Internal |
ApplySBoxes |
Convert eight 6-bit groups into 32 bits | Internal |
ApplyPPermutation |
Apply P | Internal |
ApplyInversePermutation |
Apply inverse IP | Internal |
AddPKCS7Padding |
Add PKCS#7 padding | Internal |
RemovePKCS7Padding |
Validate and remove padding | Internal |
Files: module_D.inc, module_D.asm
Responsibilities:
- Display 16 bytes per line with offset, hexadecimal, and ASCII columns.
- Display bytes outside
20h-7Ehas.. - Build a 256-bin byte-frequency histogram.
- Display the most frequently occurring byte patterns.
| Procedure | Responsibility | Visibility |
|---|---|---|
DisplayHexDump |
Display offset, hexadecimal, and ASCII | Required public name |
ComputeBufferStats |
Count bytes 00h-FFh |
Required public name |
DisplayTopOccurrences |
Display the most frequent patterns | Public |
IsPrintableASCII |
Test whether a byte is in 20h-7Eh |
Internal |
Each .asm owns its runtime buffers in .data? and initialized DES lookup tables and messages in .data. The tables contain the FIPS 46-3 values used by the implementation.
Specification-defined sizes:
- DES block: 8 bytes
- DES subkeys: 16 x 6 bytes = 96 bytes
- PC-1: 56 entries
- PC-2: 48 entries
- IP and inverse IP: 64 entries each
- Expansion table: 48 entries
- Eight S-boxes: 512 entries in total
- P permutation: 32 entries
- Histogram: 256
DWORDbins
Module A owns the command and file buffers. The maximum plaintext input size is 1 MiB, and ECB encryption reserves eight extra bytes for PKCS#7 padding.
- Use a stack frame:
push ebp,mov ebp, esp, restore the frame, and return. - Preserve caller registers according to the team's calling contract.
- Return the primary result through
EAX. - Use
EAX = 0for success and a non-zero error code where appropriate. - Pass pointers and lengths through the stack according to each
PROTO. - Do not use
.IF,.WHILE, or.REPEATin parser or cipher loops. - Implement DES and its key schedule manually; external encryption libraries are prohibited.
- Use only the permitted Win32 API or Irvine32 procedures for file I/O.
- Open x86 Native Tools Command Prompt for VS.
- Confirm Irvine32 is installed at
C:\Irvine, or editIRVINE_DIRinbuild.bat. - Change to the repository directory.
- Run:
build.batMain build commands:
ml -Zi -c -Fl -coff DES_Shell.asm module_A.asm module_B.asm module_C.asm module_D.asm
link /SUBSYSTEM:CONSOLE /LIBPATH:"C:\Irvine" /OPT:NOREF /OPT:NOICF /DEBUG /NOLOGO /OUT:DES_Shell.exe DES_Shell.obj module_A.obj module_B.obj module_C.obj module_D.objIf Irvine32 procedures are used, add Irvine32.lib, kernel32.lib, and user32.lib to the link command as required by the local installation.
The project includes executable logic for all four modules and a separate automated test runner.
From x86 Native Tools Command Prompt for VS, run:
test.batThe runner checks the official DES vector, K1/K16, block encryption/decryption, ECB/PKCS#7 lengths 0-17, invalid ciphertext and padding, the 256-bin histogram, parser behavior, file I/O round trips, and the 1 MiB file boundary. It returns a non-zero process status if any test fails.
Assign one module to each member and create a branch from the latest main:
git switch main
git pull
git switch -c module-a-shellRecommended branches:
module-a-shellmodule-b-key-schedulemodule-c-feistel-coremodule-d-dump-stats
Write logic in module_X.asm. Modify module_X.inc only when its public interface changes.
git status
git add module_A.asm module_A.inc
git commit -m "Implement module A shell and parser"
git push -u origin module-a-shellOpen a pull request into main and require at least one reviewer to verify:
- Procedure names and parameters match the public contract.
- Register preservation and stack balance are correct.
- Parser and cipher loops do not use prohibited directives.
- No external encryption library is used.
- Generated objects, executables, listings, and debug files are not committed.
- The branch builds and module-level tests pass.
The integration owner should update DES_Shell.asm, merge one module at a time, and avoid overwriting each module owner's work.
- Implement and verify Module B key generation.
- Connect Module C to B and verify single-block DES.
- Test Module D dump and histogram procedures independently.
- Connect Module A to all modules and add file I/O.
- Test complete command flows and error paths.
Official DES test vector:
Plaintext: 0123456789ABCDEF
Key: 133457799BBCDFF1
Expected ciphertext: 85E813540F0AB405
The automated runner also writes test_pdf_sample.bin, containing two copies of
the eight raw bytes 01 23 45 67 89 AB CD EF. It verifies that their first two
encrypted blocks match the sample. PKCS#7 adds a third block, so the encrypted
file is 24 bytes even though the PDF's illustrative trace displays only 16.
Typing the characters 0123456789ABCDEF into a text file creates different
input bytes. The STATS uniformity message is a coursework heuristic: it passes
when at least four byte values occur and none exceeds 25% of the file; it is
not a cryptographic entropy measurement.
- The application runs on Windows 10/11 and the REPL continues until
EXIT. - All eight commands are supported and invalid input does not crash the program.
- DES encryption/decryption, ECB, and PKCS#7 padding are correct.
DUMPdisplays non-printable bytes as..STATSuses 256 bins and displays the top occurrences.- The official DES test vector passes.
- Team member names, IDs, and responsibilities are completed below.
- Assembly sources and the required
readme.txtare included.
| Student ID | Name | Module / responsibility |
|---|---|---|
| 68010321 | Nutthawat Charoensiriphong | Module A - Shell Core, FSM Parser, validation, and File I/O |
| 68011000 | Warithnan Baibua | Module B - DES Key Schedule Generator |
| 68010697 | Panabordee Panitchakit | Module C - DES Feistel Core, ECB, and PKCS#7 |
| 68010713 | Punnawit Khamthorn | Module D - Hex Dump and byte-frequency statistics |