Cryptography is the practice and study of techniques for secure communication in the presence of adversarial behavior. Its primary goals are to ensure the confidentiality, integrity, authenticity, and non-repudiation of digital information.
Key Concepts and Goals:
1. Confidentiality: Ensuring that information is accessible only to those authorized to have access. This is typically achieved through encryption, which transforms readable data (plaintext) into an unreadable format (ciphertext).
2. Integrity: Guaranteeing that data has not been altered or tampered with during transmission or storage. Hashing algorithms and digital signatures are commonly used for this purpose.
3. Authentication: Verifying the identity of communicating parties or the origin of data. This can involve digital certificates, public-key infrastructure (PKI), and challenge-response protocols.
4. Non-repudiation: Preventing a sender from denying having sent a message or a receiver from denying having received a message. Digital signatures are crucial for achieving non-repudiation.
Types of Cryptography:
- Symmetric-key Cryptography: Uses a single secret key for both encryption and decryption. Examples include AES (Advanced Encryption Standard) and DES (Data Encryption Standard). It's generally faster and more efficient for bulk data encryption, but secure key exchange is a challenge.
- Asymmetric-key Cryptography (Public-key Cryptography): Uses a pair of mathematically related keys: a public key (shared widely) and a private key (kept secret). Data encrypted with the public key can only be decrypted with the corresponding private key, and vice-versa. Examples include RSA (Rivest-Shamir-Adleman) and ECC (Elliptic Curve Cryptography). It's slower than symmetric encryption but solves the key exchange problem and enables digital signatures.
- Hashing Functions: One-way mathematical functions that take an input (or 'message') and return a fixed-size string of bytes, typically a 'hash value' or 'message digest'. It's computationally infeasible to reverse the process and derive the original input from the hash value. Hashing is used for data integrity checks, password storage, and data indexing. Examples include SHA-256 and MD5 (though MD5 is now considered insecure for many applications).
Modern cryptography relies heavily on well-vetted algorithms and robust implementations, often provided through cryptographic libraries. These libraries encapsulate complex mathematical operations and security best practices, allowing developers to integrate secure features into applications without needing to implement the cryptographic primitives themselves, which is highly prone to errors.
Example Code
python
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
import os
--- Example 1: Symmetric Encryption (AES-256 in GCM mode) ---
GCM (Galois/Counter Mode) provides both confidentiality and authenticity.
print("--- Symmetric Encryption (AES-256 GCM) ---")
1. Generate a random secret key for AES (256-bit = 32 bytes)
key = os.urandom(32)
2. Generate a random nonce (Initialization Vector) for GCM (128-bit = 16 bytes)
A nonce must be unique for each encryption with the same key.
nonce = os.urandom(16)
Our plaintext data
plaintext = b"This is a highly confidential message for the recipient."
Create a Cipher object with the algorithm (AES) and mode (GCM)
cipher = Cipher(algorithms.AES(key), modes.GCM(nonce), backend=default_backend())
--- Encryption ---
encryptor = cipher.encryptor()
Optional: Authenticate additional data (AAD) that is not encrypted but protected by the tag.
encryptor.authenticate_additional_data(b"metadata about the message")
ciphertext = encryptor.update(plaintext) + encryptor.finalize()
tag = encryptor.tag The authentication tag
print(f"AES Key (hex): {key.hex()}")
print(f"Nonce (hex): {nonce.hex()}")
print(f"Original Plaintext: {plaintext.decode()}")
print(f"Ciphertext (hex): {ciphertext.hex()}")
print(f"Authentication Tag (hex): {tag.hex()}")
--- Decryption ---
decryptor = cipher.decryptor()
If AAD was used during encryption, it must be provided here exactly as it was.
decryptor.authenticate_additional_data(b"metadata about the message")
try:
Decrypt the ciphertext
decrypted_plaintext = decryptor.update(ciphertext) + decryptor.finalize()
Verify the authentication tag. This will raise an exception if the tag is invalid
(meaning the ciphertext or AAD was tampered with).
decryptor.verify(tag)
print(f"Decrypted Plaintext: {decrypted_plaintext.decode()}")
print("Symmetric decryption successful and integrity verified!")
except Exception as e:
print(f"Decryption failed or integrity compromised: {e}")
print("\n" + "-" - 40 + "\n")
--- Example 2: Hashing (SHA256) ---
Hashing is used to create a fixed-size digest of data, primarily for integrity checks.
print("--- Hashing Example (SHA256) ---")
data_to_hash = b"This is some important data to protect its integrity."
Create a SHA256 hash object
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
Update the hash object with the data
digest.update(data_to_hash)
Finalize the hash computation
hash_value = digest.finalize()
print(f"Original Data: {data_to_hash.decode()}")
print(f"SHA256 Hash: {hash_value.hex()}")
--- Integrity Check Simulation ---
print("\nSimulating data tampering...")
tampered_data = b"This is some importent data to protect its integrity." 'important' -> 'importent'
digest_tampered = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest_tampered.update(tampered_data)
hash_value_tampered = digest_tampered.finalize()
print(f"Tampered Data: {tampered_data.decode()}")
print(f"SHA256 Hash of Tampered Data: {hash_value_tampered.hex()}")
if hash_value == hash_value_tampered:
print("Integrity check PASSED: Hashes match, data is identical.")
else:
print("Integrity check FAILED: Hashes DO NOT match, data has been altered!")








Cryptography