Material zum Praktikumsversuch Grundpraktikum zur IT

Transcrição

Material zum Praktikumsversuch Grundpraktikum zur IT
Material zum Praktikumsversuch
Stand: 22. Dezember 2007,
zusammengestellt von: Lijun Liao (Lehrstuhl NDS)
Version 1.3
Grundpraktikum zur IT-Sicherheit
Automatisierte Bearbeitung von sicheren
E-Mails
Lehrstuhl für
Netz- und Datensicherheit
Ruhr-Universität Bochum
Bitte beachten Sie, dass dieser Versuch im Raum IC4/58 stattfindet.
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
1
1 Organisation
1.1 Erforderliche Vorkenntnisse zur Teilnahme an diesem Versuch
●
●
●
●
●
Vorlesung Kryptographie und Datensicherheit, Prof. Paar.
Struktur von Zertifikaten nach X.509.
Auszug „Sichere E-Mail“ aus Jörg Schwenk: Sicherheit und Kryptographie im Internet,
Vieweg-Verlag 2002 (in Abschnitt 2 auszugsweise abgedruckt).
Abschnitt „Using Mail/Signing & Encrypting Messages“ aus Mozilla Help lesen.
Java-Grundkenntnisse
1.2 Kontrollfragen
Eingangstestat: Sie sollten folgende Fragen beantworten können (bevor der Versuch beginnt):
Warum wurde MIME eingeführt?
● Was ist Javamail?
● Was ist BoucyCastle S/MIME Packet?
● Kann BouncyCastle S/MIME Packet ohne Javamail benutzt werden?
● Welche Vorbereitungen müssen Sie treffen, um eine E-Mail an Empfänger A
verschlüsseln zu können?
● Welche Vorbereitungen müssen Sie treffen, um eine E-Mail signieren zu können?
● Welche Überprüfungen sollen durchgeführt werden, um die Signatur einer signierten EMail zu verifizieren?
1.3 Auswertungen
● Schriftliche Versuchsauswertung
Jedes Team fertigt eine schriftliche Auswertung an. Beantworten Sie darin die Fragen,
die zu den jeweiligen Teilversuchen gestellt wurden. Die Versuchsauswertung ist
schriftlich beim nächsten Termin mitzubringen.
●
Erzeugte E-Mails und der Quellcode
Die in diesem Versuch generierten E-Mails und der Quellcode sind per E-Mail bis zum
nächsten Termin an den Betreuer Lijun Liao abzugeben.
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
2
2 Bearbeitung von sicheren E-Mails
2.1 Sichere E-Mails
Bitte den Kapitel 2 der Versuchsbeschreibung S/MIME lesen.
2.2 Javamail
Aus http://java.sun.com/developer/onlineTraining/JavaMail/contents.html
2.2.1 Introduction
The JavaMail API [1] is an optional package (standard extension) for reading, composing, and
sending electronic messages. You use the package to create Mail User Agent (MUA) type
programs, similar to Eudora, Pine, and Microsoft Outlook. Its main purpose is not for
transporting, delivering, and forwarding messages like sendmail or other Mail Transfer Agent
(MTA) type programs. In other words, users interact with MUA-type programs to read and
write emails. MUAs rely on MTAs to handle the actual delivery.
2.2.2 Session
The Session class defines a basic mail session. It is through this session that everything else
works. The Session object takes advantage of a java.util.Properties object to get
information like mail server, username, password, and other information that can be shared
across your entire application.
The constructors for the class are private. You can get a single default session that can be shared
with the getDefaultInstance() method:
Properties props = new Properties();
// fill props with any information
Session session = Session.getDefaultInstance(props, null);
Or, you can create a unique session with getInstance():
Properties props = new Properties();
// fill props with any information
Session session = Session.getInstance(props, null);
In both cases here the null argument is an Authenticator object which is not being used
at this time. More on Authenticator shortly.
In most cases, it is sufficient to use the shared session, even if working with mail sessions for
multiple user mailboxes. You can add the username and password combination in at a later step
in the communication process, keeping everything separate.
2.2.3 Message
Once you have your Session object, it is time to move on to creating the message to send.
This is done with a type of Message. Being an abstract class, you must work with a subclass,
in most cases javax.mail.internet.MimeMessage. A MimeMessage is a email
message that understands MIME types and headers, as defined in the different RFCs. Message
headers are restricted to US-ASCII characters only, though non-ASCII characters can be
encoded in certain header fields.
To create a Message, pass along the Session object to the MimeMessage constructor:
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
3
MimeMessage message = new MimeMessage(session);
Once you have your message, you can set its parts, as Message implements the Part interface
(with MimeMessage implementing MimePart). The basic mechanism to set the content is
the setContent() method, with arguments for the content and the mime type:
message.setContent("Hello", "text/plain");
If, however, you know you are working with a MimeMessage and your message is plain text,
you can use its setText() method which only requires the actual content, defaulting to the
MIME type of text/plain:
message.setText("Hello");
For plain text messages, the latter form is the preferred mechanism to set the content. For
sending other kinds of messages, like HTML messages, use the former.
For setting the subject, use the setSubject() method:
message.setSubject("First");
2.2.4 Address
Once you've created the Session and the Message, as well as filled the message with
content, it is time to address your letter with an Address. Like Message, Address is an
abstract class. You use the javax.mail.internet.InternetAddress class.
To create an address with just the email address, pass the email address to the constructor:
Address address = new InternetAddress(
"[email protected]");
If you want a name to appear next to the email address, you can pass that along to the
constructor, too:
Address address = new InternetAddress(
"[email protected]", "George Bush");
You will need to create address objects for the message's from field as well as the to field.
Unless your mail server prevents you, there is nothing stopping you from sending a message
that appears to be from anyone.
Once you've created the addresses, you connect them to a message in one of two ways. For
identifying the sender, you use the setFrom() and setReplyTo() methods.
message.setFrom(address)
If your message needs to show multiple from addresses, use the addFrom() method:
Address address[] = ...;
message.addFrom(address);
For identifying the message recipients, you use the addRecipient() method. This method
requires a Message.RecipientType besides the address.
message.addRecipient(type, address)
The three predefined types of address are:
•
Message.RecipientType.TO
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
4
•
•
Message.RecipientType.CC
Message.RecipientType.BCC
So, if the message was to go to the vice president, sending a carbon copy to the first lady, the
following would be appropriate:
Address toAddress = new
InternetAddress("[email protected]");
Address ccAddress = new
InternetAddress("[email protected]");
message.addRecipient(Message.RecipientType.TO, toAddress);
message.addRecipient(Message.RecipientType.CC, ccAddress);
The JavaMail API provides no mechanism to check for the validity of an email address. While
you can program in support to scan for valid characters (as defined by RFC 822) or verify the
MX (mail exchange) record yourself, these are all beyond the scope of the JavaMail API.
2.2.5 Authenticator
Like the java.net classes, the JavaMail API can take advantage of an Authenticator to
access protected resources via a username and password. For the JavaMail API, that resource is
the mail server. The JavaMail Authenticator is found in the javax.mail package and
is different from the java.net class of the same name. The two don't share the same
Authenticator as the JavaMail API works with Java 1.1, which didn't have the
java.net variety.
To use the Authenticator, you subclass the abstract class and return a
PasswordAuthentication instance from the getPasswordAuthentication()
method. You must register the Authenticator with the session when created. Then, your
Authenticator will be notified when authentication is necessary. You could popup a
window or read the username and password from a configuration file (though if not encrypted it
is not secure), returning them to the caller as a PasswordAuthentication object.
Properties props = new Properties();
// fill props with any information
Authenticator auth = new MyAuthenticator();
Session session = Session.getDefaultInstance(props, auth);
2.2.6 Transport
The final part of sending a message is to use the Transport class. This class speaks the
protocol-specific language for sending the message (usually SMTP). It's an abstract class and
works something like Session. You can use the default version of the class by just calling the
static send() method:
Transport.send(message);
Or, you can get a specific instance from the session for your protocol, pass along the username
and password (blank if unnecessary), send the message, and close the connection:
message.saveChanges(); // implicit with send()
Transport transport = session.getTransport("smtp");
transport.connect(host, username, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
5
This latter way is best when you need to send multiple messages, as it will keep the connection
with the mail server active between messages. The basic send() mechanism makes a separate
connection to the server for each method call.
Note: To watch the mail commands go by to the mail server, set the debug
flag with session.setDebug(true).
2.2.7 Store and Folder
Getting messages starts similarly to sending messages, with a Session. However, after
getting the session, you connect to a Store, quite possibly with a username and password or
Authenticator. Like Transport, you tell the Store what protocol to use:
// Store store = session.getStore("imap");
Store store = session.getStore("pop3");
store.connect(host, username, password);
After connecting to the Store, you can then get a Folder, which must be opened before you
can read messages from it:
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message message[] = folder.getMessages();
For POP3, the only folder available is the INBOX. If you are using IMAP, you can have other
folders available.
Note: Sun's providers are meant to be smart. While Message
message[] = folder.getMessages(); might look like a slow
operation reading every message from the server, only when you actually
need to get a part of the message is the message content retrieved.
Once you have a Message to read, you can get its content with getContent() or write its
content to a stream with writeTo(). The getContent() method only gets the message
content, while writeTo() output includes headers.
System.out.println(((MimeMessage)message).getContent());
Once you're done reading mail, close the connection to the folder and store.
folder.close(aBoolean);
store.close();
The boolean passed to the close() method of folder states whether or not to update the folder
by removing deleted messages.
2.3 BouncyCastle Bibliotheken
Wir benutzten BouncyCastle S/MIME Packet von the Legion of Bouncy Castle [2] zur
Bearbeitung von S/MIME E-Mails mit Hilfe von JavaMail [1].
2.3.1 Hinzufügen des Providers BouncyCastle
if(Security.getProvider("BC") == null)
Security.addProvider(new BouncyCastleProvider());
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
6
2.3.2 Lesen vom privaten Schlüssel und Zertifikaten aus der PKCS12-Ke
ystore Datei
KeyStore
ks = KeyStore.getInstance("PKCS12", "BC");
ks.load(new FileInputStream(keystoreFilename),
keyStorePassword.toCharArray());
Enumeration e = ks.aliases();
String
keyAlias = null;
while (e.hasMoreElements()){
String alias = (String)e.nextElement();
if (ks.isKeyEntry(alias))
keyAlias = alias;
}
if (keyAlias == null)
throw new Exception("can't find a private key!");
PrivateKey signKey = (PrivateKey) ks.getKey(keyAlias, null);
// The first certificate is the certificate of the signer, all
// others, if exist, are the CA certificates
Certificate[] certs = ks.getCertificateChain(keyAlias);
2.3.3 Lesen eines Zertifikats aus der Zertifikat-Datei
CertificateFactory cf = CertificateFactory.getInstance(
"X509", "BC");
X509Certificate cert = (X509Certificate)
cf.generateCertificate(new FileInputStream(certFile));
2.3.4 Erzeugung einer signierten S/MIME E-Mail
// create the generator for creating an smime/signed message
SMIMESignedGenerator gen = new SMIMESignedGenerator();
/* add a signer to the generator - this specifies we are using SHA1
* and adding the smime attributes above to the signed attributes
* that will be generated as part of the signature. The encryption
* algorithm used is taken from the key
*/
gen.addSigner(
signKey, // The signing key instance of PrivateKey
signCert, // The signing certificate instanceof X509Certificate
SMIMESignedGenerator.DIGEST_SHA1, // Using hash algorithm SHA1
new AttributeTable(signedAttrs), // The attributes to be signed
null);
// create a CertStore containing the certificates we want carried
// in the signature
CertStore certsAndcrls = CertStore.getInstance("Collection",
new CollectionCertStoreParameters(certsAndCrlsCollection),
"BC");
// add our pool of certs and cerls (if any) to go with the signature
gen.addCertificatesAndCRLs(certsAndcrls);
// Sign the MimeBodyPart and extract the multipart object from the
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
7
// SMIMESigned object.
MimeMultipart mm = gen.generate(mimeBodyPart, "BC");
// Set the signed multipart as the content of a mime message
MimeMessage mimemsg = ...
mimemsg.setContent(mm, mm.getContentType());
...
2.3.5 Verifizierung einer signierten S/MIME E-Mail
MimeMessage msg = ...;
// First construct an SMIMESigned object
SMIMESigned smimeSigned = null
if (msg.isMimeType("multipart/signed")){
smimeSigned = new SMIMESigned(
(MimeMultipart)msg.getContent());
}
else if (msg.isMimeType("application/pkcs7-mime"))
{
// in this case the content is wrapped in the signature block.
smimeSigned = new SMIMESigned(msg);
}
// Get the signed content
MimeBodyPart bodyPart = smimeSigned.getContent();
Object content = bodyPart.getContent();
if(content instanceof String){
...
}
else if(content instanceof Multipart){
...
}
// Get all certificates and crls passed in the signature
CertStore certs = s.getCertificatesAndCRLs(
"Collection", "BC");
// Get the signer
SignerInformationStore signers = s.getSignerInfos();
Collection c = signers.getSigners();
SignerInformation signer = (SignerInformation) c.iterator().next();
// Get the signing certificate
Collection signerCerts = certs.getCertificates(signer.getSID());
X509Certificate signingCert = (X509Certificate)
signerCerts.iterator().next();
// Create a cert selector for the building of certpath
X509CertSelector certSelector = new X509CertSelector();
certSelector.setCertificate(signingCert);
certSelector.setCertificateValid(signingTime);
// Try to build a valid certpath
CertPathBuilder cpbuilder = CertPathBuilder.getInstance(
"PKIX", "BC");
PKIXBuilderParameters params = new PKIXBuilderParameters(
trustAnchors, certSelector);
params.setRevocationEnabled(false);
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
8
params.addCertStore(certs);
params.setDate(signingTime);
// CertPathBuilderException is raised if no valid certpath is found
cpbuilder.build(params);
// Verify the signature with the signing certificate
boolean result = signer.verify(signingCert, "BC");
2.3.6 Erzeugung einer verschlüsselten S/MIME E-Mail
// create the generator for creating an smime/encrypted message
SMIMEEnvelopedGenerator gen = new SMIMEEnvelopedGenerator();
// Add the certificate of the recipients, usually also of the sender
gen.addKeyTransRecipient(recipientCert1);
// The OID is defined in the class SMIMEEnvelopedGenerator
String symmetricAlgoOID = SMIMEEnvelopedGenerator.*;
MimeBodyPart mp = gen.generate(
mimeBodyPart, symmetricAlgoOID, "BC");
// Set the signed multipart as the content of a mime message
MimeMessage mimemsg = ...
mimemsg.setContent(mm, mm.getContentType());
...
2.3.7 Entschlüsselung einer verschlüsselten S/MIME E-Mail
// First read the private key and the certificate from the key store
PrivateKey privKey = ...;
X509Certificate cert = ...;
RecipientId recId = new RecipientId();
recId.setSerialNumber(cert.getSerialNumber());
recId.setIssuer(cert.getIssuerX500Principal().getEncoded());
// Get the recipient information for this recipient
SMIMEEnveloped m = new SMIMEEnveloped(mimemsg);
RecipientInformationStore
recipients = m.getRecipientInfos();
RecipientInformation recipient = recipients.get(recId);
byte[] contentBytes = recipient.getContent(privKey, "BC");
MimeBodyPart decContent = SMIMEUtil.toMimeBodyPart(contentBytes);
...
3 Versuche
Nach den einleitenden Informationen erhalten Sie nun eine konkrete Versuchsbeschreibung.
Auf jedem Rechner ist die Java-Entwicklungsumgebung von Eclipse (Version 3.2) und die Java
Developement Kit (Version 1.5.0) installiert.
Alle Zertifikate und privaten Schlüssel sind unter dem Verzeichnis ~/workspace/GPJavamail/key gespeichert. ca.cer ist das CA-Zertifikat. Das entsprechende Zertifikat für den
Kontonamen pcZXY ist pcZXY.cer, und der entsprechende private Schlüssel ist pcZXY.p12 mit
dem Passphrase kspwd und alias pcZXY. Alle Benutzer-Zertifikate sind vom ca.cer ausgestellt.
Schritt 1:
Loggen Sie sich als Benutzer praktikum ein.
Konfigurieren Sie Ihren Mozilla E-Mail-Client mit der E-Mail-Adresse [email protected].
pcZXY ist dabei der Name des Rechners, an dem Sie gerade arbeiten (Beschriftung beachten!).
Die Kontonamen für die E-Mail-Adressen sind identisch mit den Rechnernamen:
pc011, pc012, pc013, pc014, pc015 im Subnetz netz0.test
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
9
pc112, pc113, pc114, pc115, pc116, pc117, pc118 im Subnetz netz1.test
pc211, pc212, pc213, pc214, pc215 im Subnetz netz2.test
Die Passwörter sind identisch mit den Kontonamen bzw. Rechnernamen.
Die Einträge für die IMAP- (NICHT POP3) und SMPT-Server lauten:
server0.netz0.test
server1.netz1.test
server2.netz2.test.
Konfigurieren Sie ca.cer as trusted CA und importieren Sie Ihren privaten Schlüssel.
Starten Sie die Java-Entwicklungsumgebung von Eclipse (~> eclipse-3.2) und öffnen Sie das
Java-Projekt GP-Javamail.
Die nächsten Schritte beziehen sich auf die Arbeit in dieser Entwicklungsumgebung.
Schritt 2:
Öffnen Sie die abstrakte Klasse nds.smime.SMIMEGenerator. Versuchen Sie diese Klasse
anhand der Kommentare, besonders mit dem Wort TODO, in der Datei zu vervollständigen.
Nutzen Sie bitte SHA256 und SHA512 nicht, da dieser Algorithmus vom Mail-Client nicht
verarbeitet wird.
Schritt 3:
Erstellen Sie einen Verzeichnis ~/pcZXY.
Öffnen Sie die Klasse nds.smime.SignedSMIMEGenerator. Versuchen Sie diese Klasse anhand
der Kommentare, besonders mit dem Wort TODO, in der Datei zu vervollständigen. Erzeugen
Sie mit Hilfe dieser Klasse eine signierten S/MIME E-Mail.
1. Speichern Sie diese E-Mail lokal unter ~/pcZXY/signed_local.eml.
2. Schicken Sie diese E-Mail an alle Mailadressen (auch an Sie selbst) im Netzwerklabor.
Speichern Sie diese E-Mail in Mozilla unter ~/pcZXY/signed_server.eml.
Schritt 4:
Öffnen Sie die Klasse nds.smime.SignedSMIMEReader. Versuchen Sie diese Klasse anhand
der Kommentare, besonders mit dem Wort TODO, in der Datei zu vervollständigen. Betrachten
Sie im folgenden Fällen ca.cer als TrustAnchor.
1. Verifizieren Sie mit Hilfe dieser Klasse die E-Mail in ~/pcZXY/signed_local.eml aus
Schritt 3.
2. Kopieren Sie die Datei ~/pcZXY/signed-local.eml nach
~/pcZXY/signed_local_modified.eml und modifizieren Sie die letzte Datei. Verifizieren
Sie dann die modifizierte E-Mail.
3. Verifizieren Sie alle signierten Nachrichten von Ihrem Konto.
Versuchsauswertung: Dokumentieren Sie die Ausgabe des Programms.
Schritt 5:
Öffnen Sie die Klasse nds.smime.SignedSMIMEReader. Betrachten Sie im folgenden Fällen
otherCa.cer als TrustAnchor.
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
1
1. Verifizieren Sie mit Hilfe dieser Klasse die E-Mail in ~/pcZXY/signed_local.eml aus
Schritt 3.
2. Verifizieren Sie alle signierten Nachrichten von Ihrem Konto.
Versuchsauswertung: Dokumentieren Sie die Ausgabe des Programms.
Schritt 6:
Öffnen Sie die Klasse nds.smime.EncryptedSMIMEGenerator. Versuchen Sie diese Klasse
anhand der Kommentare, besonders mit dem Wort TODO, in der Datei zu vervollständigen.
Erzeugen Sie mit Hilfe dieser Klasse eine verschlüsselte S/MIME E-Mail.
1. Speichern Sie diese E-Mail lokal unter ~/pcZXY/encrypted_local.eml.
2. Schicken Sie diese E-Mail an alle Mailadressen im Netzwerklabor. Speichern Sie diese
E-Mail in Mozilla unter ~/pcZXY/encrypted_server.eml.
Schritt 7:
Öffnen Sie die Klasse nds.smime.EncryptedSMIMEReader. Versuchen Sie diese Klasse anhand
der Kommentare, besonders mit dem Wort TODO, in der Datei zu vervollständigen.
1. Entschlüsseln Sie mit Hilfe dieser Klasse die E-Mail in ~/pcZXY/encrypted_local.eml
aus Schritt 6.
2. Entschlüsseln Sie alle verschlüsselten Nachrichten von Ihrem Konto.
Versuchsauswertung: Dokumentieren Sie die Ausgabe des Programms.
Literatur
[1] SUN. JavaMail API. URL: http://java.sun.com/products/javamail/
[2] The Legion of the Bouncy Castle. Specifications of the Bouncy Castle Crypto package.
URL: http://bouncycastle.org/specifications.html
Praktikumsversuch auto. Bearbeitung von sicheren E-Mails
Lehrstuhl Netz- und Datensicherheit
1

Documentos relacionados