Configuring Security Policies and Digital Signatures in Java

Setting Up Policy Files to Grant Required Permissions

Create a policy file named exampleraypolicy using the Policy Tool to grant permissions to code from signed JAR files. The JAR must be signed with the private key corresponding to the public key imported into Ray's keystore (exampleraystore) under the alias susan. This grants code permission to read any file in the C:\TestData\ directory.

Starting the Policy Tool

Launch the Policy Tool by executing:

policytool

This opens the Policy Tool window. If no user policy file exists, it displays a blank window. Since tutorial modifications shouldn't affect your official user policy file, create a new policy file.

Specifying the Keystore

To specify the keystore, select Change Keystore from the Edit menu. Enter the keystore URL:

file:/C:/Test/exampleraystore

Leave the keystore type blank if using the default type.

Adding a Policy Entry with SignedBy Alias

Select Add Policy Entry and enter susan in the SignedBy field. Leave CodeBase empty to grant permisssions to all code signed by susan. To add the file read permission, click Add Permission, select File Permission, and specify the target as C:\TestData\* with read action.

Saving the Policy File

Save the new policy file as exampleraypolicy in the C:\Test directory using File > Save As.

Verifying Policy File Effectiveness

Execute the Count program with the policy file using either method:

Method 1: Command-line specification

java -Djava.security.manager -Djava.security.policy=exampleraypolicy -cp sCount.jar Count C:\TestData\data

Method 2: Security properties file modification Add the following line to java.security:

policy.url.3=file:/C:/Test/exampleraypolicy

Then run:

java -Djava.security.manager -cp sCount.jar Count C:\TestData\data

File Exchange with Digital Signatures

Sender Steps (Stan Smith)

  1. Create JAR containing contract:

    jar cvf Contract.jar contract
    
  2. Generate keys (if needed):

    keytool -genkey -alias signLegal -keystore examplestanstore
    
  3. Sign the JAR file:

    jarsigner -keystore examplestanstore -signedjar sContract.jar Contract.jar signLegal
    
  4. Export public key certificate:

    keytool -export -keystore examplestanstore -alias signLegal -file StanSmith.cer
    

Receiver Steps (Ruth)

  1. Import certificate as trusted:

    keytool -import -alias stan -file StanSmith.cer -keystore exampleruthstore
    
  2. Verify JAR signature:

    jarsigner -verify -verbose -keystore exampleruthstore sContract.jar
    

Generating and Verifying Digital Signatures

Signature Generation (GenSig)

import java.io.*;
import java.security.*;

class GenSig {
    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("Usage: GenSig filename");
            return;
        }
        
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
            keyGen.initialize(1024, random);
            
            KeyPair pair = keyGen.generateKeyPair();
            PrivateKey priv = pair.getPrivate();
            PublicKey pub = pair.getPublic();
            
            Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
            dsa.initSign(priv);
            
            FileInputStream fis = new FileInputStream(args[0]);
            BufferedInputStream bufin = new BufferedInputStream(fis);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = bufin.read(buffer)) >= 0) {
                dsa.update(buffer, 0, len);
            }
            bufin.close();
            
            byte[] sig = dsa.sign();
            
            FileOutputStream sigfos = new FileOutputStream("sig");
            sigfos.write(sig);
            sigfos.close();
            
            byte[] key = pub.getEncoded();
            FileOutputStream keyfos = new FileOutputStream("suepk");
            keyfos.write(key);
            keyfos.close();
            
        } catch (Exception e) {
            System.err.println("Error: " + e.toString());
        }
    }
}

Signature Verification (VerSig)

import java.io.*;
import java.security.*;
import java.security.spec.*;

class VerSig {
    public static void main(String[] args) {
        if (args.length != 3) {
            System.out.println("Usage: VerSig publickeyfile signaturefile datafile");
            return;
        }
        
        try {
            FileInputStream keyfis = new FileInputStream(args[0]);
            byte[] encKey = new byte[keyfis.available()];
            keyfis.read(encKey);
            keyfis.close();
            
            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
            KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");
            PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
            
            FileInputStream sigfis = new FileInputStream(args[1]);
            byte[] sigToVerify = new byte[sigfis.available()];
            sigfis.read(sigToVerify);
            sigfis.close();
            
            Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
            sig.initVerify(pubKey);
            
            FileInputStream datafis = new FileInputStream(args[2]);
            BufferedInputStream bufin = new BufferedInputStream(datafis);
            byte[] buffer = new byte[1024];
            int len;
            while (bufin.available() != 0) {
                len = bufin.read(buffer);
                sig.update(buffer, 0, len);
            }
            bufin.close();
            
            boolean verifies = sig.verify(sigToVerify);
            System.out.println("Signature verification: " + verifies);
            
        } catch (Exception e) {
            System.err.println("Error: " + e.toString());
        }
    }
}

Implementing Custom Permissions

ExampleGame Implementation

package com.gamedev.games;

import java.io.*;
import java.security.*;
import com.scoredev.scores.*;

public class ExampleGame {
    public static void main(String[] args) throws Exception {
        HighScore hs = new HighScore("ExampleGame");
        
        if (args.length == 0) usage();
        
        if (args[0].equals("set")) {
            hs.setHighScore(Integer.parseInt(args[1]));
        } else if (args[0].equals("get")) {
            System.out.println("Score = " + hs.getHighScore());
        } else {
            usage();
        }
    }
    
    private static void usage() {
        System.out.println("ExampleGame get");
        System.out.println("ExampleGame set <score>");
        System.exit(1);
    }
}

HighScore Class with Security Check

package com.scoredev.scores;

import java.io.*;
import java.security.*;

public class HighScore {
    private String gameName;
    
    public HighScore(String gameName) {
        this.gameName = gameName;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new HighScorePermission(gameName));
        }
    }
    
    public int getHighScore() {
        return AccessController.doPrivileged(
            new PrivilegedAction<Integer>() {
                public Integer run() {
                    try {
                        String home = System.getProperty("user.home");
                        File file = new File(home, ".highscore");
                        if (!file.exists()) return 0;
                        
                        BufferedReader reader = new BufferedReader(
                            new FileReader(file));
                        String line;
                        while ((line = reader.readLine()) != null) {
                            String[] parts = line.split("=");
                            if (parts[0].equals(gameName)) {
                                return Integer.parseInt(parts[1]);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return 0;
                }
            }
        );
    }
    
    public void setHighScore(final int score) {
        AccessController.doPrivileged(
            new PrivilegedAction<Void>() {
                public Void run() {
                    try {
                        String home = System.getProperty("user.home");
                        File file = new File(home, ".highscore");
                        
                        // Implementation to write score to file
                        // ...
                        
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                }
            }
        );
    }
}

Custom Permission Class

package com.scoredev.scores;

import java.security.BasicPermission;

public final class HighScorePermission extends BasicPermission {
    public HighScorePermission(String name) {
        super(name);
    }
    
    public HighScorePermission(String name, String actions) {
        super(name, actions);
    }
}

Java Extension Mechanism

Installed Extensions

Place JAR files in the JRE's lib/ext directory to make them available as installed extensions. For system-wide installation (Java 6+), use platform-specific directories:

  • Linux: /usr/java/packages/lib/ext
  • Windows: %SystemRoot%\Sun\Java\lib\ext
  • Solaris: /usr/jdk/packages/lib/ext

Download Extensions

Use Class-Path header in manifest to reference dependent JAR files:

Manifest-Version: 1.0
Class-Path: extension.jar

Service Provider Interface Example

// SPI Definition
package dictionary.spi;

public interface Dictionary {
    String getDefinition(String word);
}

// Service Implementation
package dictionary;

import dictionary.spi.Dictionary;
import java.util.ServiceLoader;

public class DictionaryService {
    private static DictionaryService instance;
    private ServiceLoader<Dictionary> loader;
    
    private DictionaryService() {
        loader = ServiceLoader.load(Dictionary.class);
    }
    
    public static synchronized DictionaryService getInstance() {
        if (instance == null) {
            instance = new DictionaryService();
        }
        return instance;
    }
    
    public String getDefinition(String word) {
        for (Dictionary dict : loader) {
            String definition = dict.getDefinition(word);
            if (definition != null) return definition;
        }
        return null;
    }
}

Register service providers by creating META-INF/services/dictionary.spi.Dictionary containing:

dictionary.GeneralDictionary

Tags: java Security policy digital-signature permissions

Posted on Fri, 15 May 2026 07:20:47 +0000 by litarena