- Example Programs and crypttool
- Cryptographic Services and Providers
- Cryptographic Keys
- Encryption and Decryption
- Message Digest
- Message Authentication Code
- Digital Signature
- Key Agreement
- Summary of Cryptographic Operations
- Cryptography with crypttool
- Limited versus Unlimited Cryptography
- Performance of Cryptographic Operations
- Practical Applications
- Legal Issues with Cryptography
- Summary
- Further Reading
Digital Signature
Encrypting the digest of a message with the private key using asymmetric cryptography creates the digital signature of the person or entity known to own the private key. Anyone with the corresponding public key can decrypt the signature to get the message digest and verify that the message digest indeed corresponds to the original message and be confident that it must have been encrypted with the private key corresponding to the public key. As the private key is not made public, it can be deduced that the message was signed by the owner of the private key. Generally, these are the same properties as the ones associated with a signature on paper.
Note that use of a digital signature requires a digest algorithm and an asymmetric encryption algorithm.
Algorithms
Currently, there are three FIPS-approved digital signature algorithms: DSA, RSA and ECDSA (Elliptic Curve Digital Signature Algorithm). More information on these algorithms can be found at http://csrc.nist.gov/CryptoToolkit/tkhash.html.
Java API
Java class java.security.Signature represents the signature service and has methods to create and verify a signature. Like any engine class, a concrete Signature object is created by invoking the static method getInstance(). For signing data bytes, it must be initialized using initSign() with the private key as an argument. A subsequent signature creation operated, through the method sign(), produces the signature bytes. Similarly, the verification operation, through the method verify(), after initialization using initVerify() with the public key as the argument, verifies whether a particular signature has been created using the corresponding private key or not.
The example program SignatureTest.java illustrates signing and verification.
Listing 3-9. Signature creation and verification
// File: src\jsbook\ch3\ex1\SignatureTest.java import java.security.KeyPairGenerator; import java.security.KeyPair; import java.security.PublicKey; import java.security.PrivateKey; import java.security.Signature; import java.io.FileInputStream; public class SignatureTest { private static byte[] sign(String datafile, PrivateKey prvKey, String sigAlg) throws Exception { Signature sig = Signature.getInstance(sigAlg); sig.initSign(prvKey); FileInputStream fis = new FileInputStream(datafile); byte[] dataBytes = new byte[1024]; int nread = fis.read(dataBytes); while (nread > 0) { sig.update(dataBytes, 0, nread); nread = fis.read(dataBytes); }; return sig.sign(); } private static boolean verify(String datafile, PublicKey pubKey, String sigAlg, byte[] sigbytes) throws Exception { Signature sig = Signature.getInstance(sigAlg); sig.initVerify(pubKey); FileInputStream fis = new FileInputStream(datafile); byte[] dataBytes = new byte[1024]; int nread = fis.read(dataBytes); while (nread > 0) { sig.update(dataBytes, 0, nread); nread = fis.read(dataBytes); }; return sig.verify(sigbytes); } public static void main(String[] unused) throws Exception { // Generate a key-pair KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); kpg.initialize(512); // 512 is the keysize. KeyPair kp = kpg.generateKeyPair(); PublicKey pubk = kp.getPublic(); PrivateKey prvk = kp.getPrivate(); String datafile = "SignatureTest.java"; byte[] sigbytes = sign(datafile, prvk, "SHAwithDSA"); System.out.println("Signature(in hex):: " + Util.byteArray2Hex(sigbytes)); boolean result = verify(datafile, pubk, "SHAwithDSA", sigbytes); System.out.println("Signature Verification Result = " + result); } }
Besides SHAwithDSA, the J2SE bundled providers support SHA1withRSA, MD5withRSA and MD2with RSA signature algorithms.