Lecture note 6
Download
Report
Transcript Lecture note 6
MT311 Java Application
Development and Programming
Languages
Li Tak Sing (李德成)
Security
For Java applications, there are two main areas
of security issues:
1 system security
2 information security.
System security
System security refers to the safety and
stability of the computing environment. The
safety and stability can be breached in a
number of ways.
When a malicious application (such as a
virus) executes itself, it can cause damage to
the system — for example, by deleting some
critical files and rendering the computer
inoperable.
Information security
Or, the malicious application can intentionally
or unintentionally consume too many
resources, such as computing time, disk
space, or network bandwidth, thereby
causing the system to perform improperly.
Information security
Information security, however, refers to the
secrecy and integrity of data. For example,
when you send an email, how do you ensure
that only the targeted recipients can read the
message? When you receive an email, how
do you ensure that the message has not
been tampered with and that it is from the
supposed sender?
System security
In the security policy model, resources can
be granted or denied different types of
access independently. For example, a file
can be a resource, and the read action can
be differentiated from the write action. So,
you can easily grant read-only access to a
particular file. You can do the same with
objects, allowing you to create security
policies for runtime objects as well.
System security
Java makes things even more interesting by
allowing different policies to apply to different
applications, or to different invocations of the
same application.
Security policy
As you know by now, applets are small
applications that can be embedded in
webpages. When Java was first introduced,
applets were sensational because they
provided a cross-platform solution for making
a webpage more interesting. To safeguard
users from malicious applets, applets are run
in a sandbox, which imposes rather stringent
restrictions on what the applets can do.
Applet security
If you run an applet through a browser and
then the applet tries to read a local file, an
error message would appear.
Allowing an applet to access a
local file
To remove the restriction, we need to specify a
different policy. The format of the policy file is
quite simple, and you can create one using a
text editor. For example, below is a simple
file that grants rights for applets from
plbpc001.ouhk.edu.hk ‘.java.policy’:
Changing the policy
grant codeBase "http://plbpc001.ouhk.edu.hk/-"
{
permission java.security.AllPermission;
};
You should put this file in the "My Documents"
directory. As this would grant permission to
applets from the host to do everything, you
should remove this file after testing it.
Cryptography
Information security is save guarded by
cryptography.
Cryptography
Cryptography has four main objectives:
–
–
Confidentiality — the information cannot be
understood by anyone for whom it was not
intended.
Integrity — the information cannot be altered in
storage or transit between sender and intended
receiver without the alteration being detected.
Cryptography
–
–
Non-repudiation — the creator/sender of the
information cannot deny at a later stage his or her
intentions in the creation or transmission of the
information.
Authentication — the sender and receiver can
confirm each other’s identity and the
origin/destination of the information.
Secret Key method
In the secret key method, the sender and the
receiver share the same secret key. Then,
the sender first encrypts the message with
the key and sends the encrypted message to
the receiver who decrypts the message with
the same key.
Secret key
key
message
send over an
unsafe channel
encrypted
message
key
encrypted
message
message
Java secret key APIs
Java’s cryptographic APIs are defined in the
java.security and javax.crypto packages. For
a basic encryption, we need a secret key and
a cryptographic algorithm. The Java classes
for those are:
–
–
SecretKey — this class encapsulates the secret
key for use in encryption and decryption
Cipher — this class provides cryptographic APIs
for encryption and decryption.
Creating a secret key
The following code would create a secret key:
// the key itself as a byte array
byte[] key = new byte[] {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
// create a KeySpec specifically for DES for our key
DESKeySpec spec = new DESKeySpec(key);
// retrieve a DES SecretKeyFactory
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
// generate the actual SecretKey object
SecretKey secret = factory.generateSecret(spec);
Creating a cipher
To create a DES cipher, you first need to find a DES
algorithm provider using Cipher.getInstance:
Cipher c = Cipher.getInstance("DES");
The same Cipher object can be used for either
encryption or decryption, depending on how you
initialize the object:
– Encryption:
c.init(Cipher.ENCRYPT_MODE, secret);
– Decryption
c.init(Cipher.DECRYPT_MODE, secret);
To encrypt or decrypt a message
Now, with Cipher object, you can encrypt or
decrypt any bytes easily with:
c.update(byte[] buf);
You can invoke update as many times as
necessary to encrypt or decrypt the entire
message. To retrieve the encrypted or
decrypted result, you invoke the doFinal
method:
byte[] inEncrypted = c.doFinal();
Overall algorithm
To create a secret key
To create a cipher
Invoke the update method continuously until
the end of data
Invoke the doFinal method to get the final
result.
Conversion to or from byte[]
You should notice that all the cryptography
APIs work on byte[]. So no method what is
the format of your original message, you
must convert it to byte[].
Conversion to or from byte[]
To convert a String to byte[], you can use the
following method of String:
public byte[] getBytes()
To convert a byte[] to a String, you can use
the following constructor of String:
public String(byte[] bytes)
Encryption
The following method would encrypt a
message:
static byte[] encrypt(String st, Cipher c) {
c.update(st.getBytes());
return c.doFinal();
}
Decryption
The following method would decrypt a
message:
public static String decrypt(byte[] message,
Cipher c) {
c.update(message);
byte[] result=c.doFinal();
return new String(result);
}
Message digest
The above method would only be able to
protect the confidentiality of the message. It
cannot protect the integrity of the message
because the receiver would not know
whether the message has been altered in
any way.
To protect the integrity, we need the
message digest.
Hash function
A message digest, typically of fixed length, is
generated using a special mathematical
transformation called a hash function. A hash
function is basically a transformation that
takes any arbitrary input and produces an
output in a finite space.
Hash function
For message digests, we need a hash
function that has two properties:
–
–
It must be extremely difficult to produce the same
message digest from two different messages, i.e.
the hash must be one-to-one.
It must be extremely difficult to produce the
original message from a given message digest,
i.e. the hash must be irreversible.
Message digest
Message digest alone cannot be used to
protect the integrity of message. This is
because anyone can use the same hash
function to protect a message digest of an
altered message.
So the secret key method must be used
together with the message digest.
Secret key method with message
digest
message digest
message digest
produce
sent over
unsafe
channel
key
compare
key
message
message
encrypted message
encrypted message
Message digest
The creation of a MessageDigest is similar to that of
Cipher, using getInstance:
MessageDigest md =
MessageDigest.getInstance("MD5");
Once you have a MessageDigest object, you can
feed data to it using the update method:
md.update(inbuf);
Finally, you can retrieve the final hash using the
digest method:
md.digest();
Message digest
The following method generate the message
digest of a String:
public static byte[] md(String st) {
MessageDigest md =
MessageDigest.getInstance("MD5");
md.update(st.getBytes());
return md.digest();
}
Compare two byte[]
Since message digests are in the format of
byte[], we need to compare two byte[]'s. you
should use a for loop to compare two byte[]'s.
Message Authentication Code
(MAC)
As we have mentioned earlier, we cannot
use the message digest alone to guarantee
the integrity of a message. We need to add
a secret key protection so that the resulting
string would also depends on the secret key.
Such an encrypted message digest is called
a message authentication code(MAC).
MAC protects the authentication and integrity
of a message.
MAC
When a user want to send a message, it would use
the secret key to produce a MAC of the message.
Then he/she sends the message and the MAC to the
receiver. The receiver would then use the same
secret key and the message to generate another
MAC. The two MACs would then be compared. If
they are the same, then the message is really from
the supposed sender and the message has not been
messed with by others.
message
keyed hash
message
keyed
hash
MAC
send to the recipient
compare
MAC
MAC
MAC
The followings are the steps to create an
MAC of a message:
–
–
–
–
–
create a secret key
create an Mac object
initialize the Mac object with the key
update the Mac object with the contents of the
message
get the MAC from the Mac object.
Create a secret key
KeyGenerator kg =
KeyGenerator.getInstance("HmacMD5");
SecretKey sk = kg.generateKey();
Note that the key is randomly generated. So
different key would be generated if the
generateKey is invoked for many times. So if
you want to share this key, you need to save
the key to a file and then share the file.
Create an Mac object
Mac mac = Mac.getInstance("HmacMD5");
Initialize the Mac object with the
key
mac.init(sk);
update the Mac object with the
contents of the message
mac.update(buf);
where buf is an array of bytes. You can call
this method as many times as you wish.
get the MAC from the Mac object.
byte[] result=mac.doFinal();
The MD5 program
KeyGenerator kg =
KeyGenerator.getInstance("HmacMD5");
SecretKey sk = kg.generateKey();
Mac mac = Mac.getInstance("HmacMD5");
mac.init(sk);
mac.update(buf);
byte[] result=mac.doFinal();
Public key method
In the secret key method, there is a problem
in distributing the key because both the
sender and recipient need to have the same
key.
It is possible that the key is intercepted when
it is transmitted from one person to another.
Public key method
The public key method, you need a pair of
keys to perform the encryption and
decryption process. The two keys are called
public key and private key. You cannot
deduce the private key from the public key.
When a message is encrypted with the public
key, it must be decrypted with the private key.
When a message is decrypted with the
private key, it must be decrypted with the
public key.
Public key methods
A user first generates a key pair that consists
of a public key and private key. He/she now
informs others about the public key. Then
anybody can now encrypt a message with
the public key and send the encrypted
message to the user. Now, the user can
decrypt the message with the private key.
Public key methods
Note that the public key does not have to be
send over a secured channel because any
one who knows the public key would still not
be able to decrypt any message that has
been encrypted with the public key.
The method protects the confidentiality of the
message.
Java classes for the public key
methods
Most java classes for the public key methods
are in the package java.security.
KeyPairGenerator
–
the static method
static public KeyPairGenerator getInstance(String)
would return a KeyPairGenerator with the
specified method. The most popular method is
RSA. So the following statement get a RSA
public key generator:
encrypted
with public
encrypted
key
message
decrypted
with private
encrypted key
original
message
message
encrypted
with private
original key
encrypted
message
message
decrypted
with public
encrypted key
original
message
message
original
message
Java classes for the public key
methods
KeyPairGenerator generator=KeyPairGenerator("RSA");
The following method of KeyPairGenerator
would initial the KeyPairGenerator to
generate a key of the specified byte length:
public void initialize(int length)
For example, the following statement would
initialize a KeyPairGenerator to generate a
key of size 2048 bits long:
generator.initialize(2048);
Java classes for the public key
methods
The following statement create a key pair:
KeyPair key=generator.generateKeyPair();
The following statement finds the public key:
PublicKey publicKey=key.getPublic();
The following statement finds the private key:
Privatekey privatekey=key.getPrivate();
Java classes for the public key
methods
After obtaining the key pair, we can use
Cipher to encode or decode a message like
what we have done in the secret key
algorithm.
The following statement initializes a Cipher to
be used to encrypt a message using the
private key:
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,
key.getPrivate());
Java classes for the public key
methods
The following statement initializes a Cipher to
be used to encrypt a message using the
public key:
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE,
key.getPublic());
Java classes for the public key
methods
The following statement initializes a Cipher to
be used to decrypt a message using the
private key:
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,
key.getPivate());
Java classes for the public key
methods
The following statement initializes a Cipher to
be used to decrypt a message using the
public key:
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE,
key.getPublic());
Java classes for the public key
methods
Then, we can use the update and doFinal
method Cipher to encrypt or decrypt the
message.
If the message is short, we can simply use
the doFinal straight away to decrypt the
message.
Digital signature
When you receive a message from a person,
how do you be sure that the message is
really from that person? This can be done by
using digital signature.
Digital signature
A digital signature is like a MAC but the key
used is the private key of the key pair.
To produce a digital signature, we first create
a message digest and then encrypt the
message digest with the private key of the
message. We would say that we sign the
message with the private key.
Digital signature
Then, the sender would send the message
together with the digital signature.
The receiver would then first use the public
key of the sender to decrypt the digital
signature and then get back the message
digest. The receiver then calculate another
message digest from the message.
Digital signature
If the two digital digests match, then we can
sure of two things:
–
–
integrity. That is the message has not been
changed by another person.
authentication. The message is really from the
supposed sender because only he/she has the
private key.
message
hash
message
digital
digest
encrypt signature
with
private
key
message
send to
the recipient
hash
message
digest
compare
digital
signature
decrypt
with
public
key
message
digest
Java classes to create a digital
signature
First we create a key pair first like what we did
for the public key method. However, we
would specify that we want to use the DSA
algorithm which is a digital signature
algorithm:
KeyPairGenerator kpg =
KeyPairGenerator.getInstance("DSA");
Java classes to create a digital
signature
Then, we initialize the key as before:
kpg.initialize(1024);
Then, we can use this key pair generator to
generate a key pair:
KeyPair keyPair=kpg.generateKeyPair();
Java classes to create a digital
signature
We can then get the public key and private
key of the key pair:
PublicKey publicKey=keyPair.getPublic();
PrivateKey privateKey=keyPair.getPrivate();
You should then save the two keys to a files
and send the public key to your recipients.
Java classes to create a digital
signature
Now, assume that we want to create a digital
signature of a message.
Signature sig=Signature.getInstance("DSA");
sig.initSign(privateKey);
Then, you can use the update method of
Signature to check the contents of the
message:
sig.update(message);
Java classes to create a digital
signature
The digital signature is generated by invoked
by the method sign:
sig.sign();
This method returns an array of bytes which
is the digital signature of the message.
To verify a signature, we need the following
statements:
Signature sig=Signature.getInstance("DSA");
sig.initVerify(publicKey);
Java classes to create a digital
signature
Then, we use the update method of
signature to put in the content of the
message just like what we did when we
generated the digitial message.
sig.update(message);
Java classes to create a digital
signature
Then, we can check whether the message
has been correctly signed by invoking the
method verify of Signature:
sig.verify();
This method would return true or false
depending on whether the message has
been correctly signed or not.