Java Security                                                   P.Komisar

references: 'Java Developer's Handbook' Heller&Roberts, 'Just Java' P.Van der Linden
                     The JDK1.2.2 API documentation



You know a book is significant when it is cross recommended by several different authors
as is Bruce Schneier's book,

Applied Cryptography: Protocols, Algorithms, and Source Code in C
2nd Edition John Wiley & Sons; ISBN: 0471117099
 
The JDK Security API is a core API of the Java programming language, built around the java.security package The first release of JDK Security in JDK 1.1 introduced the Java Cryptography Architecture (JCA), which refers to a framework for accessing and developing cryptographic functionality for the Java platform. JDK 1.2 significantly extends the Java Cryptography Architecture The Java Cryptography Extension (JCE) extends the JCA API to include APIs for encryption, key exchange, and Message Authentication Code (MAC). Together, the JCE and the cryptography aspects of the JDK provide a complete, platform-independent cryptography API.



Vernacular

Security distills to access control

Access is based on identification and authentication. A unique identifier describes a real
person and authentication says you are that real person. For example, you have a user name
(identifier) and a password (authenticator). A password or pin number is weak authentication
compared to say a photograph of an individual, a retina scan or a DNA sample.

To associate an identity with a (paper) document a signature is used. Electronically, a digital
signature is used. (A digital signature is produced by validation code which anyone can check
but only one person can generate). In reverse, actions performed against these identifiers can be
legally bound to the described individual. This concept, called nonrepudiation, is neccessary for
accountability in electronic commerce transactions. Messages including the public key of a
trusted intermediary, (like a certification authority) are called certificates.
Granting permissions to access computer resources is called authorization.The mechanism
preventing  unauthorized access to resources is called resource control. Resource control is
most critical as other security measures are only as safe as the mechanism protecting them from
unauthorized modification.

Access control is important to prevent 1) unauthorizied tampering and  2) secrecy.

Code tags created using mathematically techniques can be associated with files to signal whether
the file has been tampered with or accidently corrupted. This insures data integrity

1) checksums       //weakest
2) CRC's (cyclic redundancy checks)
3) message digests    //strongest

Secrecy is ensured using encryption. Encryption is reversibly hiding data information by a
mathematical scheme. Encryption uses publicly know algorithms for changing original data
into secret, cipher-text. Secret, numbers called keys, uniquely modify the algorithms
processes. // here security must be considered for the keys
 
encryption note


An interesting example of encryption was the use of Navaho soldiers by the Americans during the Second World War. The personel would  translate messages into a version of their language which was made even more cryptic by the translators. (Other Navaho personel when asked didn't know what they were talking about). The code was never cracked and was classified as a military secret until declassification in the 1960's. //sorry have misplaced the reference to this interesting article

One or Two Keys

1) secret-key or symmetric cipher is a single key, (or two so similar as to be thought of as one),
    used for encryption and decryption.
     // the key becomes the security issue, and getting it to the intended partner
2) public-key cryptography or asymmetric cryptography use different keys, one public and
    one private to encrypt and decrypt data. The mathematical relationship to derive one key from
    the other is so time consuming as to be considered impossible to solve. One key can be made
    public while the other is for the private use of the originator of the key pair. Anyone wishing, can
    use the public key to encrypt a message to the holder of the private key. The private key holder
    decrypts the message using his or her, private key.

Digital signatures

Digital signatures employ the asymmetric key relationship in reverse. The private key of the
originator binds sender's identity to a message. Since the public keys are used to decrypt
the message, there is no secrecy however the source of the mesage is effectively signed digitally.
// security concerns turn to the safe-keeping of the private key.

Auditing, keeping track of system transactions, usually on a removable storage medium, is costly
but a good additional security.     // The auditing system can be tampered with


Conventional Operating System Control

Most modern operating systems have MMU's, memory management units, which prevents
one process from having access to the memory allocated to another. Only the pseudo-user,
kernel mode, has access to the MMU. Software interupts cause the invocation of kernel mode.
Software interupts create pointers in a special area of memory protected and supervised by the
MMU. So most OS' have what is called a defensive circle of memory management.

1) This defence provides no controls on how memory is used within processes.
     // Java's strict memory allocation limits bugs
2) There is no defense against executing potentially hostile, untrusted code.
     // Java's security model does not allow untrusted code to run


Java Security

The JVM Instruction Set  // The interpreter/native interface provides a security checkpoint

JVM instructions do not address memory directly and has no IO instructions and only refers
to memory in a symbolic way. ( i.e getfield # 2< Field int z > the 2nd entry in a symbol table
describes an int called x ) This allows the possibility of checking if the described field meets the
strict criteria for that type.

The Bytecode Verifier     // Code is scrutinized for correctness before execution

When a class is executed, first it is loaded, it's main( ) method is called and supplemental
classes are loaded. Then verification takes place. During four passes, verification includes

a) checking for the java class file, magic number ( 0xCAFEBABE ),
b) outside code details are checked (like checking for needed superclasses),
c) bytecode verification of opcode  (i.e. method arguments and returns are correct and legal)
d) a delayed verification on methods when called. (only if the given method is called )
 
 
Rule of thumb


Local code is trusted (that accessible via CLASSPATH), while that loaded from the net is not. This describes the default setting for verification. Manual controls of verification in jdk 1.2  are -Xverify:remote (default verifies net loaded classes), -Xverify:all, -Xverfy:none 
[jdk 11 commands are similar but drop the X and the colon]

SecurityManager     // Given safe code, the security manager regulates access to resources

Given code that has been proven correct, the SecurityManagerchecks to see if calls to
protected resources are acceptable at runtime. The security manager can veto the loading
of underlying machine libraries containing native methods needed for direct memory access
and IO. To work these must be linked to the symbol tables of the calling java classes. If the
calling classes don't have permission to use the requested resource, the SecurityManager will
skip loading the native functions and issue a SecurityException. To help decide if a call should
be permitted the security manager has access to the stack frames of the calling thread. The
SecurityManager allows the creation of a security policy allowing or restricting privileges
to a java program (i.e browser's default manager restricts applets loaded over a network from
reading and writing to file.)

Class Loaders
// controls remotely loaded code, checks and controls class name spaces and accounts for the class'
presence within the system      // provides security at the class name level

Loading and verification are the responsibility of the ClassLoader class. // in java.lang package
Additional security duties of the ClassLoader class are:

1) ClassLoader will not attempt to load java.* packages from over the net.
    //secures against hostile java class impersonators
2) Provides seperate name spaces for classes loaded from different locations, preventing name
     clashes    // secures against  unauthorized communication between classes inside the JVM
3) Check class names are not illegal  // have leading dots which might force a local class load
4) Ensures local classes are loaded over remote // insures local code isn't usurped by remote
5) Ensures loaded classes are cached and accounted for.         // prevents twice loading static members

ClassLoader is an abstract class with a single abstract method that needs to be overridden.

protected abstract Class loadClass ( String name, boolean resolve )
throws ClassNotFoundException

If you were creating your own ClassLoader, loadClass( ) would have to be implemented to satify
the following conditions;

1) Find if class is loaded (using findLoadedClass( ) andfindSystemClass( ) )
2) load class data from wherever into a byte array
3) call defineClass( ) to convert the bytes into the class
4) resolveClass( ) resolves the class so that an instance of the class can be created, or so that
    one of its methods can be called. The method is called by loadClass if the resolve flag is true.
5) return the newly created class
 
 JDK 1.1.7's description of classLoader( ) method


 Requests the class loader to load and resolve a class with the specified name. The loadClass method is called by the Java Virtual Machine when a class loaded by a class loader first references another class. Every subclass of class ClassLoader must define this method. Class loaders should use a hashtable or other cache to avoid defining classes with the same name multiple times.

Runtime checks

After class loading, runtime checking is Java's next line of defense. Because of late binding,
runtime type checking is done on assignments and array bounds. (A subclass can be accessed
as a superclass but not the reverse)
// this assures a type Object is not passed as a String to gain unexpected access.
In other languages attempting array accesses outside array bounds will cause memory to be
surrendered. Java restricts this behaviour making it illegal.

The security arrangement between the bytecode verifier, the security manager and the class
loaders is a circular one. If one part of the system is breached, the whole system fails.


JDK 1.2 Security Model

There can only be one Security Manager per JVM. // prevents replacement  by a hostile version.
In JDK 1.1, to change security policy a whole new SecurityManager class had to be written.
Also many calls to SecurityManager were difficult to understand. In JDK1.2, changes can be
made to security policy without changing or adding code. JDK 1.2 security relies on an internal
AccessController.The model has been extended to make all classes subject to permission
checks, local and remote.
 
 public final class AccessController extends Object      // from the jdk documetation


The AccessController class is used for three purposes: 
 ( i)    to decide whether an access to a critical system resource is to be allowed or denied, based
           on the security policy currently in effect,
 (ii)    to mark code as being "privileged", thus affecting subsequent access determinations, and
 (iii)   to obtain a "snapshot" of the current calling context so access-control decisions from a
            different context can be made with respect to the saved context. 
.

Permissions

The units of the security system are subclasses of java.security.Permission. Specific subclasses
represent permissions for particular operations. For example,

.java.io.FilePermission  // describes file access taking two String arguments, name and action.

FilePermission fp = new FilePermission( "/password", "read" ); // permits reading password file

// when a privileged operation is attempted, a permissions database is checked against the source
// of the requesting code

The Policy File

The database containing the Permissions objects is known as the policy. It is loaded by the
runtime from a text file called java.security in jre\ lib\ security. It contains a line

policy.java = java.policy

causing the loading of the security policy from the text file. Additional permissions are loaded
into policy with a file stored in the user's home directory called .java.policy//multi-user mode
// In windows this is the user.home property

Granting Permissions

Protection domain is the set of all classes loaded from same source (same signers).

 grant signedBy  "Izzie" , codeBase  "http://Bizzie.com/"  {
    permission java.io.FilePermission  "/ ToolsForSale / * ", "read";
    };

// code signed by Izzie loaded from beneath base http://Bizzie.con/  is granted permission to
// read any file in ToolsForSale directory.
// can specify multiple users, (comma seperated) and multiple permission lines.

The Policy Tool

simplifies editing the policy file (over doing it manually)

1) add a new grant, select Add Permission button.(see invite to sign and enter codebase)
2) click Add  to add a new permission
3) Select

Permission    (class of the Permission)                  // select first as it effects following fields
TargetName (enter yourself)                              // may be pre-existing settings
Actions          (action you want enabled)               // i.e. ''read"
Signed By     (allows you to require validation for the Permission class)

The mew model allows privileges to be extended to signed code. The alias used to describe
the signing entity must be stored, along with it's associated public key, in the policy database
defined in the file  lib/security/java.security. The default entry is

keystore = sun.security.tools.JavaKeyStore

JavaKeyStore and associated classes implement the permanent storage of keys in a file called
.keystore which is kept in the user's home directory.  // storing the .keystore file is a security risk

// Consider the security of the original file distribution of the JDK and it's subsequent storage

Creating Keys

To create keys use the -genkey option of the keytool utility. (Other options can be used to encrypt
keys with other algorithms) You will be prompted for a password and personal information (name,
Co., local) Leave unknown if certificate isn't needed
//As stated above .keystore must be protected as it is weakly encrypted as per U.S. export laws
A self-signed certificate is created. The signature indicates there was no accidental corruption.

Getting a certificate signed

To have a certificate signed by an authority, a certificate-signing request must be made, using
keytool with the -csr option. An encrypted 7-bit ASCII, certificate-signing request results
that can be mailed to a certification authority like 'Verisign' who have procedures to validate the
request is really yours. (Demonstration certificate with short expirary dates are available for
experimentation.)

Importing a Certificate

A certificate is imported and stored in the keystore for later use by using -impt and -file options of
keytool along with the destination file.  For example

keytool -import -file \temp\cert1

After this command your alias will refer to this certificate rather than the self-signed one.



Warning: JDK 1.2 only supports DSA signatures. Most certification authorities support the
RSA/SHA standard. Import a security package like Cryptix (www.systemics.com/docs/cryptix)
to add the RSA/SHA standard.

Exporting a Certificate

Use the -export option of keytool. Another 7-bit ASCII block is generated which interested parties
can put in their key databases.

Signing a JAR File

Sign a jar using the jarsigner tool in JDK 1.2. (1.1 used javakey). With a private key in your
keystore, issue the command

jarsigner  <archive.jar>  <alias>

// a prompt will occure for keystore and alias passwords

Verifying a JAR File

Generally, the signature of the JAR file is read and verified by a class loader.
It can be verified manually with the command

jarsigner -verify -verbose < archive.jar >

-a list of files is output, the left-column containing letter prefixes, m, s and/or k describing the
associated file

-a file listed on the manifest (only files in the META-INF directory are not on manifest)
     -may not be on manifest if a ZIP variant
-indicates the file is signed                  // though signed it may not match your keys
k  -the file has a signature matching one in your keystore

-last output is jar verified which says the archive is not corrupted
-leaving out -verbose reduces output to jar verified and omits the list labelled m s and/or k

Sealing Packages in JAR Files

To specify a package in a jar may not be added to by classes from other jars, the jar file should
be signed and sealed. The manifest file, (META-INF/MANIFEST.MF), specifies sealing in
two ways.

1) Indicate all the packages are sealed with the entry

    Archive-Sealed: true     // or

2) Associate a seal with a specific package

    Name: theDay/Sunday/
    Package-Sealed: true

The boolean type tag can be used in reverse to unseal