Verifying a jar file

String className = jarName.substring0, jarName.length − 6; classArrays.putclassName, jarOut.toByteArray ; This returns the certificates from the signature file only if this class was signed. java.security.cert.Certificate c[] = je.getCertificates ; if c == null c = new java.security.cert.Certificate[0]; classIds.putclassName, c; } catch IOException ioe { System.out.printlnError reading entry + jarName; } } } Although its a long example, most of it simply deals with reading entries from the jar file. All that were left to do from a security perspective is obtain the array of signers when we read in each jar entry and then use that array of signers when we construct the code source we use to define the class. Remember that each file in a jar file may be signed by a different group of identities and that some may not be signed at all. This is why we must construct a new code source object for each signed class that was in the jar file.

12.3 Implementing a Signature Class

Now that weve seen how to use the Signature class, well look at how to implement our own class. The techniques well see here should be very familiar from our other examples of implementing an engine in the security provider architecture. In particular, since in Java 2 the Signature class extends its own SPI, we can implement a single class that extends the Signature class. To construct our subclass, we must use the following constructor: protected SignatureString algorithm This is the only constructor of the Signature class, so all subclasses of this class must use this constructor. The string passed to the constructor is the name that will be registered with the security provider. Once weve constructed our engine object, we must implement the following methods in it: protected abstract void engineInitVerifyPublicKey pk Initialize the object to prepare it to verify a digital signature. If the public key does not support the correct algorithm or is otherwise corrupted, an InvalidKeyException is thrown. protected abstract void engineInitSignPrivateKey pk Initialize the object to prepare it to create a digital signature. If the private key does not support the correct algorithm or is otherwise corrupted, an InvalidKeyException is thrown. protected abstract void engineUpdatebyte b protected abstract void engineUpdatebyte b[], int off, int len Add the given bytes to the data that is being accumulated for the signature. These methods are called by the update methods; they typically call the update method of a message digest held in the engine. If the engine has not been correctly initialized, a SignatureException is thrown. Chapter 12. Digital Signatures protected abstract byte[] engineSign protected int engineSignbyte[] outbuf, int offset, int len Create the signature based on the accumulated data. If there is an error in generating the signature, a SignatureException is thrown. protected abstract boolean engineVerifybyte b[] Return an indication of whether or not the given signature matches the expected signature of the accumulated data. If there is an error in validating the signature, a SignatureException is thrown. protected abstract void engineSetParameterString p, Object o [deprecated] protected abstract void engineSetParameterAlgorithmParameterSpec p Set the given parameters, which may be algorithm−specific. If this parameter does not apply to this algorithm, this method should throw an InvalidParameterException . protected abstract Object engineGetParameterString p [deprecated] Return the desired parameter, which is algorithm−specific. If the given parameter does not apply to this algorithm, this method should throw an InvalidParameterException . In addition to those methods, there are a few protected instance variables that keep track of the state of the signature object −− whether it has been initialized, whether it can be used to sign or to verify, and so on: protected final static int UNINITIALIZED protected final static int SIGN protected final static int VERIFY protected int state These variables control the internal state of signature object. The state is initially UNINITIALIZED ; it is set to SIGN by the initSign method and to VERIFY by the initVerify method. These variables are not normally used by the subclasses of Signature since the logic to maintain them is already implemented in the Signature class itself. Here is an implementation of a signature class. Note that the XYZSign class depends on other aspects of the security architecture −− in this example, the message digest engine to create an SHA message digest and the DSA key interfaces to handle the public and private keys. This is very typical of signature algorithms −− even to the point where the default name of the algorithm reflects the underlying components. The actual encryption of the message digest will use a simple XOR−based algorithm so that we can, as usual, avoid the mathematics involved with a secure example: package javasec.samples.ch12; import java.security.; import java.security.interfaces.; import java.security.spec.; public class XYZSignature extends Signature implements Cloneable { private DSAPublicKey pub; private DSAPrivateKey priv; private MessageDigest md; public XYZSignature throws NoSuchAlgorithmException { superXYZSignature;