Master Digital Signatures & Encryption Algorithms: Practical Guide with Code

This comprehensive guide explains digital signatures, encryption and decryption processes, symmetric and asymmetric cryptography, and compares common algorithms such as MD5, SHA‑1, HMAC, DES, 3DES, AES, RSA, and ECC, complete with Java code examples and usage scenarios.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Master Digital Signatures & Encryption Algorithms: Practical Guide with Code

1. Digital Signature

Digital signature is a method that provides verifiable digital information to confirm the identity of the sender. It uses a pair of complementary operations: signing with a private key held by the sender and verification with the corresponding public key held by the receiver.

The encryption process shown in the diagram differs from simple public‑key encryption. The fundamental purpose of a signature is to uniquely prove the sender’s identity and prevent man‑in‑the‑middle attacks, CSRF and other forgery.
Digital signature diagram
Digital signature diagram

2. Encryption and Decryption

2.1 Encryption

Encryption transforms clear‑text data into unreadable ciphertext using a specific algorithm, thereby protecting the data from unauthorized reading or theft.

2.2 Decryption

Decryption is the reverse process that converts the ciphertext back to its original clear‑text form.

3. Symmetric and Asymmetric Encryption

Encryption algorithms are divided into symmetric (same key for encryption and decryption) and asymmetric (different keys). Hash algorithms require no key.

3.1 Symmetric Encryption

Symmetric encryption, also called shared‑key encryption, uses a single secret key for both encryption and decryption. Both parties must know the key in advance.

Symmetric encryption illustration
Symmetric encryption illustration

Data encryption process: the sender combines the plaintext with the encryption key, processes it with the algorithm, and produces ciphertext for transmission.

Data decryption process: the receiver uses the same key and algorithm to recover the original plaintext from the ciphertext.

3.2 Asymmetric Encryption

Asymmetric encryption (public‑key encryption) uses a public key for encryption and a private key for decryption. The public key can be shared openly, while the private key must remain secret.

Example: Party A generates a key pair, publishes the public key, Party B encrypts confidential data with the public key, and A decrypts it with the private key.

4. Common Signature and Hash Algorithms

4.1 MD5

MD5 is a hash function that produces a 128‑bit digest. It is not an encryption algorithm but is used for integrity checking.

public static final byte[] computeMD5(byte[] content) {
    try {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        return md5.digest(content);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

4.2 SHA‑1

SHA‑1 is another hash algorithm that generates a 160‑bit digest, offering stronger security than MD5.

public static final byte[] computeSHA1(byte[] content) {
    try {
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        return sha1.digest(content);
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    }
}

4.3 HMAC

HMAC combines a hash algorithm (e.g., MD5, SHA‑1) with a secret key to produce a message authentication code, preventing tampering.

public class HMacHelper {
    private Mac mac;
    private static final String KEY_MAC = "HmacMD5";
    public HMacHelper(String key) {
        try {
            SecretKey secretKey = new SecretKeySpec(key.getBytes(ConstField.UTF8), KEY_MAC);
            mac = Mac.getInstance(secretKey.getAlgorithm());
            mac.init(secretKey);
        } catch (Exception e) {
            logger.error("create hmac helper failed.", e);
        }
    }
    public byte[] sign(byte[] content) {
        return mac.doFinal(content);
    }
    public boolean verify(byte[] signature, byte[] content) {
        try {
            return Arrays.equals(signature, mac.doFinal(content));
        } catch (Exception e) {
            logger.error("verify sig failed.", e);
            return false;
        }
    }
}

4.4 DES / 3DES / AES

DES is a block cipher with a 56‑bit key; 3DES applies DES three times with two or three keys; AES supports 128/192/256‑bit keys and is the modern standard for block encryption.

public class AesHelper {
    private SecretKeySpec keySpec;
    private IvParameterSpec iv;
    public AesHelper(byte[] aesKey, byte[] iv) {
        if (aesKey == null || aesKey.length < 16) {
            throw new RuntimeException("Invalid key");
        }
        if (iv == null) {
            iv = Md5Util.compute(aesKey);
        }
        keySpec = new SecretKeySpec(aesKey, "AES");
        this.iv = new IvParameterSpec(iv);
    }
    public byte[] encrypt(byte[] data) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public byte[] decrypt(byte[] secret) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            return cipher.doFinal(secret);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

4.5 RSA

RSA is a widely used public‑key algorithm for both encryption and digital signatures. It relies on the difficulty of factoring large prime products.

public class RsaHelper {
    private RSAPublicKey publicKey;
    private RSAPrivateCrtKey privateKey;
    public RsaHelper(byte[] publicKeyBytes, byte[] privateKeyBytes) {
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
            if (publicKeyBytes != null && publicKeyBytes.length > 0) {
                publicKey = (RSAPublicKey) kf.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
            }
            if (privateKeyBytes != null && privateKeyBytes.length > 0) {
                privateKey = (RSAPrivateCrtKey) kf.generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public byte[] encrypt(byte[] content) {
        if (publicKey == null) throw new RuntimeException("public key is null.");
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(content);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public byte[] decrypt(byte[] secret) {
        if (privateKey == null) throw new RuntimeException("private key is null.");
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(secret);
        } catch (Exception e) {
            logger.error("rsa decrypt failed.", e);
            return null;
        }
    }
    public byte[] sign(byte[] content) {
        if (privateKey == null) throw new RuntimeException("private key is null.");
        try {
            Signature sig = Signature.getInstance("SHA1WithRSA");
            sig.initSign(privateKey);
            sig.update(content);
            return sig.sign();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public boolean verify(byte[] signature, byte[] content) {
        if (publicKey == null) throw new RuntimeException("public key is null.");
        try {
            Signature sig = Signature.getInstance("SHA1WithRSA");
            sig.initVerify(publicKey);
            sig.update(content);
            return sig.verify(signature);
        } catch (Exception e) {
            logger.error("rsa verify failed.", e);
            return false;
        }
    }
}

4.6 ECC

Elliptic Curve Cryptography (ECC) provides comparable security to RSA with much smaller keys, though its operations are computationally heavier.

public class EccHelper {
    private BCECPublicKey publicKey;
    private BCECPrivateKey privateKey;
    public EccHelper(byte[] pub, byte[] pri) {
        try {
            KeyFactory kf = KeyFactory.getInstance("EC", "BC");
            if (pub != null && pub.length > 0) {
                publicKey = (BCECPublicKey) kf.generatePublic(new X509EncodedKeySpec(pub));
            }
            if (pri != null && pri.length > 0) {
                privateKey = (BCECPrivateKey) kf.generatePrivate(new PKCS8EncodedKeySpec(pri));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public byte[] encrypt(byte[] data) {
        if (publicKey == null) throw new RuntimeException("public key is null.");
        try {
            Cipher cipher = Cipher.getInstance("ECIES", "BC");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public byte[] decrypt(byte[] secret) {
        if (privateKey == null) throw new RuntimeException("private key is null.");
        try {
            Cipher cipher = Cipher.getInstance("ECIES", "BC");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(secret);
        } catch (Exception e) {
            logger.error("ecc decrypt failed.", e);
            return null;
        }
    }
    public byte[] sign(byte[] content) {
        if (privateKey == null) throw new RuntimeException("private key is null.");
        try {
            Signature sig = Signature.getInstance("SHA1withECDSA", "BC");
            sig.initSign(privateKey);
            sig.update(content);
            return sig.sign();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public boolean verify(byte[] signature, byte[] content) {
        if (publicKey == null) throw new RuntimeException("public key is null.");
        try {
            Signature sig = Signature.getInstance("SHA1withECDSA", "BC");
            sig.initVerify(publicKey);
            sig.update(content);
            return sig.verify(signature);
        } catch (Exception e) {
            logger.error("ecc verify failed.", e);
            return false;
        }
    }
}

5. Algorithm Comparison

Hash algorithms: SHA‑1 offers higher security but is slower; MD5 is faster but only medium security. Symmetric ciphers: DES (low security, moderate speed), 3DES (medium security, slower, higher resource use), AES (high security, fast, low resource use). Asymmetric ciphers: RSA has high maturity and security with moderate speed; ECC provides high security with smaller keys but slower performance and higher resource consumption.

Conclusion

The article introduced digital signatures, encryption/decryption, symmetric and asymmetric encryption, and provided detailed Java implementations for MD5, SHA‑1, HMAC, DES/AES, RSA, and ECC, along with practical usage notes and algorithm comparisons.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

encryptionhash algorithmscryptographyasymmetric encryptionsymmetric encryptionjava code
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.