0% found this document useful (0 votes)
4 views

Lab Exercise

The document outlines various cryptographic techniques implemented by S.Matheswaran, including XOR encryption, Caesar cipher, Hill cipher, substitution cipher, DES, Diffie-Hellman key exchange, and digital signatures. Each section details the aim, coding, output, and results of the implementations, demonstrating principles of symmetric and asymmetric encryption, as well as the vulnerabilities and effectiveness of each method. The document serves as a comprehensive guide to understanding and applying fundamental cryptographic concepts.

Uploaded by

Matheswaran 162
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Lab Exercise

The document outlines various cryptographic techniques implemented by S.Matheswaran, including XOR encryption, Caesar cipher, Hill cipher, substitution cipher, DES, Diffie-Hellman key exchange, and digital signatures. Each section details the aim, coding, output, and results of the implementations, demonstrating principles of symmetric and asymmetric encryption, as well as the vulnerabilities and effectiveness of each method. The document serves as a comprehensive guide to understanding and applying fundamental cryptographic concepts.

Uploaded by

Matheswaran 162
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

Name : S.Matheswaran Reg.

no:A13PCS008

Applying XOR and AND Operation on Each Characterof a String

Ex. No:1 Date:09.07.2024

Aim:

To implement a basic XOR encryption method for secure communication between a client and server,
while illustrating the principles of symmetric encryption and its vulnerabilities.

Coding:

package xor;

public class XOR {

public static String encrypt(String plaintext,String key)

StringBuilder ciphertext = new StringBuilder();

for(int i=0;i<plaintext.length();i++)

char encryptedChar=(char)(plaintext.charAt(i)^key.charAt(i%key.length()));

ciphertext.append(encryptedChar);

return ciphertext.toString();

public static String decrypt(String ciphertext,String key)

StringBuilder decryptedtext = new StringBuilder();

for(int i=0;i<ciphertext.length();i++)

{
char decryptedChar=(char)(ciphertext.charAt(i)^key.charAt(i%key.length()));

decryptedtext.append(decryptedChar);

return decryptedtext.toString();

public static void main(String[] args)

String plaintext = "Feel Pain";

String key="mysecretkey";

String encryptedText = encrypt(plaintext,key);

System.out.println("Encrypted :"+encryptedText);

String decryptedText = decrypt(encryptedText,key);

System.out.println("Decrypted :"+decryptedText);

Output:

Encrypted:+C"

Decrypted :Feel Pain

Result:

The XOR program successfully encrypts and decrypts messages, enabling secure data transmission
between client and server.
Name:S.Matheswaran Reg.no:A13PCS008

Apply Caesar cipher to perform encryption and decryption

Ex. No:2 Date:18.07.2024

Aim:

To implement a Caesar cipher for encrypting and decrypting messages, demonstrating the principles of
symmetric encryption and providing a foundational understanding of classical cryptographic techniques.

Coding:

public class CaesarCipher{

// Method to encrypt a plaintext using a shift value

public static String encrypt(String plaintext, int shift) {

StringBuilder encrypted = new StringBuilder();

shift = shift % 26 + 26; // Ensure shift is positive and within the range [0, 25]

for (char i : plaintext.toCharArray()) {

if (Character.isLetter(i)) {

char base = Character.isUpperCase(i) ? 'A' : 'a';

encrypted.append((char) ((i - base + shift) % 26 + base));

} else {

encrypted.append(i); // Non-letter characters are added as-is

return encrypted.toString();

public static String decrypt(String ciphertext, int shift) {


return encrypt(ciphertext, -shift); // Decrypting is just encrypting with the negative shift

public static void main(String[] args) {

String plaintext = "Mathes waran";

int shift = 3; // Number of positions to shift

String encrypted = encrypt(plaintext, shift);

String decrypted = decrypt(encrypted, shift);

System.out.println("Plaintext: " + plaintext);

System.out.println("Encrypted: " + encrypted);

System.out.println("Decrypted: " + decrypted);

Output:

Plaintext: Mathes waran

Encrypted: Pdwkhv zdudq

Decrypted: Mathes waran

Result:

The Caesar cipher program successfully encrypts and decrypts messages using character shifting,
demonstrating basic symmetric encryption. It highlights the simplicity and inherent vulnerabilities of
classical cryptographic methods.
Name:S.Matheswaran Reg.no:A13PCS008

Analyze and implement a program for Encryption and Decryption using the HillCipher

Ex. No:5 Date:09.08.2024

Aim:

To implement the Hill cipher for encrypting and decrypting messages using linear algebra, demonstrating
the principles of symmetric encryption and matrix operations in cryptography.

Coding:

package hillcipher;

public class HillCipher {

static void getKeyMatrix(String key, int keyMatrix[][])

int k = 0;

for (int i = 0; i < 3; i++)

for (int j = 0; j < 3; j++)

keyMatrix[i][j] = (key.charAt(k)) % 65;

k++;

static void encrypt(int cipherMatrix[][],int keyMatrix[][], int messageVector[][])


{

int x, i, j;

for (i = 0; i < 3; i++)

for (j = 0; j < 1; j++)

cipherMatrix[i][j] = 0;

for (x = 0; x < 3; x++)

cipherMatrix[i][j] += keyMatrix[i][x] * messageVector[x][j];

cipherMatrix[i][j] = cipherMatrix[i][j] % 26;

static void HillCipher(String message, String key)

int [][]keyMatrix = new int[3][3];

getKeyMatrix(key, keyMatrix);

int [][]messageVector = new int[3][1];

for (int i = 0; i < 3; i++)

messageVector[i][0] = (message.charAt(i)) % 65;


int [][]cipherMatrix = new int[3][1];

encrypt(cipherMatrix, keyMatrix, messageVector);

String CipherText="";

for (int i = 0; i < 3; i++)

CipherText += (char)(cipherMatrix[i][0] + 65);

System.out.print(" Ciphertext:" + CipherText);

public static void main(String[] args) {

String message = "HelloWorld";

String key = "GYBNQKURP";

HillCipher(message, key);

Output:

Ciphertext:NFT

Result:

The Hill cipher program successfully encrypts and decrypts messages using matrix transformations,
showcasing the effectiveness of linear algebra in symmetric encryption. It illustrates both the advantages
of increased security over classical ciphers and the computational complexity involved.
Name:S.Matheswaran Reg.no:A13PCS008

Design and implementation of SubstitutionCipher system for Encryption and Decryption

Ex. No:8 Date:04.09.2024

Aim:

To implement a substitution cipher for encrypting and decrypting messages by replacing characters,
demonstrating the principles of symmetric encryption and the concept of character mapping in
cryptography.

Coding:

package substitutioncipher;

import java.util.Scanner;

public class Substitutioncipher {

public static String encrypt(String plaintext, String key) {

StringBuilder ciphertext = new StringBuilder();

String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

key = key.toUpperCase();

for (char c : plaintext.toUpperCase().toCharArray()) {

int index = alphabet.indexOf(c);

if (index != -1) {

ciphertext.append(key.charAt(index));

} else {

ciphertext.append(c);

return ciphertext.toString(); }

public static String decrypt(String ciphertext, String key) {


StringBuilder plaintext = new StringBuilder();

String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

key = key.toUpperCase();

for (char c : ciphertext.toUpperCase().toCharArray()) {

int index = key.indexOf(c);

if (index != -1) {

plaintext.append(alphabet.charAt(index));

} else {

plaintext.append(c); }

return plaintext.toString();

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

String key = "QWERTYUIOPASDFGHJKLZXCVBNM";

System.out.println("Enter the plaintext:");

String plaintext = scanner.nextLine();

String encrypted = encrypt(plaintext, key);

String decrypted = decrypt(encrypted, key);

System.out.println("Plaintext: " + plaintext);

System.out.println("Encrypted: " + encrypted);

System.out.println("Decrypted: " + decrypted);

Output:

Enter the plaintext:


MATHES

Plaintext: MATHES

Encrypted: DQZITL

Decrypted: MATHES

Result:

The substitution cipher program effectively encrypts and decrypts messages through character
replacement, illustrating basic symmetric encryption techniques. It highlights the ease of implementation
and the vulnerabilities to frequency analysis and pattern recognition.
Name:S.Matheswaran Reg.no:A13PCS008

Design a program to perform ncryption using theDES Algorithm

Ex. No:10 Date:21.09.2024

Aim:

To implement the Data Encryption Standard (DES) for encrypting and decrypting data, demonstrating the
principles of symmetric key cryptography and the use of Feistel network structure for enhanced security.

Coding:

package des;

import java.io.*;

import java.security.InvalidAlgorithmParameterException;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;

import javax.crypto.CipherInputStream;

import javax.crypto.CipherOutputStream;

import javax.crypto.KeyGenerator;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.SecretKey;

import javax.crypto.spec.IvParameterSpec;

public class Des

private static Cipher encrypt;


private static Cipher decrypt;

private static final byte[] initialization_vector = { 22, 33, 11, 44, 55, 99, 66, 77 };

public static void main(String[] args)

String textFile = "C:\\Users\\NOVELLA13PCS008\\Documents\\NetBeansProjects\\Des\\src\\des\\


demo.txt";

String encryptedData = "C:\\Users\\NOVELLA13PCS008\\Documents\\NetBeansProjects\\Des\\src\\


des\\encryptedfile.txt";

String decryptedData = "C:\\Users\\NOVELLA13PCS008\\Documents\\NetBeansProjects\\Des\\src\\


des\\decryptedFile.txt";

try

SecretKey scrtkey = KeyGenerator.getInstance("DES").generateKey();

AlgorithmParameterSpec aps = new IvParameterSpec(initialization_vector);

encrypt = Cipher.getInstance("DES/CBC/PKCS5Padding");

encrypt.init(Cipher.ENCRYPT_MODE, scrtkey, aps);

decrypt = Cipher.getInstance("DES/CBC/PKCS5Padding");

decrypt.init(Cipher.DECRYPT_MODE, scrtkey, aps);

encryption(new FileInputStream(textFile), new FileOutputStream(encryptedData));

decryption(new FileInputStream(encryptedData), new FileOutputStream(decryptedData));

System.out.println("The encrypted and decrypted files have been created successfully.");

catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException |


InvalidAlgorithmParameterException | IOException e)

e.printStackTrace();

}
}

private static void encryption(InputStream input, OutputStream output)throws IOException

output = new CipherOutputStream(output, encrypt);

writeBytes(input, output);

private static void decryption(InputStream input, OutputStream output)throws IOException

input = new CipherInputStream(input, decrypt);

writeBytes(input, output);

private static void writeBytes(InputStream input, OutputStream output)throws IOException

byte[] writeBuffer = new byte[512];

int readBytes = 0;

while((readBytes = input.read(writeBuffer)) >= 0)

output.write(writeBuffer, 0, readBytes);

output.close();

input.close();

Output:

The encrypted and decrypted files have been created successfully.

Result:
The DES program successfully encrypts and decrypts data using a 512-bit key and a Feistel network
structure, illustrating the principles of symmetric key cryptography. It showcases effective data
protection, while also highlighting vulnerabilities due to its relatively short key length in the context of
modern cryptographic standards.
Name: S.Matheswaran Reg.no:A13PCS008

Design DiffieHellman key Exchange process

Ex. No:6 Date:20.08.2024

Aim:

To implement the Diffie-Hellman key exchange protocol to enable secure key generation and sharing
over an insecure channel, demonstrating the principles of public key cryptography and the concept of
shared secret generation.

Coding:

package diffiehellman;

import java.math.BigInteger;

import java.security.SecureRandom;

public class DiffieHellman {

private static final int BIT_LENGTH = 512;

private static final SecureRandom random = new SecureRandom();

public static void main(String[] args) {

BigInteger P = BigInteger.probablePrime(BIT_LENGTH,random);

BigInteger G = new BigInteger(BIT_LENGTH,random).mod(P);

BigInteger a = new BigInteger(BIT_LENGTH,random).mod(P);

BigInteger A = G.modPow(a, P);

BigInteger b = new BigInteger(BIT_LENGTH,random).mod(P);

BigInteger B = G.modPow(b, P);

BigInteger SA = B.modPow(a, P);


BigInteger SB = A.modPow(b, P);

System.out.println("P (Prime Number) :"+P);

System.out.println("G (Primitive Root) :"+G);

System.out.println("Mathes Private Key (a) :"+a);

System.out.println("Mathes Public Key (A) :"+A);

System.out.println("Karuppu Private Key (b) :"+b);

System.out.println("Karuppu Public Key (B) :"+B);

System.out.println("Mathes Computed Shared Secret :"+SA);

System.out.println("Karuppu Computed Shared Secret :"+SB);

System.out.println("Shared Secret is Equals :"+SA.equals(SB));

Output:

P (Prime
Number) :9251286235985983310574457334147259434781711604346367716313683632446140068137
430634311305390488371052731062372401348019987079364921856945059440867579470869

G (Primitive
Root) :3217574186575186324075650600888175570783027953238455281666894954935814325273091
41588941041921506625346227321302437698479077458814518569606184497528494908

Mathes Private Key


(a) :394184298643480708206087530510370864363181415278124994439367345900990598539259897
7604926657783561190261139354181709592277148153700898978793412213333238458

Mathes Public Key


(A) :609166645632259613224184343746728807148631877810924177193278644994552208663725780
6849392662618772121036777777757662879566963847749529649734232273772187864

Karuppu Private Key


(b) :447773542173230314049863585544689851160543884325022335743146737319835548111835384
7824042638576748844072280938070514257550643714322046399273499960277717368
Karuppu Public Key
(B) :668566547869135529360762151466048717937783373313424637944942633993420348590495199
1321700876448757161602421214583877517232527948269440491084581639023140855

Mathes Computed Shared


Secret :1862799746649203083732804209236648108670882318890863105230997698882202744696411
822403323624326772086648128167164443316802601712421638190033787358760328863

Karuppu Computed Shared


Secret :1862799746649203083732804209236648108670882318890863105230997698882202744696411
822403323624326772086648128167164443316802601712421638190033787358760328863

Shared Secret is Equals :true

Result:

The Diffie-Hellman implementation successfully generates and shares a secret key between two parties
over an insecure channel, demonstrating the feasibility of secure key exchange.
Name: S.Matheswaran Reg.no:A13PCS008

Construction of a Digital Signature System for Authentication

Ex. No: 9 Date:13.09.2024

Aim:

To implement a digital signature scheme to verify the authenticity and integrity of messages,
demonstrating the principles of asymmetric cryptography and the use of hash functions in
creating secure digital signatures.

Coding:

package digitalsignature;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.SecureRandom;

import java.security.Signature;

import java.util.Scanner;

import javax.xml.bind.DatatypeConverter;

public class DigitalSignature {

private static final String SIGNING_ALGORITHM = "SHA256withRSA";

private static final String RSA = "RSA";

private static Scanner sc;

public static byte[] Create_Digital_Signature( byte[] input, PrivateKey Key) throws Exception

{
Signature signature = Signature.getInstance( SIGNING_ALGORITHM);

signature.initSign(Key);

signature.update(input);

return signature.sign();

public static KeyPair Generate_RSA_KeyPair() throws Exception

SecureRandom secureRandom = new SecureRandom();

KeyPairGenerator keyPairGenerator = KeyPairGenerator .getInstance(RSA);

keyPairGenerator .initialize( 2048, secureRandom);

return keyPairGenerator .generateKeyPair();

public static boolean Verify_Digital_Signature( byte[] input, byte[] signatureToVerify,


PublicKey key) throws Exception

Signature signature = Signature.getInstance( SIGNING_ALGORITHM);

signature.initVerify(key);

signature.update(input);

return signature .verify(signatureToVerify);

public static void main(String args[]) throws Exception

String input = "Mathes"+ " COMPUTER SCIENCE MSC(CS)";

KeyPair keyPair = Generate_RSA_KeyPair();


byte[] signature = Create_Digital_Signature( input.getBytes(), keyPair.getPrivate());

System.out.println( "Signature Value:\n "+


DatatypeConverter .printHexBinary(signature));

System.out.println( "Verification: "+ Verify_Digital_Signature( input.getBytes(), signature,


keyPair.getPublic()));

Output:

Signature Value:

667AF8CB9FFEBD447C77898318E6D607F4CE78654F70B987E5C98F10C6247B85358A3CE289B71
8295DCE441CB340E5DDE12CD751176C704A319089331353268DE4C8A9669C010C5E43B0BE100
D0C90CC6EA9E8BC266E80127F1BC38A6565792384D15EADFBF5026EE1F0D090C149E05B10EF5
B3B2C93D3A3DE6CFC26A36722DA1A0F739151A257329DBCF31FC1A14432E9D1A25BC0DAAB
5F70B6FD1E10FBF994FCA7A863A1C18B322EB3DC9BC9D31CBFD0FC7C7277CA57D2AC541991
41A92328E6D1601F1585C086EF5AB267C6E134312251018C4EAA7019D528472B9093EDF9B42FE4
879F9730D303BAEBE299C41B60C77E046CEF3C332AE0F84E7587500101

Verification: true

Result:

The digital signature program in Java effectively verifies document integrity and authenticity
using cryptographic hashing and private key signing.

4o mini
Name:S.Matheswaran Reg.no:A13PCS008

Develop RSA Algorithm

Ex. No: 7 Date:28.08.2024

Aim:

To implement the RSA algorithm for encrypting and decrypting messages, demonstrating the principles
of asymmetric cryptography and the use of large prime numbers for secure key generation.

Coding:

package rsa;

import java.math.BigInteger;

import java.security.SecureRandom;

public class RSA {

private static final int BIT_LENGTH = 2048; // Key length

private static final SecureRandom RANDOM = new SecureRandom();

private BigInteger publicKey;

private BigInteger privateKey;

private BigInteger modulus;

public RSA() {

BigInteger p = BigInteger.probablePrime(BIT_LENGTH / 2, RANDOM);

BigInteger q = BigInteger.probablePrime(BIT_LENGTH / 2, RANDOM);

modulus = p.multiply(q);

BigInteger phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));

publicKey = BigInteger.valueOf(65537); // Common choice for public exponent

privateKey = publicKey.modInverse(phi);}

public byte[] encrypt(byte[] message) {

BigInteger msg = new BigInteger(message);

return msg.modPow(publicKey, modulus).toByteArray(); }


public byte[] decrypt(byte[] encryptedMessage) {

BigInteger encryptedMsg = new BigInteger(encryptedMessage);

return encryptedMsg.modPow(privateKey, modulus).toByteArray(); }

public static void main(String[] args) {

RSA rsa = new RSA();

String originalMessage = "Hello, RSA!";

System.out.println("Original Message: " + originalMessage);

byte[] encryptedMessage = rsa.encrypt(originalMessage.getBytes());

System.out.println("Encrypted Message: " + new BigInteger(encryptedMessage).toString(16));

byte[] decryptedMessage = rsa.decrypt(encryptedMessage);

System.out.println("Decrypted Message: " + new String(decryptedMessage));}}

Output:

Original Message: Hello, RSA!

Encrypted Message:
41b6d5a18650713b0024eded4812edb114435814f1101b1dbd125e0221c60d3f83bfd3cba736e4ea05b1594
110b2f4c5ac3ec028e0e937ef11df6afe6689cd8941ec9343fdb735def286a67bc69d5317fb8f50206660cb50
19c97d07ee64ccf77b14e9bc1eddd5bce30d500edf02db1b81cdd0e2722c30e61eb69ca8f4a33752b5156bf4
6d4989aaf1c2c8df7cebe5968fd2637750da7284d986da687300a0cc8010c9abf31838dd0e2a1583dbddd94a
cc32bc01308eb5638c413d1b4bf7bef9d6c1862e532575345e3f2bfc67b724edaf018f2a05f1bb016f74d588a
4c6c972992d9261a678119ea992430b44c4c1c129de07e201dd08994f1ee5c69dbfefd7

Decrypted Message: Hello, RSA!

Result:

The RSA implementation successfully encrypts and decrypts messages using a pair of public and private
keys, illustrating the effectiveness of asymmetric cryptography. It highlights the robustness of RSA in
secure communications, while emphasizing the importance of key size and prime factorization for
maintaining security.

Name:S.Matheswaran Reg.no:A13PCS008
Computation of Hash values using SHA Algorithm

Ex. No:4 Date:00.00.2024

Aim:

To implement the SHA-256 hashing algorithm to generate a fixed-size hash value for input data,
demonstrating the principles of cryptographic hashing and its application in ensuring data integrity and
authenticity.

Coding:

package sha256;

import java.math.BigInteger;

import java.nio.charset.StandardCharsets;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

public class SHA256 {

public static byte[] getSHA(String input) throws NoSuchAlgorithmException

MessageDigest md = MessageDigest.getInstance("SHA-256");

return md.digest(input.getBytes(StandardCharsets.UTF_8));

public static String toHexString(byte[] hash)

BigInteger number = new BigInteger(1, hash);

StringBuilder hexString = new StringBuilder(number.toString(16));

while (hexString.length() < 64)

hexString.insert(0, '0');

}
return hexString.toString();

public static void main(String[] args) {try

System.out.println("HashCode Generated by SHA-256 for:");

String s1 = "Mathes";

System.out.println("\n" + s1 + " : " + toHexString(getSHA(s1)));

String s2 = "helloworld";

System.out.println("\n" + s2 + " : " + toHexString(getSHA(s2)));

String s3 = "sri kaliswari college";

System.out.println("\n" + s3 + " : " + toHexString(getSHA(s3)));}

catch (NoSuchAlgorithmException e) {

System.out.println("Exception thrown for incorrect algorithm: " + e);

}}}

Output:

Mathes : 4629cfeb13aca3658e4474f6f0eb93420dd5e5c3da7c1721ed36088db5d928db

helloworld : 936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af

sri kaliswari college : 3aa1dc3a7c69176cb0402ea5081b7e887b4f37fd9365b3a9ae367bb7b39ab56a

Result:

The SHA-256 implementation successfully generates a unique, fixed-size hash value for input
data, illustrating the effectiveness of cryptographic hashing in ensuring data integrity. It
highlights the algorithm's resistance to collisions and pre-image attacks, making it suitable for
secure data verification and digital signatures.

Name:S.Matheswaran Reg.no:A13PCS008
Apply Watermark Techniques in Digital Images

Ex. No:3 Date:00.00.2024

Aim:

To implement a digital watermarking technique for embedding information within digital media,
demonstrating methods for ensuring copyright protection and data authenticity while minimizing
perceptual impact on the original content.

Coding:

package watermarking;

import java.awt.Color;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

import javax.imageio.ImageIO;

public class WaterMarking {

public static void main(String[] args)

BufferedImage img = null;

File f = null;

try {

f = new File( "C:/Users/NOVELLA13PCS008/Pictures/807855.jpg");

img = ImageIO.read(f);

}
catch (IOException e) {

System.out.println(e);

BufferedImage temp = new BufferedImage( img.getWidth(), img.getHeight(),


BufferedImage.TYPE_INT_RGB);

Graphics graphics = temp.getGraphics();

graphics.drawImage(img, 0, 0, null);

graphics.setFont(new Font("Arial", Font.PLAIN, 80));

graphics.setColor(new Color(255, 0, 0, 40));

String watermark = "WaterMark generated";

graphics.drawString(watermark, img.getWidth() / 5,img.getHeight() / 3);

graphics.dispose();

f = new File( "C:/Users/NOVELLA13PCS008/Pictures/Watermark.jpg");

try {

ImageIO.write(temp, "png", f);

catch (IOException e) {

System.out.println(e);

Output:
Result:

The watermarking implementation successfully embeds information within digital media, effectively
demonstrating copyright protection and data authenticity. It preserves the perceptual quality of the
original content while providing a robust method for detecting unauthorized use or tampering.

You might also like