Thursday, July 23, 2026

Spring Security Interview Question

public key


  1. Publicly shared encryption key
  2. Encrypts sensitive data
  3. Verifies digital signatures
  4. Paired with private key
  5. Cannot decrypt private data


private key


  1. Secret cryptographic key
  2. Decrypts encrypted data
  3. Creates digital signatures
  4. Paired with public key
  5. Must remain confidential




certificate


  1. Verifies entity identity
  2. Contains public key
  3. Issued by Certificate Authority
  4. Enables secure communication
  5. Used in SSL/TLS


pkcs file


  1. Stores cryptographic keys securely
  2. Contains certificates and keys
  3. Password-protected file format
  4. Commonly uses .p12
  5. Used for SSL/TLS


pem file


  1. Base64-encoded text format
  2. Stores certificates or keys
  3. Uses ASCII encoding
  4. Begins with BEGIN header
  5. Commonly used for SSL



cacerts


  1. JVM trusted certificates store
  2. Contains CA certificates
  3. Validates SSL/TLS connections
  4. Used by HTTPS clients
  5. Managed using keytool


cookie


  1. Stored in browser
  2. Maintains user session
  3. Sent with requests
  4. Can store small data
  5. Supports authentication state


session


  1. Stores user-specific state
  2. Maintained on server
  3. Identified using session ID
  4. Persists across requests
  5. Expires after inactivity



JWT


Stateless authentication mechanism

Contains signed user claims

Validated by security filter

No server-side session

Secures protected API endpoints


 Spring Cloud Gateway

  1. Centralized API authentication
  2. Validates JWT tokens
  3. Applies authorization rules
  4. Routes secured requests
  5. Protects downstream services



@PreAuthorize


  1. Method-level security annotation
  2. Checks access before execution
  3. Uses SpEL expressions
  4. Supports roles and permissions
  5. Blocks unauthorized access


claims


  1. JWT payload information
  2. Contains user identity
  3. Includes roles and permissions
  4. Digitally signed data
  5. Used for authorization


principal


  1. Represents authenticated user
  2. Contains user identity
  3. Available in SecurityContext
  4. Used for authorization
  5. Retrieved after authentication





What is the difference between DelegatingFilterProxy and FilterChainProxy in Spring Security?

  • DelegatingFilterProxy: A standard Servlet filter registered in the traditional web.xml or Servlet container context. It does not perform security checks itself. Instead, it bridges the gap by delegating the filter workload to a Spring-managed bean.
  • FilterChainProxy: The actual Spring-managed bean that wraps the SecurityFilterChain. It orchestrates the sequence of custom and predefined security filters (JwtAuthenticationFilter, UsernamePasswordAuthenticationFilter, etc.)

How do you protect a Java application against SQL Injection (SQLi) and Cross-Site Scripting (XSS)?

  • SQL Injection: Never concatenate input variables directly inside raw queries. Use PreparedStatementor robust Object-Relational Mappings (ORMs) like Hibernate/JPA. They separate query logic from data parameters using automated placeholder binding.
  • XSS Mitigation: Treat all incoming data as untrusted. Use context-aware HTML/Javascript escaping via libraries like OWASP Java Encoder. Implement strict Content Security Policies (CSP) headers to stop unauthorized third-party scripts from executing inside your UI layer.

Wednesday, July 22, 2026

Choosing Programming Language

 ENIAC 

Used Decimal system

Initially used to find ballistic trajectory 

Team adjusted knobs and final trajectory was pushed to Punch Card 

EDVAC (1949): 




  switched to true binary 0 and 1 machine code and stored those 0s and 1s as acoustic waves inside tubes of liquid mercury 

introduced the Stored-Program Concept. The instructions to calculate a trajectory were converted into digital binary code (0s and 1s) and saved directly into the computer's memory

Assembly 

replaced raw binary instructions with short, memorable text commands called mnemonics. Instead of typing 00001011, the programmer typed ADD


Hand written 


To a human, an assembly instruction looks like a short text command (e.g., mov rax, 42). But to a computer CPU, an instruction is nothing more than a fixed-size sequence of 1s and 0s (a binary number) grouped into specific structural patterns called fields. [1, 2, 3, 4] 
Here is how a machine code instruction is structured and decoded by the CPU hardware. [5, 6] 

  The Anatomy of an Instruction

Every instruction is broken up into distinct logical pieces. The most basic blueprint contains two primary components: 
┌─────────────────────────────────┐
│            INSTRUCTION          │
├────────────────┬────────────────┤
│     OPCODE     │    OPERAND     │
│  (What to do)  │ (What to do to)│
└────────────────┴────────────────┘
  1. The Opcode (Operation Code): The unique binary ID that tells the CPU what math or logic circuit to activate (e.g., Add, Subtract, Load, Jump). [9, 10, 11, 12, 13] 
  2. The Operand(s): The data fields that tell the CPU where to find the source inputs or where to place the output result (e.g., specific registers, or a memory address). [14, 15, 16, 17, 18] 

  A Real-World Example: Adding Two Numbers

Let’s look at exactly what a real instruction looks like on an x86_64 processor (Intel or AMD).
Suppose we want to add the number 5 directly to the EBX register. [19] 

1. The Assembly Code (Human Readable)

add ebx, 5

2. The Machine Code (Hexadecimal Format)

Engineers often read binary using Hexadecimal shorthand to keep it concise:
83 C3 05

3. The Pure Machine Code (What the CPU Actually Reads)

When loaded into RAM, it is exactly 3 bytes of raw binary voltage pulses:
10000011  11000011  00000101

 How the CPU Decodes Those Bits

When the CPU's Instruction Decoder pulls those 24 bits (10000011 11000011 00000101) into its processing pipeline, it instantly breaks them down into hardware triggers: [20, 21] 
  • 10000011 (Byte 1: Opcode Matrix)
    The CPU reads the first few bits and recognizes this specific number matches the hardwired hardware circuit for an "ADD operation involving an immediate value and a register." [22, 23, 24] 
  • 11000011 (Byte 2: ModR/M Field)
    This byte is split into sub-blocks that point to target locations. The bits 011 explicitly route the output connection wires directly to the EBX Register hardware slot on the chip.
  • 00000101 (Byte 3: Immediate Data)
    This is the raw, literal binary number 5 (4 + 1). The CPU channels this value directly into its Arithmetic Logic Unit (ALU) to combine with whatever is already sitting inside the EBX register.

  RISC vs. CISC Instruction Sizes

Depending on the architecture of your device, instructions look physically different in memory:
  • ARM / RISC (Apple Silicon, Smartphones): Uses Fixed-Length instructions. Every single instruction is exactly 32 bits (4 bytes) long. This makes it incredibly easy for the CPU to stream instructions fast and save battery power because it always knows exactly where the next instruction begins. [25, 26, 27, 28, 29] 
  • x86 / CISC (Intel, AMD PCs): Uses Variable-Length instructions. An instruction can be as short as 1 byte (like 0x90 for NOP/No-Operation) or as long as 15 bytes for incredibly complex memory-routing math. This makes the chip design highly complex but allows for dense, tightly packed code programs. [30, 31, 32, 33, 34] 

 









Core Features of C
  • Procedural and Structured: Programs are organized using distinct, reusable blocks called functions.
  • Low-Level Hardware Access: Allows direct manipulation of computer memory registers and hardware addresses.
  • Pointers: Variables that store the exact memory addresses of other variables for high-speed data handling.
  • Statically Typed: All variable data types (like integers or characters) must be declared and checked before compiling.
  • Extremely Portable: Source code can be easily compiled for completely different computer architectures with minimal changes.
  • Minimalist Standard Library: Focuses on raw performance, avoiding heavy built-in features to keep the runtime footprint tiny.

New Features in C++ (On Top of C)

  • Object-Oriented Programming (OOP): Introduced Classes and Objects to group data variables and functions together into single units.
  • Encapsulation & Access Control: Added keywords (publicprivateprotected) to secure data from unauthorized modification.
  • Polymorphism (Virtual Functions): Enables a single command to behave differently based on the specific type of object executing it.
  • Inheritance: Allows a new class to automatically adopt the properties and code of an existing class, reducing duplicate work.
  • Constructors & Destructors: Automatically allocate memory when an object is created and safely clean it up when deleted, preventing memory leaks.
  • Function & Operator Overloading: Allows multiple functions to share the exact same name if they use different inputs, and lets standard symbols (like +) manipulate user-defined objects.
  • References (&): Introduced a safer, cleaner alternative to C pointers that acts as an alias for an existing variable without the risks of manual address arithmetic.
  • Standard Template Library (STL): Provided a massive, pre-built collection of ready-to-use data structures (like vectors, lists, and queues) and algorithms out of the box.

The C Compilation Process (4 Key Steps)

When you run a command like gcc main.c, the compiler executes four distinct steps behind the scenes to turn human-readable C code into a runnable binary executable file.
 [ .c Source Code ] 
         │
         ▼  (Step 1) PREPROCESSING (Expands macros, includes headers)
 [ .i Expanded Source ]
         │
         ▼  (Step 2) COMPILATION (Translates C to Assembly)
 [ .s Assembly Code ]
         │
         ▼  (Step 3) ASSEMBLY (Translates Assembly to Binary Object)
 [ .o / .obj Object Code ] ───▶ [ Linker ] ◀─── [ Pre-compiled Libraries ]
                                   │
                        (Step 4)   ▼ LINKING (Stitches blocks together)
                             [ Executable Binary ]

Step 1: Preprocessing

  • What happens: The preprocessor (cpp) cleans up the raw text of your .c source code file.
  • The actions: It strips away comments, copies the contents of header files (like #include <stdio.h>) directly into the file, and replaces macro shorthand (like #define PI 3.14) with its actual value.
  • Output: A temporary, expanded pure text file (usually ending in .i).

Step 2: Compilation

  • What happens: The compiler core (cc1) translates the high-level syntax of the preprocessed text file into low-level machine logic.
  • The actions: It analyzes syntax errors, maps data variables to hardware registries, and outputs the code using architecture-specific computer instructions.
  • Output: An assembly language text file tailored to your specific CPU (usually ending in .s).

Step 3: Assembly

  • What happens: The assembler (as) converts human-readable assembly instructions into raw machine language instructions.
  • The actions: It translates commands like MOV or ADD directly into binary operational codes (opcodes).
  • Output: An unlinked machine-code binary file called an Object File (usually ending in .o or .obj). This file cannot run yet because it contains placeholder addresses for unresolved functions.

Step 4: Linking

  • What happens: The linker (ld) stitches independent code blocks into a single, cohesive, self-contained system executable file.
  • The actions: If your program calls a standard library routine (like printf), the linker finds its pre-compiled binary code inside the operating system library paths and links it. It also merges multiple user-written .o files into one layout and resolves memory addresses.
  • Output: The final executable file (e.g., a.outmain, or main.exe).

What Changed in this Process for C++?

The fundamental structural stages (Preprocessing $\rightarrow$ Compilation $\rightarrow$ Assembly $\rightarrow$Linking) remain identical in C++. However, because C++ introduces objects, classes, and function overloading, the compiler and linker had to adopt three major procedural changes on top of the standard C pipeline:

1. Name Mangling (During Compilation)

  • The Challenge: In C, every function must have a completely unique name. In C++, you can have three distinct functions all named print() as long as they accept different data inputs (Function Overloading).
  • The Change: To prevent the assembler and linker from getting confused by matching names, the C++ compiler automatically rewrites function names behind the scenes. A function like print(int x) is mangled into something unique like _Z5printi. This ensures the linker can uniquely match function calls to their exact binary definitions.

2. VTable Generation (During Compilation)

  • The Challenge: C++ supports runtime polymorphism, meaning a single function call to a base class might need to execute entirely different code depending on which inherited object subclass is active at runtime.
  • The Change: The C++ compiler generates a hidden lookup array called a Virtual Table (VTable) for classes containing virtual functions. Instead of hardcoding a direct memory address during compilation, it emits instructions telling the processor to look up the target address inside the VTable at execution time.

3. Object Construction & Destructor Injections (During Compilation)

  • The Challenge: C++ objects require precise memory initialization upon creation and automatic memory cleanup when they fall out of scope.
  • The Change: The compiler steps through your functions and silently injects low-level constructor and destructor instructions directly into the assembly pipeline. It ensures that memory allocations, pointer tracking, and variable initialization happen automatically without requiring explicit manual code updates from the developer.

 
When you run a compiled C or C++ application, the CPU executes the raw machine instructions directly. However, whenever your program needs to interact with the outside world (like printing text, allocating memory, or reading a file), it cannot talk to the hardware directly; it must ask the Operating System (OS) for help via system calls. [1, 2, 3, 4, 5] 

🪵 The Division of Labor

[ Your C/C++ Code ] 
        │
        ├──► Pure Math / Logic ──────► [ Direct CPU Execution ]
        │
        └──► Input/Output / Memory ──► [ OS Kernel API ] ──► [ Hardware / CPU ]

1. What C/C++ Executes DIRECTLY on the CPU

For standard logic, math, and data manipulation, C and C++ completely bypass the operating system. The compiler translates these lines directly into raw machine instructions. [6, 7] 
  • Examples: Adding numbers, loops (for/while), array manipulation, sorting algorithms, and basic logic switches (if/else).
  • How it looks:
    int a = 5;
    int b = 10;
    int c = a + b; // Compiles to a single CPU instruction: 'add'
    
  • Performance: This runs at the absolute maximum speed of your processor chip because there is zero OS overhead. [8, 9, 10, 11, 12] 

2. What C/C++ Must Route Through the OS API

The CPU operates in different security privileges. Normal applications run in User Mode (restricted access). The OS kernel runs in Kernel Mode (full hardware access). If your C++ code tries to touch hardware or cross process boundaries without the OS, the CPU will trigger a security fault and kill your program. [13, 14, 15, 16, 17] 
  • Examples: Writing to the screen (std::cout), reading a file, connecting to the internet, or requesting heap memory (new or malloc).
  • How it looks:
    std::cout << "Hello!"; 
    
  • Under the Hood: The C++ Standard Library wraps this nice command into a low-level OS API request (e.g., write() on Linux, WriteFile() on Windows). The CPU handles a Software Interrupt, safely hands execution control over to the OS kernel, the OS interacts with the monitor hardware, and then control is handed back to your program. [18, 19, 20, 21, 22] 

🔍 A Concrete Example: Allocating Memory

To see exactly how this hybrid approach works, look at what happens when you create a dynamic array in C++:
int* arr = new int[1000]; // 1. Calls OS API (Requires permission for memory)
arr[0] = 42;              // 2. Direct CPU Instruction (Blazing fast math)
  1. new int[1000]: Your program does not own the computer's physical RAM. The C++ runtime must drop down and call an OS memory allocation API (like brk or mmap on Linux). The OS updates its virtual page tables, grants your program a safe block of addresses, and returns control to C++. [23, 24] 
  2. arr[0] = 42: Now that your program safely owns that block of memory, assigning the value 42 bypasses the OS entirely. The compiler converts this line into a raw mov (move) assembly instruction. The CPU moves the binary digits straight into its hardware cache registers.

🔓 Exception: Bare-Metal Coding (No OS)

There is one major exception to this rule: Embedded Systems. [25] 
If you are writing C or C++ for an Arduino, a microwave controller, a car engine computer, or writing an Operating System kernel from scratch, there is no OS API to call. [26] 
In these environments, C and C++ compilers are configured to interface 100% directly with the CPU and memory registers. Writing to an output pin or an LCD display means using pointers to overwrite specific, physical hardware memory addresses mapped directly to the processor's pins.

 

Because Java was designed to solve the problem of "Write Once, Run Anywhere" (WORA), it introduced a dual-stage execution model. It sits completely on top of a runtime engine written in C++, which handles the heavy lifting of interacting with the physical operating system.
Here is the exact breakdown of how this pipeline operates under the hood:
1. The Compilation Phase (Human to Bytecode)
  • What Happens: When a developer writes code in a .java file and compiles it (using javac), the compiler does not generate machine code or assembly for a real CPU.
  • The Output: It outputs a .class file containing Bytecode. Bytecode is a highly optimized set of instructions designed for a hypothetical, universal computer—the JVM.
2. The JVM: Built on C++
  • The Layer: The standard JVM (Oracle’s HotSpot) is a massive software application written primarily in C++ (along with some low-level Assembly).
  • The Subsystem: Because it is built in C++, it has direct access to OS system calls, memory management, and threads. The JVM acts as a buffer shield between your Java code and the operating system.
3. The Execution Phase (Bytecode to Assembly)
When you run a Java application, the C++ engine of the JVM processes the bytecode using two distinct execution strategies:
[ .class Bytecode ] 
         │
         ▼
 ┌─────────────── JVM (Built in C++) ────────────────┐
 │                                                   │
 │ ──▶ [ Interpreter ] ──▶ Translates line-by-line   │
 │                                                   │
 │ ──▶ [ JIT Compiler ] ─▶ Translates hot loops      │
 │                         directly to Native Asm    │
 └───────────────────────────────────────────────────┘
         │
         ▼
 [ Native OS / CPU Assembly ]
  • The Interpreter: The JVM reads the bytecode instructions line-by-line and translates them into corresponding C++ runtime functions, which then execute on the OS. This gets the program running instantly but is relatively slow.
  • The JIT (Just-In-Time) Compiler: To speed things up, the JVM monitors the running code. If it finds a section of bytecode that is executed repeatedly (a "hot spot"), the JIT compiler instantly compiles that bytecode block directly into native CPU assembly code in memory, completely bypassing interpretation for subsequent loops.

Why Was This Shift Away From Native C++ Necessary?
MetricC++ StrategyJava / JVM Strategy
TargetCompiles down to a specific OS/CPU architecture.Compiles down to universal intermediate Bytecode.
PortabilityMust recompile the entire codebase for every single platform.The same .class file runs unmodified on any machine with a JVM.
MemoryManual memory allocation (mallocnewdelete).Automatic Garbage Collection handled by the C++ engine.
SafetyCrash-prone if pointers access illegal memory spaces.Sandboxed environment prevents direct malicious memory corruption.
1. Python is Built on C, Not C++
The standard, official version of Python that everyone downloads from Python.org is called CPython. As the name suggests, the entire Python executable, its runtime environment, and its core libraries are written in pure C, not C++. [123]
(Note: There are alternative versions of Python like PyPy, or Jython which is written in Java, but the standard engine is completely C-based). [12]
2. Python Does Not Convert Code to Assembly
Unlike a C++ compiler, the standard Python interpreter never converts your Python code into CPU assembly language or machine code instructions. [12]
Instead, the process looks like this:
[ .py Source Code ]
         │
         ▼  (Step 1: Automated Compilation)
[ .pyc Bytecode ]  ──▶ Stored in __pycache__ folder
         │
         ▼  (Step 2: Interpretation Loop)
 ┌─────────────── CPython Engine (Written in C) ──────────────┐
 │                                                            │
 │  Reads Bytecode instructions one-by-one                   │
 │                                                            │
 │  [ Bytecode: BINARY_ADD ] ──▶ Evaluates via C functions    │
 │                                                            │
 └────────────────────────────────────────────────────────────┘
         │
         ▼
 [ Directly Triggers Pre-Compiled C Executable Logic on CPU ]
Step 1: The Hidden Compilation (Source to Bytecode)
When you run a Python script, it doesn't immediately read the text line-by-line. First, Python’s internal C-compiler parses your entire .py file and translates it into an intermediate low-level language called Bytecode (compiled .pyc files found in your __pycache__ directory). [12]
Step 2: The Virtual Machine Loop (No Assembly Needed)
This bytecode is handed over to the Python Virtual Machine (PVM). The PVM is just a massive loop written in C. It reads the bytecode instructions one at a time: [12]
  • If your bytecode says BINARY_ADD, the PVM does not generate an assembly ADD instruction for your computer chip.
  • Instead, the PVM calls a pre-compiled C function (like PyNumber_Add()) that has already been turned into machine code when Python itself was installed on your computer.
Summary: Why This Matters
Because Python relies on a C-runtime engine to evaluate instructions on the fly rather than translating your code directly into native CPU assembly, it achieves incredible cross-platform flexibility. However, this extra layer of runtime interpretation is also the exact reason why Python runs significantly slower than pure compiled languages like C or C++. [123]

Spring Security Interview Question

public key Publicly shared encryption key Encrypts sensitive data Verifies digital signatures Paired with private key Cannot decrypt pr...