Разработка Java-апплета и подписывание архивного JAR-файла электронной цифровой подписью
Государственное
образовательное учреждение высшего профессионального образования
ПЕТЕРБУРГСКИЙ
ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ПУТЕЙ СООБЩЕНИЯ
Кафедра
«Информационные и вычислительные системы»
ПОЯСНИТЕЛЬНАЯ
ЗАПИСКА
к курсовому
проекту
по
дисциплине «Методы программирования»
на тему: «Разработка
Java-апплета и подписывание архивного JAR-файла электронной цифровой подписью»
Выполнил:
студент группы
КИБ-708
Таранин В.В.
Руководитель:
к.т.н., доц.
Кожомбердиева Г.И.
Санкт-Петербург
2009
Задание
по курсовому проекту
по дисциплине «Методы программирования»
на тему: «Разработка Java-апплета и
подписывание архивного JAR-файла электронной цифровой подписью»
·
В
качестве исходных данных к курсовому проекту используется апплет,
являющийся результатом выполнения лабораторной работы №4 «Разработка
апплета с эффектом анимации на основе многопоточности Java».
Вариант задания №20
·
Необходимо
расширить функциональность апплета с эффектом анимации, реализовав обращение к
локальной файловой системе.
·
Создать
архивный JAR-файл, содержащий апплет.
·
Подписать
JAR-файл электронной цифровой подписью (ЭЦП) и задать политику безопасности для
подписанного апплета, включив в файл политики соответствующую запись,
разрешающую доступ к локальной файловой системе и выполнение операций
чтения-записи.
При выполнении курсового проекта использовать
утилиты jar, keytool и jarsigner, а
также комплект JDK 1.4.x с модулем plug-in для браузера MS IE 5,(6),(7).
Аннотация
В данном курсовом проекте был разработан
Java-апплет, использующий механизм многопоточности Java: использование двух
потоков команд, реализующих движение геометрических фигур в области рисования
апплета. Также апплет имеет возможность обращаться к локальной файловой
системе, при предоставлении соответствующих прав доступа. Возможность обращения
к локальной файловой системе реализована с использованием специализированных
классов Java API.
Архивный JAR-файл, содержащий апплет,
подписывается электронной цифровой подписью. Для апплета задается политика
безопасности, путём создания пользовательского файла политики безопасности,
который позволяет апплету получить доступ к локальной файловой системе и
обеспечивающий возможность работы апплета за пределами модели безопасности
Sandbox - «Песочница».
Подписанный электронной цифровой подписью апплет
выполняется в среде MS IE с модулем plug-in из JDK 1.4.x.
После запуска апплета пользователю
предоставляется возможность оказать доверие подписанному апплету и разрешить
выполнение операций ввода-вывода в файл.
Содержание
Введение
1. Апплет с эффектом анимации на
основе многопоточности Java
и
обращением к локальной файловой системе
2. Создание подписанного
апплета
.1 Создание архивного JAR-файла
.2 Создание
пары ключей и сертификата в хранилище ключей
.3 Подписывание JAR-файла
цифровой подписью
.4 Задание политики безопасности для
подписанного апплета
3. Выполнение подписанного апплета
Список использованных источников
Введение
Платформа Java 2 располагает мощной встроенной
системой безопасности, включающая API-интерфейсы и механизмы, которые
используются для обеспечения безопасности апплетов и приложений Java. Среди
особенностей языка программирования Java, которые обеспечивают надежность и
безопасность можно выделить: архитектурную независимость, интерпретируемость,
переносимость, отсутствие указателей, строгую типизацию, эффективный механизм
обработки исключений. Важными неотъемлимыми компонентами системы безопасности
Java 2 являются Java Cryptography Architecture (JCA) - архитектура шифрования
Java, а также Java Cryptography Extension (JCE) - криптографическое расширение
Java.
Целью данного курсового проекта является -
подписание архивного JAR-файла, содержащего апплет, электронной цифровой
подписью, а также задание политики безопасности для подписанного апплета;
ознакомление студентов с криптографическими методоми защиты информации и
возможностями, которые предоставляет Java разработчиками программного
обеспечения. Для этого необходимо: создать архивный JAR-файл, пары ключей и
сертификата в хранилище ключей, далее подписать JAR-файл цифровой подписью и
задать политику безопасности для подписанного апплета.
Результатом данной курсовой работы является
подписанный электронной цифровой подписью апплет, имеющий возможность
обращаться к локальной файловой системе.
1.
Апплет с эффектом анимации на основе многопоточности Java
и
обращением к локальной файловой
системе
апплет архивный электронный цифровой
подпись
import
java.applet.Applet;
import
java.awt.*;java.awt.event.*;java.io.*; java.util.Calendar;
// Класс апплета, реализующий интерфейсы блоков
прослушивания событий
public class Lab4 extends Applet
implements ActionListener,ItemListener,Runnable
{p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,cards,pfield,pb,pread;lb1,lb2,lb3;cbg;cb1,cb2,cb3,cb4;list;cv;b1,b2,b3,b4,start,stop,read;cardLO;sb1,sb2,sb3,sb4;col;posX,strWidth;fm;rectX=0,rectY=0,posFlag=0,movFlag=0,ovalX=0,ovalY=0;animFlag=0;rColor,gColor,bColor;
// Флаг остановки анимации
boolean
stopFlag;
// Поток выполняющий анимацию
Thread
t = null;
//Текстовая область для вывода содержимого файла
журнала
TextArea
fileText;
// Имя файла-журнала для записи информации о
работе апплета
String
fileName = "";
// Разделитель строк (признак конца строки)
String
ls;
// Буферизированный символьный поток записи в
файл
BufferedWriter out;void init()
{(new
GridLayout(2,2));(Color.black); = Color.black;
// ЛЕВАЯ ВЕРХНЯЯ ПАНЕЛЬ
p1 = new Panel(new
BorderLayout());.setBackground(Color.lightGray);= new Panel();= new
Label("Активная панель:
",lb1.CENTER);.add(lb1);.add(p2,BorderLayout.NORTH);
// Панель радиокнопок внутри ЛЕВОЙ ВЕРХНЕЙ
панели
p3 = new Panel(new
GridLayout(2,2));= new CheckboxGroup();= new Checkbox("Все
панели",cbg,true);= new Checkbox("1-я панель",cbg,false);= new
Checkbox("2-я панель",cbg,false);= new Checkbox("3-я
панель",cbg,false);.addItemListener(this);.addItemListener(this);.addItemListener(this);.addItemListener(this);.add(cb1);.add(cb2);.add(cb3);.add(cb4);.add(p3,BorderLayout.CENTER);(p1);
// ВЕРХНЯЯ
ПРАВАЯ ПАНЕЛЬ= new Panel(new GridLayout(1,1));=
new List(9,false);.add("Чёрный");.add("Синий");.add("Красный");.add("Зелёный");.add("Жёлтый");.add("Оранжевый");.add("Розовый");.add("Фиолетовый");.add("Тёмно-серый");.addItemListener(this);.add(list);(p4);
// ЛЕВАЯ НИЖНЯЯ ПАНЕЛЬ
// Панель с кнопками
start = new
Button("Запуск"); start.addActionListener(this);= new
Button("Остановка");stop.addActionListener(this);.add(start);.add(stop);
// !!! ПАНЕЛЬ ДЛЯ ЧТЕНИЯ ФАЙЛА-ЖУРНАЛА !!!
pfield = new Panel(new
BorderLayout());= new Panel(new GridLayout(3,1));= new Button("Чтение
файла-журнала");.addActionListener(this);
// Текстовая область для вывода информации из
файла журнала
fileText
= new TextArea();
// Название файла-журнала задаётся параметром в HTML-файле
// или если такого нет - создаётся по умолчанию
fileName =
getParameter("FileName");(fileName == null)= "log.txt";=
System.getProperty("line.separator"); // разделитель
строк.setBackground(Color.white);.add(lb2);.add(pb);.add(read);.add(p5,BorderLayout.NORTH);.add(pread,BorderLayout.CENTER);.add(fileText,BorderLayout.SOUTH);(pfield);
// ПРАВАЯ НИЖНЯЯ ПАНЕЛЬ
// ПАНЕЛЬ С КАРТАМИ (ГЛАВНАЯ)
cardLO = new CardLayout();= new
Panel();.setLayout(cardLO);.setBackground(Color.white);= 65;
// ПЕРВАЯ ПАНЕЛЬ В КАРТАХ= new
Panel(new BorderLayout())
{void paint(Graphics g)
{(animFlag==0)
{.setColor(col);.drawRect(rectX,rectY,50,50);
}
}
};
// ВТОРАЯ
ПАНЕЛЬ В КАРТАХ= new Panel(new BorderLayout())
{void paint(Graphics g)
{(animFlag==1)
{.setColor(col);.fillOval(ovalX,ovalY,50,50);
}
}
};
// ТРЕТЬЯ
ПАНЕЛЬ В КАРТАХ= new Panel(new BorderLayout())
{void paint(Graphics g)
{.setColor(col);x[] =
{posX,posX+40,posX+80};y[] = {80,20,80};.drawPolygon(x,y,3);
}
};= new
Scrollbar(Scrollbar.HORIZONTAL,0,1,0,100);.addAdjustmentListener(new
AdjustmentListener()
{void
adjustmentValueChanged(AdjustmentEvent ae)
{=
(ae.getValue())*(cards.getSize().width -80) /sb3.getMaximum();.repaint();
}
});.add(sb3,BorderLayout.SOUTH);
// ЧЕТВЁРТАЯ
ПАНЕЛЬ В КАРТАХ= new Panel(new BorderLayout())
{void paint(Graphics g)
{= g.getFontMetrics();=
fm.stringWidth("J A V A");
g.setFont(new
Font("Dialog",Font.ITALIC,20));
g.setColor(col);.drawString("J
A V A",posX,65);
}
};= new
Scrollbar(Scrollbar.HORIZONTAL,0,1,0,5);.addAdjustmentListener(new AdjustmentListener()
{void
adjustmentValueChanged(AdjustmentEvent ae)
{
posX
= (ae.getValue())*(cards.getSize().width - strWidth)/sb4.getMaximum();
p9.repaint();
}
});.add(sb4,BorderLayout.SOUTH);
// ДОБАВЛЕНИЕ КАРТ В ПАНЕЛЬ С КАРТАМИ (cards)
cards.add(p6,"sqaure");.add(p7,"oval");.add(p8,"rect");.add(p9,"text");(cards);
// СОЗДАНИЕ БУФЕРИЗИРОВАННОГО СИМВОЛЬНОГО ПОТОКА
ЗАПИСИ В ФАЙЛ
try
{
// В качестве параметра в данном конструкторе
класса Buffered
используется
// ссылка на объект основного потока (приёмника
данных)
out = new BufferedWriter(new
FileWriter(fileName));
}(IOException ex)
{.setText("Ошибка при создании
потока записи: " + ls);.append(ex.toString() + ls);
}(SecurityException ex)
{.setText("Нет разрешения
доступа к файлу: " + ls);.append(ex.toString() + ls);.setEnabled(false);
}(out != null)
{
// Если создание Buffered-потока
прошло успешно то в качестве данных, которые
// будут заполнять буфер будет являться
сообщение от текущей дате и времени
Calendar c = Calendar.getInstance();
String
dateMessage ="Дата и время: " + c.get(Calendar.DAY_OF_MONTH) +
"/" +
(c.get(Calendar.MONTH)+1) + " -
" + c.get(Calendar.YEAR) +
" " +
c.get(Calendar.HOUR_OF_DAY) + ":" +.get(Calendar.MINUTE);
// После записи в String-переменную
dateMessage информации о дате
-
// вызывается метод writeLogMessage
writeLogMessage(dateMessage);
writeLogMessage("Инициализация
апплета завершена");
}
}
// Вывод сообщения в буферизированный поток для
записи в файл
private
void writeLogMessage(String
message)
{
// Запись в файл осуществляется вызовом метода write
объек-та out типа BufferedWriter
try
{.write(message);.newLine();
}(IOException ex)
{.setText("Ошибка записи в
файл:" + ls);.append(ex.toString() + ls);
}
}
// Запуск
потоковvoid
run()
{
// Пока флаг остановки анимации равен false
- происходит анимация
while (!stopFlag)
{
{(animFlag==0)
{
if(posFlag==0)
// Начальное движение вправо по верхней грани
{
p6.repaint();
// Перерисовка
// Временное (на 40 мс) остановка потока для
создания эффекта анимации
// Далее идут аналогичные изменения координат/
Thread.currentThread().sleep(40);+=5;(rectX>p6.getSize().width-50)
{=7;=1;(posFlag==1)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);6.repaint();
}
}
}
if(posFlag==1)
// Движение вниз по правой грани
{.repaint();.currentThread().sleep(40);
// приостановить
поток+=5;(rectY>p6.getSize().height -
50)
{=p6.getSize().height-53;=2;(posFlag==2)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);6.repaint();
}
}
}
if(posFlag==2)
// Движение влево по нижней грани
{(rectX>0)
{.repaint();.currentThread().sleep(40);=5;
}
{=0;=3;(posFlag==3)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);6.repaint();
}
}
}
if(posFlag==3)
// Движение вверх по левой грани
{(rectY>0)
{.repaint();.currentThread().sleep(40);=5;(rectY<0)
{=0;=0;.repaint();
{(rectX==0 && rectY==0)
{=0;(posFlag==0)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);.repaint();
}
}
}
}
}
}
}(animFlag==1)
{(movFlag==0) // Движение
по диагонали сверху в нижний угол
{.repaint();.currentThread().sleep(50);+=5;+=5;(ovalX>p7.getSize().width-50)
{= p7.getSize().width -50;=
p7.getSize().height-52;=1;(movFlag==1)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);7.repaint();
}
}
}
if(movFlag==1)
// Движение по нижней грани
{.repaint();.currentThread().sleep(50);=5;(ovalX<0)
{=0;=2;(movFlag==2)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);7.repaint();
}
}
if(movFlag==2)
// Движение по диагонали снизу вверх
{.repaint();.currentThread().sleep(50);+=5;=5;(ovalX>p7.getSize().width-50)
{= p10.getSize().width - 52;=
0;=3;(movFlag==3)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);7.repaint();
}
}
}
if(movFlag==3)
// Движение по верхней грани в обратном направлении
{.repaint();.currentThread().sleep(50);=5;(ovalX<0)
{= 0;=0;(movFlag==0)
{= (int)(255*Math.random());=
(int)(255*Math.random());= (int)(255*Math.random());= new
Color(rColor,gColor,bColor);.repaint();
}
}
}
}
}(InterruptedException e)
{
return; //
Завершить поток
}
}
}
//Реализация блоков прослушивания от кнопок
public
void actionPerformed(ActionEvente)
{ac =
e.getActionCommand();(ac.equals("Квадрат"))
{=0;.show(cards,"sqaure");("Рисуется
Квадрат");
}(ac.equals("Круг"))
{=1;.show(cards,"oval");("Рисуется
Круг");
}(ac.equals("Треугольник"))
{.show(cards,"rect");
}(ac.equals("Строка"))
{.show(cards,"text");
}if("Запуск".equals(ac))
{= new Thread(this);=
false;.start();.setEnabled(false);("Поток запущен");
}if("Остановка".equals(ac))
{=true;=
null;.setEnabled(true);("Поток остановлен");
}
if("Чтение
файла-журнала".equals(ac))
{
try
{
// Сброс данных из буфера потока (запись в файл)
out.flush();
// Далее происходит чтение из файла и заполнение
текстовой области
// данными, содержащимися в текстовом файле Lab4Log.txt
// Создание буферизированного символьного потока
чтения из файла*/
BufferedReader in = new BufferedReader(new
FileReader(fileName));s = "", line;((line = in.readLine()) != null)+=
line + "\n";.setText(s);.close();
}(IOException ex)
{.setText("Ошибка чтения файла:
" + ls);.append(ex.toString());
}
}
}
// Реализация блока прослушивания от списка List
и переключателей(CheckBox)
public void
itemStateChanged(ItemEvent ie)
{(ie.getSource() == list)
{s =
list.getSelectedItem();(s.equals("Чёрный"))
{= Color.black;
}(s.equals("Синий"))
{= Color.blue;
}(s.equals("Красный"))
{= Color.red;
}(s.equals("Зелёный"))
{= Color.green;
}(s.equals("Жёлтый"))
{= Color.yellow;
}(s.equals("Оранжевый"))
{= Color.orange;
}(s.equals("Розовый"))
{= Color.pink;
{= Color.magenta;
}(s.equals("Тёмно-серый"))
{= Color.darkGray;
}.repaint();.repaint();.repaint();.repaint();
}
}
// Обработка события от CheckBox
(Определение доступности панелей и их компонентов)
if(ie.getSource() == cb1)
{.setEnabled(true);p4.setEnabled(true);.setEnabled(true);.setEnabled(true);
}(ie.getSource() == cb2)
{.setEnabled(true);p4.setEnabled(true);.setEnabled(false);.setEnabled(false);
}(ie.getSource() == cb3)
{.setEnabled(true);p4.setEnabled(false);.setEnabled(true);.setEnabled(false);
}(ie.getSource() == cb4)
{.setEnabled(true);p4.setEnabled(false);.setEnabled(false);.setEnabled(true);
}
}
}
2. Создание подписанного апплета
.1 Создание архивного JAR-файла
Для подписания апплета электронной цифровой
подписью его упаковывают в архивный JAR-файл. В данной курсовой работе для этой
цели используется утилита jar, либо можно использовать интегрированную
среду разработки приложений.
Для создания архива применилась команда
следующего вида:
cfv Lab4.jar Lab4*.class,
где: jar - название утилиты, которая
упаковывает файлы и создаёт архив- это набор из трёх параметров:
· с - указывает на то,что
создаётся новый архив
· f - первый элемент в
списке файлов - имя архива, который должен быть создан
· v - вывод на консоль
сообщений о всех действиях утилиты jar
Lab4.jar - название
нового архива*.class - параметр указывает, что все файлы классов
расположенные в текущем каталоге, размещаются в архиве Lab4.jar
При этом утилита jar создаёт каталог
META-INF с файлом описания архива MANIFEST.MF
Также в HTML файле, используемом для запуска
апплета были внесены изменения, а именно добавлен атрибут ARCHIVE
элемента Applet. Значение атрибута ARCHIVE = Lab4.JAR.
2.2 Создание
пары ключей и сертификата в хранилище ключей
Далее с помощью утилиты keytool создаётся
пара ключей («открытый/закрытый») и сертификат по стандарту X.509 для
псевдонима «Taraninkey»
в хранилище ключей Taraninstore
в
текущем каталоге.
Для создания самоподписанного сертификата
применилась команда:
keytool -genkey -alias
«Taraninkey» -keystore Taraninstore,
где:
genkey
- параметр
указывающий, что утилита keytool должна сгенерировать ключи
alias «Taraninkey»
- псевдоним,
под которым в хранилище ключей размещается сертификат
keystore
Taraninstore
- название
хранилища ключей
Также по требованиям утилиты, был введён пароль
защиты хранилища ключей, информация о владельце сертификата и пароль защиты
закрытого ключа.
В данном курсовом проекте пароль закрытого ключа
«Taraninkey»
- 123369, а пароль хранилища ключей «Taraninstore»
- 123.
При создании ключей и подписании сертификата
были использованы алгоритмы:
· Алгоритм ключа RSA
· Алгоритм подписи MD-5
2.3 Подписывание JAR-файла
цифровой подписью
Архивный JAR-файл подписывается с помощью
утилиты jarsigner. используя следующую команду:
jarsigner
-keystore
Taraninstore
Lab4.jar
«Taraninkey»
Утилита требует ввести пароль хранилища ключей и
пароль закрытого ключа после чего модифицирует файл описания архива
MANIFEST.MF в каталоге META-INF архива.
В него добавляются записи для каждого файла
класса, входящего в архив. Запись файла класса включает имя и дайджест файла.
Также в каталог META-INF архива
добавляется файл подписи TARNINK.SF.
Содержимое файла подписи TARNINK.SF.
Файл подписи идентифицирует каждый из файлов в
архиве, алгоритм дайджеста содержит для каждого файла значение
дайджеста, вычисленного из записи файла в файле описания MANIFEST.MF.
На заключительном этапе подписания в каталог
META-INF файла архива добавляется двоичный файл подписи TARANINK.RSA.
Расширение
файла подписи указывает, что утилита keytool
использует алгоритм цифровой подписи RSA.
Этот
файл содержит подпись файла подписи TARNINK.SF
и
сертификат, заверяющий подлинность открытого ключа, соответствующего
закрытому ключу, использованному при создании подписи.
2.4 Задание политики безопасности
для подписанного апплета
В данной курсовом проекте для получения доступа
к локальной файловой системе, для подписанного электронной цифровой подписью
апплета, был создан пользовательский файл политики безопасности Lab4.policy.
Содержимое данного файла - набор разрешающих
записей, в которых указываются права доступа, предоставляемые источнику кода
апплета. Данная запись права доступа предоставляет право чтения/записи
всех файлов файловой системы.
3. Выполнение подписанного апплета
При запуске апплета в среде браузера MS IE 5(6)
с модулем Java plgu-in из JDK 1.4.x система безопасности задаёт вопрос о
доверии поставщику, чьим сертификатом заеверен апплет.
При выборе пользователем ответа Grant this
session апплет получает полные права доступа ко всем ресурсам. Для
обращения к локальной файловой системе пользователь может осущесвить чтение
файла-журнала, хранящегося на локальном диске, нажав кнопку «View
Certificate».
При выборе пользователем Deny апплет
получает разрешене работать только с теми ресурсами, права доступа к которым
прописаны в файлах политики безопасности. При выборе Grant always апплет
получает полные права доступа ко всем ресурсам, при следующем запуске апплета
не будет задаваться запрос о доверии поставщику, права доступа будут
автоматически ко всем ресурсам.
При запуске подписанного апплета под браузером
appletviewer апплет автоматически получает права доступа к ресурсам,
указанные в пользовательском файле политики безопасности, размещённом в текущем
каталоге.
1. Корниенко
А.А., Кожомбердиева Г.И., Ерофеев П.В. Электронная цифровая подпись и
безопасность Java-апплетов. Метод. указания. - СПб.: ПГУПС, 2005. - 28 с.
2. Корниенко
А.А., Кожомбердиева Г.И., Киселев И.С. Методы криптографической защиты
информации и их реализация на платформе Java:
Метод. указания. - СПб.: ПГУПС, 2006. - 35 с
3. Ноутон
П., Шилдт Г. Java 2: Пер. с
англ. - СПб.: БХВ-Петербург, 2006
4.
Java 2 SDK, Standard Edition
Documentation, version 1.2.2.
5. Яворски
Дж., Перроун П. Система безопасности Java,
2001.