references: 'Java Developer's
Handbook' Heller&Roberts, 'Just Java' P.Van der Linden
The JDK1.2.2 API documentation
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. |
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.
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
m -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
s -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