Initial import.

This commit is contained in:
Peter Boraros 2011-11-05 03:20:24 +01:00
commit 2034d263bd
165 changed files with 21641 additions and 0 deletions

0
README Normal file
View file

15
bin/createKey.sh Executable file
View file

@ -0,0 +1,15 @@
#!/bin/bash
. libs.sh
if [ $# -ne 1 ]; then
echo 1>&2 Usage: $0 location
exit -1
fi
# This will create a new key store in the given location and generate a new
# symmetric signing key. This expects Keyczar and GSON to be on the classpath
if [ ! -f $1/meta ]; then
java -Dfile.encoding=UTF-8 -classpath $CP cz.cvut.keyczar.KeyczarTool create --location=$1 --purpose=sign
fi
java -Dfile.encoding=UTF-8 -classpath $CP cz.cvut.keyczar.KeyczarTool addkey --location=$1 --status=primary

1
bin/libs.sh Normal file
View file

@ -0,0 +1 @@
CP="keyczar-0.6b-jar-with-dependencies.jar"

4
bin/signMessage.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
. libs.sh
java -Dfile.encoding=UTF-8 -classpath $CP cz.cvut.keyczar.homework.CreateSignedFile $@

31
bin/startServer.sh Executable file
View file

@ -0,0 +1,31 @@
#!/bin/bash
. libs.sh
if [ $# -lt 4 ]; then
echo "Usage:"
echo "$0 <level> <port> <kudofileprefix> <keydirprefix>"
echo "<kudofile> = <kudofileprefix><level>"
echo "<keydir> = <keydirprefix><level>"
exit 1
fi
milis=0
if [ $1 -eq 0 ]; then
nanos=1000000
elif [ $1 -eq 1 ]; then
nanos=10000
elif [ $1 -eq 2 ]; then
nanos=100
elif [ $1 -eq 3 ]; then
nanos=0
else
echo "U TROLL? IDK LEVEL > 4!!"
echo "Usage:"
echo "$0 <level> <port> <kudofileprefix> <keydirprefix>"
echo "<kudofile> = <kudofileprefix><level>"
echo "<keydir> = <keydirprefix><level>"
exit 1
fi
java -Dmilis=$milis -Dnanos=$nanos -Dfile.encoding=UTF-8 -classpath $CP cz.cvut.keyczar.homework.VerificationServer $2 $3$1 $4$1

21
keyczar.iml Normal file
View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/testdata" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:1.4" level="project" />
<orderEntry type="library" name="Maven: log4j:log4j:1.2.14" level="project" />
<orderEntry type="library" name="Maven: org.mozilla:jss:4" level="project" />
<orderEntry type="library" name="Maven: junit:junit:4.0" level="project" />
<orderEntry type="library" name="Maven: org.testng:testng:jdk15:5.8" level="project" />
</component>
</module>

258
keyczar.ipr Normal file
View file

@ -0,0 +1,258 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AntConfiguration">
<defaultAnt bundledAnt="true" />
</component>
<component name="ClearCaseSharedConfig">
<option name="myUseUcmModel" value="true" />
</component>
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="?*.properties" />
<entry name="?*.xml" />
<entry name="?*.gif" />
<entry name="?*.png" />
<entry name="?*.jpeg" />
<entry name="?*.jpg" />
<entry name="?*.html" />
<entry name="?*.dtd" />
<entry name="?*.tld" />
<entry name="?*.ftl" />
</wildcardResourcePatterns>
<annotationProcessing enabled="false" useClasspath="true" />
</component>
<component name="CopyrightManager" default="">
<module2copyright />
</component>
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="IdProvider" IDEtalkID="9E076A8D3D477230903028DB84CC84F5" />
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_STRING" value="-target 1.6" />
</component>
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" />
<option name="OPTION_SCOPE" value="protected" />
<option name="OPTION_HIERARCHY" value="true" />
<option name="OPTION_NAVIGATOR" value="true" />
<option name="OPTION_INDEX" value="true" />
<option name="OPTION_SEPARATE_INDEX" value="true" />
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
<option name="OPTION_DEPRECATED_LIST" value="true" />
<option name="OTHER_OPTIONS" value="" />
<option name="HEAP_SIZE" />
<option name="LOCALE" />
<option name="OPEN_IN_BROWSER" value="true" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/keyczar.iml" filepath="$PROJECT_DIR$/keyczar.iml" />
</modules>
</component>
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/classes" />
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
</component>
<component name="WebServicesPlugin" addRequiredLibraries="true" />
<component name="libraryTable">
<library name="Maven: com.google.code.gson:gson:1.4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/1.4/gson-1.4.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/1.4/gson-1.4-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/1.4/gson-1.4-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: junit:junit:4.0">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.0/junit-4.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.0/junit-4.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/junit/junit/4.0/junit-4.0-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: log4j:log4j:1.2.14">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/log4j/log4j/1.2.14/log4j-1.2.14.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/log4j/log4j/1.2.14/log4j-1.2.14-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/log4j/log4j/1.2.14/log4j-1.2.14-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.mozilla:jss:4">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/mozilla/jss/4/jss-4.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/mozilla/jss/4/jss-4-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/mozilla/jss/4/jss-4-sources.jar!/" />
</SOURCES>
</library>
<library name="Maven: org.testng:testng:jdk15:5.8">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/org/testng/testng/5.8/testng-5.8-jdk15.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/org/testng/testng/5.8/testng-5.8-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/org/testng/testng/5.8/testng-5.8-sources.jar!/" />
</SOURCES>
</library>
</component>
</project>

777
keyczar.iws Normal file
View file

@ -0,0 +1,777 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="BookmarkManager">
<bookmark url="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/MessageVerifier.java" line="102" />
</component>
<component name="CCaseConfig">
<option name="checkoutReserved" value="false" />
<option name="markExternalChangeAsUpToDate" value="true" />
<option name="checkInUseHijack" value="true" />
<option name="useUcmModel" value="true" />
<option name="synchOutside" value="false" />
<option name="isHistoryResticted" value="true" />
<option name="useIdenticalSwitch" value="true" />
<option name="synchActivitiesOnRefresh" value="true" />
<option name="lastScr" value="" />
<option name="scrTextFileName" value="" />
<option name="historyRevisionsNumber" value="4" />
</component>
<component name="ChangeListManager">
<list default="true" id="4a20697b-0497-4294-8e23-618a6ba62449" name="Default" comment="" />
<ignored path="keyczar.iws" />
<ignored path=".idea/workspace.xml" />
<option name="TRACKING_ENABLED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ChangesViewManager" flattened_view="true" show_ignored="false" />
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
<option name="REVERSE_PATCH" value="false" />
</component>
<component name="DaemonCodeAnalyzer">
<disable_hints />
</component>
<component name="DebuggerManager">
<breakpoint_any>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
</breakpoint_any>
<breakpoint_rules />
<ui_properties />
</component>
<component name="FavoritesManager">
<favorites_list name="keyczar" />
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="VerificationServer.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/VerificationServer.java">
<provider selected="true" editor-type-id="text-editor">
<state line="19" column="39" selection-start="577" selection-end="577" vertical-scroll-proportion="0.0">
<folding>
<element signature="imports" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="CreateSignedFile.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/CreateSignedFile.java">
<provider selected="true" editor-type-id="text-editor">
<state line="21" column="58" selection-start="728" selection-end="728" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="MessageVerifier.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/MessageVerifier.java">
<provider selected="true" editor-type-id="text-editor">
<state line="33" column="38" selection-start="1084" selection-end="1084" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="KeyczarTool.java" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/KeyczarTool.java">
<provider selected="true" editor-type-id="text-editor">
<state line="163" column="5" selection-start="5473" selection-end="5473" vertical-scroll-proportion="6.84">
<folding>
<element signature="imports" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file leaf-file-name="pom.xml" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/pom.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="89" column="22" selection-start="3422" selection-end="3422" vertical-scroll-proportion="0.9813084">
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindManager">
<FindUsagesManager>
<setting name="OPEN_NEW_TAB" value="false" />
</FindUsagesManager>
</component>
<component name="Git.Settings">
<option name="CHECKOUT_INCLUDE_TAGS" value="false" />
<option name="UPDATE_CHANGES_POLICY" value="STASH" />
</component>
<component name="IdeDocumentHistory">
<option name="changedFiles">
<list>
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/HmacKey3.java" />
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/HmacKey2.java" />
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/HmacKey1.java" />
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/HmacKey.java" />
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/homework/VerificationServer.java" />
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/homework/MessageVerifier.java" />
<option value="$PROJECT_DIR$/src/cz/cvut/keyczar/homework/CreateSignedFile.java" />
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="MavenImportPreferences">
<option name="importingSettings">
<MavenImportingSettings>
<option name="keepSourceFolders" value="false" />
</MavenImportingSettings>
</option>
</component>
<component name="ModuleEditorState">
<option name="LAST_EDITED_MODULE_NAME" />
<option name="LAST_EDITED_TAB_NAME" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<OptionsSetting value="true" id="Undo Check Out" />
<OptionsSetting value="true" id="Get Latest Version" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectReloadState">
<option name="STATE" value="2" />
</component>
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1" splitterProportion="0.5">
<flattenPackages />
<showMembers />
<showModules />
<showLibraryContents />
<hideEmptyPackages />
<abbreviatePackageNames />
<autoscrollToSource />
<autoscrollFromSource />
<sortByType />
</navigator>
<panes>
<pane id="PackagesPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewLibrariesNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="cz.cvut.keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageElementNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="ProjectPane">
<subPane>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="External Libraries" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ExternalLibrariesNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="keyczar" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="timingattack" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="Scope" />
<pane id="Favorites" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="project.structure.last.edited" value="Project" />
<property name="GoToFile.includeJavaFiles" value="false" />
<property name="OverrideImplement.combined" value="true" />
<property name="project.structure.proportion" value="0.0" />
<property name="options.splitter.main.proportions" value="0.3" />
<property name="MemberChooser.sorted" value="false" />
<property name="recentsLimit" value="5" />
<property name="options.lastSelected" value="preferences.externalResources" />
<property name="project.structure.side.proportion" value="0.0" />
<property name="MemberChooser.copyJavadoc" value="false" />
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="MemberChooser.showClasses" value="true" />
<property name="GoToClass.includeLibraries" value="false" />
<property name="options.searchVisible" value="true" />
<property name="options.splitter.details.proportions" value="0.2" />
<property name="dynamic.classpath" value="false" />
</component>
<component name="RecentsManager">
<key name="CopyClassDialog.RECENTS_KEY">
<recent name="cz.cvut.keyczar" />
</key>
</component>
<component name="RunManager" selected="Application.VerificationServer">
<configuration default="false" name="VerificationServer" type="Application" factoryName="Application" temporary="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea">
<pattern>
<option name="PATTERN" value="cz.cvut.keyczar.homework.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="MAIN_CLASS_NAME" value="cz.cvut.keyczar.homework.VerificationServer" />
<option name="VM_PARAMETERS" value="" />
<option name="PROGRAM_PARAMETERS" value="4444 kudo.txt" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="keyczar" />
<envs />
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="50737" />
<option name="TRANSPORT" value="0" />
<option name="LOCAL" value="true" />
</RunnerSettings>
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Debug" />
<ConfigurationWrapper RunnerId="Run" />
<method />
</configuration>
<configuration default="false" name="CreateSignedFile" type="Application" factoryName="Application" temporary="true">
<extension name="coverage" enabled="false" merge="false">
<pattern>
<option name="PATTERN" value="cz.cvut.keyczar.homework.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="MAIN_CLASS_NAME" value="cz.cvut.keyczar.homework.CreateSignedFile" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="keyczar" />
<envs />
<RunnerSettings RunnerId="Run" />
<ConfigurationWrapper RunnerId="Run" />
<method />
</configuration>
<configuration default="true" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Maven.BeforeRunTask" enabled="false" />
<option name="PhingTarget" enabled="false" />
</method>
</configuration>
<configuration default="true" type="FlexUnitRunConfigurationType" factoryName="FlexUnit" adl_options="" air_descriptor_path="" air_program_params="" air_publisher_id="" air_root_dir_path="" air_run_mode="AppDescriptor" browser_family="FIREFOX" class_name="" debugger_sdk="Module SDK" html_or_swf_file_path="" launcher_type="OSDefault" main_class_name="" method_name="" module_name="" output_log_level="" package_name="" player_path="/usr/bin/flashplayer" port="0" run_mode="HtmlOrSwfFile" run_trusted="false" scope="Class" socket_policy_port="0" url_to_launch="http://">
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
<option name="PhingTarget" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
<option name="PhingTarget" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" />
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
<option name="PROGRAM_PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="ENABLE_SWING_INSPECTOR" value="false" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<module name="" />
<envs />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
<option name="PhingTarget" enabled="false" />
</method>
</configuration>
<configuration default="true" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs />
<patterns />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
<option name="PhingTarget" enabled="false" />
</method>
</configuration>
<list size="2">
<item index="0" class="java.lang.String" itemvalue="Application.VerificationServer" />
<item index="1" class="java.lang.String" itemvalue="Application.CreateSignedFile" />
</list>
<configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
<Host>localhost</Host>
<Port>5050</Port>
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false" />
<component name="SvnConfiguration" maxAnnotateRevisions="500">
<option name="USER" value="" />
<option name="PASSWORD" value="" />
<option name="mySSHConnectionTimeout" value="30000" />
<option name="mySSHReadTimeout" value="30000" />
<option name="LAST_MERGED_REVISION" />
<option name="MERGE_DRY_RUN" value="false" />
<option name="MERGE_DIFF_USE_ANCESTRY" value="true" />
<option name="UPDATE_LOCK_ON_DEMAND" value="false" />
<option name="IGNORE_SPACES_IN_MERGE" value="false" />
<option name="DETECT_NESTED_COPIES" value="true" />
<option name="CHECK_NESTED_FOR_QUICK_MERGE" value="false" />
<option name="IGNORE_SPACES_IN_ANNOTATE" value="true" />
<option name="SHOW_MERGE_SOURCES_IN_ANNOTATE" value="true" />
<option name="FORCE_UPDATE" value="false" />
<configuration useDefault="true">$USER_HOME$/.subversion_IDEA</configuration>
<myIsUseDefaultProxy>false</myIsUseDefaultProxy>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="4a20697b-0497-4294-8e23-618a6ba62449" name="Default" comment="" />
<created>1320143548148</created>
<updated>1320143548148</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="0" y="0" width="1024" height="742" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Phing Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
<window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.2174359" sideWeight="0.41512606" order="1" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.2174359" sideWeight="0.9579832" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="VcsManagerConfiguration">
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" />
<option name="CHECK_NEW_TODO" value="true" />
<option name="myTodoPanelSettings">
<value>
<are-packages-shown value="false" />
<are-modules-shown value="false" />
<flatten-packages value="false" />
<is-autoscroll-to-source value="false" />
</value>
</option>
<option name="PERFORM_UPDATE_IN_BACKGROUND" value="true" />
<option name="PERFORM_COMMIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_EDIT_IN_BACKGROUND" value="true" />
<option name="PERFORM_CHECKOUT_IN_BACKGROUND" value="true" />
<option name="PERFORM_ADD_REMOVE_IN_BACKGROUND" value="true" />
<option name="PERFORM_ROLLBACK_IN_BACKGROUND" value="false" />
<option name="CHECK_LOCALLY_CHANGED_CONFLICTS_IN_BACKGROUND" value="false" />
<option name="ENABLE_BACKGROUND_PROCESSES" value="false" />
<option name="CHANGED_ON_SERVER_INTERVAL" value="60" />
<option name="SHOW_ONLY_CHANGED_IN_SELECTION_DIFF" value="true" />
<option name="CHECK_COMMIT_MESSAGE_SPELLING" value="true" />
<option name="DEFAULT_PATCH_EXTENSION" value="patch" />
<option name="FORCE_NON_EMPTY_COMMENT" value="false" />
<option name="LAST_COMMIT_MESSAGE" />
<option name="MAKE_NEW_CHANGELIST_ACTIVE" value="true" />
<option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
<option name="CHECK_FILES_UP_TO_DATE_BEFORE_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
<option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
<option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
<option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
<option name="ACTIVE_VCS_NAME" />
<option name="UPDATE_GROUP_BY_PACKAGES" value="false" />
<option name="UPDATE_GROUP_BY_CHANGELIST" value="false" />
<option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
<option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
</component>
<component name="VssConfiguration">
<option name="CLIENT_PATH" value="" />
<option name="SRCSAFEINI_PATH" value="" />
<option name="USER_NAME" value="" />
<option name="PWD" value="" />
<CheckoutOptions>
<option name="COMMENT" value="" />
<option name="DO_NOT_GET_LATEST_VERSION" value="false" />
<option name="REPLACE_WRITABLE" value="false" />
<option name="RECURSIVE" value="false" />
</CheckoutOptions>
<CheckinOptions>
<option name="COMMENT" value="" />
<option name="KEEP_CHECKED_OUT" value="false" />
<option name="RECURSIVE" value="false" />
</CheckinOptions>
<AddOptions>
<option name="STORE_ONLY_LATEST_VERSION" value="false" />
<option name="CHECK_OUT_IMMEDIATELY" value="false" />
</AddOptions>
<UndocheckoutOptions>
<option name="MAKE_WRITABLE" value="false" />
<option name="REPLACE_LOCAL_COPY" value="2" />
<option name="RECURSIVE" value="false" />
</UndocheckoutOptions>
<GetOptions>
<option name="REPLACE_WRITABLE" value="0" />
<option name="MAKE_WRITABLE" value="false" />
<option name="ANSWER_NEGATIVELY" value="false" />
<option name="ANSWER_POSITIVELY" value="false" />
<option name="RECURSIVE" value="false" />
<option name="VERSION" />
</GetOptions>
</component>
<component name="XDebuggerManager">
<breakpoint-manager />
</component>
<component name="antWorkspaceConfiguration">
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
<option name="FILTER_TARGETS" value="false" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/HmacKey.java">
<provider selected="true" editor-type-id="text-editor">
<state line="133" column="48" selection-start="3706" selection-end="3706" vertical-scroll-proportion="2.580247">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/Verifier.java">
<provider selected="true" editor-type-id="text-editor">
<state line="75" column="16" selection-start="2805" selection-end="2805" vertical-scroll-proportion="0.49270073">
<folding>
<element signature="imports" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/CreateSignedFile.java">
<provider selected="true" editor-type-id="text-editor">
<state line="21" column="58" selection-start="728" selection-end="728" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/VerificationServer.java">
<provider selected="true" editor-type-id="text-editor">
<state line="19" column="39" selection-start="577" selection-end="577" vertical-scroll-proportion="0.0">
<folding>
<element signature="imports" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/scripts/hmac-keygen.sh">
<provider selected="true" editor-type-id="text-editor">
<state line="12" column="9" selection-start="333" selection-end="333" vertical-scroll-proportion="0.32846716">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/homework/MessageVerifier.java">
<provider selected="true" editor-type-id="text-editor">
<state line="33" column="38" selection-start="1084" selection-end="1084" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/scripts/generate-test-keys.py">
<provider selected="true" editor-type-id="text-editor">
<state line="37" column="44" selection-start="1432" selection-end="1436" vertical-scroll-proportion="0.3558394">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/COPYING">
<provider selected="true" editor-type-id="text-editor">
<state line="5" column="26" selection-start="164" selection-end="185" vertical-scroll-proportion="0.13686131">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bin/libs.sh">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bin/createKey.sh">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bin/signMessage.sh">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bin/out0">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="41" selection-start="30" selection-end="30" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/bin/startServer.sh">
<provider selected="true" editor-type-id="text-editor">
<state line="4" column="47" selection-start="63" selection-end="63" vertical-scroll-proportion="0.11214953">
<folding />
</state>
</provider>
</entry>
<entry file="jar:///usr/java/default/jre/lib/alt-rt.jar!/META-INF/MANIFEST.MF">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/cz/cvut/keyczar/KeyczarTool.java">
<provider selected="true" editor-type-id="text-editor">
<state line="163" column="5" selection-start="5473" selection-end="5473" vertical-scroll-proportion="6.84">
<folding>
<element signature="imports" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pom.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="89" column="22" selection-start="3422" selection-end="3422" vertical-scroll-proportion="0.9813084">
<folding />
</state>
</provider>
</entry>
</component>
<component name="masterDetails">
<states>
<state key="ArtifactsStructureConfigurable.UI">
<settings>
<artifact-editor />
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="FacetStructureConfigurable.UI">
<settings>
<last-edited>Android</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="GlobalLibrariesConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="JdkListConfigurable.UI">
<settings>
<last-edited>1.6</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ModuleStructureConfigurable.UI">
<settings>
<last-edited>keyczar</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
<option value="0.5" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.6</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ProjectLibrariesConfigurable.UI">
<settings>
<last-edited>Maven: com.google.code.gson:gson:1.4</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>

124
pom.xml Normal file
View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Licensed to the Apache Software Foundation (ASF) under one * or more
contributor license agreements. See the NOTICE file * distributed with this
work for additional information * regarding copyright ownership. The ASF
licenses this file * to you under the Apache License, Version 2.0 (the *
"License"); you may not use this file except in compliance * with the
License. You may obtain a copy of the License at * *
http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable
law or agreed to in writing, * software distributed under the License is
distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
KIND, either express or implied. See the License for the * specific language
governing permissions and limitations * under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.cvut.keyczar</groupId>
<artifactId>keyczar</artifactId>
<name>Keyczar</name>
<version>0.6b</version>
<packaging>jar</packaging>
<properties>
<maven.test.skip>true</maven.test.skip>
</properties>
<build>
<finalName>${project.artifactId}-${project.version}</finalName>
<sourceDirectory>src</sourceDirectory>
<scriptSourceDirectory>scripts</scriptSourceDirectory>
<testSourceDirectory>tests</testSourceDirectory>
<resources>
<resource>
<directory>src</directory>
<filtering>false</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<testResources>
<testResource>
<directory>testdata</directory>
</testResource>
</testResources>
</build>
<repositories>
<repository>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</snapshots>
<id>keyczar</id>
<name>Keyczar</name>
<url>http://keyczar.googlecode.com/svn/trunk/java/maven/</url>
<layout>default</layout>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>jss</artifactId>
<version>4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>5.8</version>
<classifier>jdk15</classifier>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,179 @@
K 25
svn:wc:ra_dav:version-url
V 49
/svn/!svn/ver/376/trunk/java/code/src/org/keyczar
END
EcPublicKey.java
K 25
svn:wc:ra_dav:version-url
V 66
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/EcPublicKey.java
END
MockKeyczarReader.java
K 25
svn:wc:ra_dav:version-url
V 72
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/MockKeyczarReader.java
END
GenericKeyczar.java
K 25
svn:wc:ra_dav:version-url
V 69
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/GenericKeyczar.java
END
KeyczarTool.java
K 25
svn:wc:ra_dav:version-url
V 66
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/KeyczarTool.java
END
Keyczar.java
K 25
svn:wc:ra_dav:version-url
V 62
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/Keyczar.java
END
KeyczarEncryptedReader.java
K 25
svn:wc:ra_dav:version-url
V 77
/svn/!svn/ver/333/trunk/java/code/src/org/keyczar/KeyczarEncryptedReader.java
END
UnversionedSigner.java
K 25
svn:wc:ra_dav:version-url
V 72
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/UnversionedSigner.java
END
DsaPrivateKey.java
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/DsaPrivateKey.java
END
Encrypter.java
K 25
svn:wc:ra_dav:version-url
V 64
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/Encrypter.java
END
Verifier.java
K 25
svn:wc:ra_dav:version-url
V 63
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/Verifier.java
END
KeyczarPrivateKey.java
K 25
svn:wc:ra_dav:version-url
V 72
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/KeyczarPrivateKey.java
END
StreamCache.java
K 25
svn:wc:ra_dav:version-url
V 66
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/StreamCache.java
END
DsaPublicKey.java
K 25
svn:wc:ra_dav:version-url
V 67
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/DsaPublicKey.java
END
KeyczarPublicKey.java
K 25
svn:wc:ra_dav:version-url
V 71
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/KeyczarPublicKey.java
END
HmacKey.java
K 25
svn:wc:ra_dav:version-url
V 62
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/HmacKey.java
END
KeyczarKey.java
K 25
svn:wc:ra_dav:version-url
V 65
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/KeyczarKey.java
END
AesKey.java
K 25
svn:wc:ra_dav:version-url
V 61
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/AesKey.java
END
TimeoutVerifier.java
K 25
svn:wc:ra_dav:version-url
V 70
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/TimeoutVerifier.java
END
Signer.java
K 25
svn:wc:ra_dav:version-url
V 61
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/Signer.java
END
COPYING
K 25
svn:wc:ra_dav:version-url
V 57
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/COPYING
END
Crypter.java
K 25
svn:wc:ra_dav:version-url
V 62
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/Crypter.java
END
RsaPrivateKey.java
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/RsaPrivateKey.java
END
KeyMetadata.java
K 25
svn:wc:ra_dav:version-url
V 66
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/KeyMetadata.java
END
KeyczarFileReader.java
K 25
svn:wc:ra_dav:version-url
V 72
/svn/!svn/ver/333/trunk/java/code/src/org/keyczar/KeyczarFileReader.java
END
EcPrivateKey.java
K 25
svn:wc:ra_dav:version-url
V 67
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/EcPrivateKey.java
END
RsaPublicKey.java
K 25
svn:wc:ra_dav:version-url
V 67
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/RsaPublicKey.java
END
UnversionedVerifier.java
K 25
svn:wc:ra_dav:version-url
V 74
/svn/!svn/ver/357/trunk/java/code/src/org/keyczar/UnversionedVerifier.java
END
KeyVersion.java
K 25
svn:wc:ra_dav:version-url
V 65
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/KeyVersion.java
END
TimeoutSigner.java
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/TimeoutSigner.java
END

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,224 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.CipherMode;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.ShortBufferException;
import org.keyczar.interfaces.DecryptingStream;
import org.keyczar.interfaces.EncryptingStream;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Wrapping class for AES keys. Currently the default is to use CBC mode.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class AesKey extends KeyczarKey {
private Key aesKey;
private int blockSize;
private static final String AES_ALGORITHM = "AES";
private static final CipherMode DEFAULT_MODE = CipherMode.CBC;
@Expose private String aesKeyString = "";
@Expose private HmacKey hmacKey = new HmacKey();
@Expose private CipherMode mode = DEFAULT_MODE;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
static AesKey generate() throws KeyczarException {
return generate(KeyType.AES.defaultSize());
}
static AesKey generate(int keySize) throws KeyczarException {
AesKey key = new AesKey();
key.size = keySize;
byte[] aesBytes = Util.rand(key.size() / 8);
key.aesKeyString = Base64Coder.encode(aesBytes);
key.mode = DEFAULT_MODE;
key.hmacKey = HmacKey.generate();
key.init();
return key;
}
@Override
KeyType getType() {
return KeyType.AES;
}
@Override
byte[] hash() {
return hash;
}
static AesKey read(String input) throws KeyczarException {
AesKey key = Util.gson().fromJson(input, AesKey.class);
key.hmacKey.init();
key.init();
return key;
}
private void init() throws KeyczarException {
byte[] aesBytes = Base64Coder.decode(aesKeyString);
aesKey = new SecretKeySpec(aesBytes, AES_ALGORITHM);
blockSize = aesBytes.length;
byte[] fullHash =
Util.hash(Util.fromInt(blockSize), aesBytes, hmacKey.keyBytes());
System.arraycopy(fullHash, 0, hash, 0, hash.length);
}
@Override
Stream getStream() throws KeyczarException {
return new AesStream();
}
private class AesStream implements EncryptingStream, DecryptingStream {
private Cipher encryptingCipher;
private Cipher decryptingCipher;
private SigningStream signStream;
boolean ivRead = false;
public AesStream() throws KeyczarException {
/*
* The JCE Cipher.init() call essentially reallocates a new Cipher object
* We avoid this by initializing two Cipher objects with zero-valued IVs,
* Then passing IVs for CBC mode ourselves. The Ciphers will be cached in
* this stream
*/
IvParameterSpec zeroIv = new IvParameterSpec(new byte[blockSize]);
try {
encryptingCipher = Cipher.getInstance(mode.getMode());
encryptingCipher.init(Cipher.ENCRYPT_MODE, aesKey, zeroIv);
decryptingCipher = Cipher.getInstance(mode.getMode());
decryptingCipher.init(Cipher.DECRYPT_MODE, aesKey, zeroIv);
signStream = (SigningStream) hmacKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public SigningStream getSigningStream() {
return signStream;
}
public VerifyingStream getVerifyingStream() {
return (VerifyingStream) signStream;
}
public void initDecrypt(ByteBuffer input) {
// This will simply decrypt the first block, leaving the CBC Cipher
// ready for the next block of input.
byte[] iv = new byte[blockSize];
input.get(iv);
decryptingCipher.update(iv);
ivRead = true;
}
public int initEncrypt(ByteBuffer output) throws KeyczarException {
// Generate a random value and encrypt it. This will be the IV.
byte[] ivPreImage = new byte[blockSize];
Util.rand(ivPreImage);
try {
return encryptingCipher.update(ByteBuffer.wrap(ivPreImage), output);
} catch (javax.crypto.ShortBufferException e) {
throw new ShortBufferException(e);
}
}
public int updateDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
if (ivRead && input.remaining() >= blockSize) {
// The next output block will be the IV preimage, which we'll discard
byte[] temp = new byte[blockSize];
input.get(temp);
decryptingCipher.update(temp); // discard IV preimage byte array
ivRead = false;
}
try {
return decryptingCipher.update(input, output);
} catch (javax.crypto.ShortBufferException e) {
throw new ShortBufferException(e);
}
}
public int updateEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return encryptingCipher.update(input, output);
} catch (javax.crypto.ShortBufferException e) {
throw new ShortBufferException(e);
}
}
public int doFinalDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
if (ivRead) {
if (input.remaining() == 0) {
// This can occur if someone encrypts an 0-length array
return 0;
}
// The next output block will be the IV preimage, which we'll discard
byte[] temp = new byte[blockSize];
input.get(temp);
decryptingCipher.update(temp); // discard IV preimage byte array
ivRead = false;
}
try {
if (input.remaining() == 0) {
byte[] outputBytes = decryptingCipher.doFinal();
output.put(outputBytes);
return outputBytes.length;
} else {
return decryptingCipher.doFinal(input, output);
}
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int doFinalEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return encryptingCipher.doFinal(input, output);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int maxOutputSize(int inputLen) {
return mode.getOutputSize(blockSize, inputLen);
}
}
}

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2008
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,191 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.BadVersionException;
import org.keyczar.exceptions.InvalidSignatureException;
import org.keyczar.exceptions.KeyNotFoundException;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.ShortCiphertextException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.DecryptingStream;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Crypters may both encrypt and decrypt data using sets of symmetric or private
* keys. Sets of public keys may only be used with {@link Encrypter} objects.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Crypter extends Encrypter {
private static final int DECRYPT_CHUNK_SIZE = 1024;
private static final Logger logger = Logger.getLogger(Crypter.class);
private static final StreamCache<DecryptingStream> CRYPT_CACHE
= new StreamCache<DecryptingStream>();
/**
* Initialize a new Crypter with a KeyczarReader. The corresponding key set
* must have a purpose {@link org.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Crypter(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Crypter with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of
* {@link org.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Crypter(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Decrypt the given byte array of ciphertext
*
* @param input The input ciphertext
* @return The decrypted plaintext
* @throws KeyczarException If the input is malformed, the ciphertext
* signature does not verify, the decryption key is not found, or a JCE
* error occurs.
*/
public byte[] decrypt(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(input.length);
decrypt(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Decrypt the given ciphertext input ByteBuffer and write the decrypted
* plaintext to the output ByteBuffer
*
* @param input The input ciphertext. Will not be modified.
* @param output The output buffer to write the decrypted plaintext
* @throws KeyczarException If the input is malformed, the ciphertext
* signature does not verify, the decryption key is not found, or a JCE
* error occurs.
*/
public void decrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
ByteBuffer inputCopy = input.asReadOnlyBuffer();
logger.info(
Messages.getString("Crypter.Decrypting", inputCopy.remaining()));
if (inputCopy.remaining() < HEADER_SIZE) {
throw new ShortCiphertextException(inputCopy.remaining());
}
byte version = inputCopy.get();
if (version != FORMAT_VERSION) {
throw new BadVersionException(version);
}
byte[] hash = new byte[KEY_HASH_SIZE];
inputCopy.get(hash);
KeyczarKey key = getKey(hash);
if (key == null) {
throw new KeyNotFoundException(hash);
}
// The input to decrypt is now positioned at the start of the ciphertext
inputCopy.mark();
DecryptingStream cryptStream = CRYPT_CACHE.get(key);
if (cryptStream == null) {
cryptStream = (DecryptingStream) key.getStream();
}
VerifyingStream verifyStream = cryptStream.getVerifyingStream();
if (inputCopy.remaining() < verifyStream.digestSize()) {
throw new ShortCiphertextException(inputCopy.remaining());
}
// Slice off the signature into another buffer
inputCopy.position(inputCopy.limit() - verifyStream.digestSize());
ByteBuffer signature = inputCopy.slice();
// Reset the position of the input to start of the ciphertext
inputCopy.reset();
inputCopy.limit(inputCopy.limit() - verifyStream.digestSize());
// Initialize the crypt stream. This may read an IV if any.
cryptStream.initDecrypt(inputCopy);
// Verify the header and IV if any
ByteBuffer headerAndIvToVerify = input.asReadOnlyBuffer();
headerAndIvToVerify.limit(inputCopy.position());
verifyStream.initVerify();
verifyStream.updateVerify(headerAndIvToVerify);
output.mark();
// This will process large input in chunks, rather than all at once. This
// avoids making two passes through memory.
while (inputCopy.remaining() > DECRYPT_CHUNK_SIZE) {
ByteBuffer ciphertextChunk = inputCopy.slice();
ciphertextChunk.limit(DECRYPT_CHUNK_SIZE);
cryptStream.updateDecrypt(ciphertextChunk, output);
ciphertextChunk.rewind();
verifyStream.updateVerify(ciphertextChunk);
inputCopy.position(inputCopy.position() + DECRYPT_CHUNK_SIZE);
}
inputCopy.mark();
verifyStream.updateVerify(inputCopy);
if (!verifyStream.verify(signature)) {
throw new InvalidSignatureException();
}
inputCopy.reset();
cryptStream.doFinalDecrypt(inputCopy, output);
output.limit(output.position());
CRYPT_CACHE.put(key, cryptStream);
}
/**
* Decrypt the given web-safe Base64 encoded ciphertext and return the
* decrypted plaintext as a String.
*
* @param ciphertext The encrypted ciphertext in web-safe Base64 format
* @return The decrypted plaintext as a string
* @throws KeyczarException If the input is malformed, the ciphertext
* signature does not verify, the decryption key is not found, the input is
* not web-safe Base64 encoded, or a JCE error occurs.
*/
public String decrypt(String ciphertext) throws KeyczarException {
return new String(decrypt(Base64Coder.decode(ciphertext)));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.DECRYPT_AND_ENCRYPT;
}
}

View file

@ -0,0 +1,196 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
/**
* Wrapping class for DSA Private Keys
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class DsaPrivateKey extends KeyczarKey implements KeyczarPrivateKey {
private static final String KEY_GEN_ALGORITHM = "DSA";
private static final String SIG_ALGORITHM = "SHA1withDSA";
@Expose private DsaPublicKey publicKey;
@Expose private String x;
private DSAPrivateKey jcePrivateKey;
private DsaPrivateKey() {
publicKey = new DsaPublicKey();
}
@Override
byte[] hash() {
return getPublic().hash();
}
public String getKeyGenAlgorithm() {
return KEY_GEN_ALGORITHM;
}
public KeyczarPublicKey getPublic() {
return publicKey;
}
@Override
Stream getStream() throws KeyczarException {
return new DsaSigningStream();
}
@Override
KeyType getType() {
return KeyType.DSA_PRIV;
}
public void setPublic(KeyczarPublicKey pub) throws KeyczarException {
publicKey = (DsaPublicKey) pub;
publicKey.init();
}
static DsaPrivateKey generate() throws KeyczarException {
return generate(KeyType.DSA_PRIV.defaultSize());
}
void init() throws KeyczarException {
publicKey.init();
BigInteger xVal = new BigInteger(Base64Coder.decode(x));
BigInteger pVal = new BigInteger(Base64Coder.decode(publicKey.p));
BigInteger qVal = new BigInteger(Base64Coder.decode(publicKey.q));
BigInteger gVal = new BigInteger(Base64Coder.decode(publicKey.g));
DSAPrivateKeySpec spec = new DSAPrivateKeySpec(xVal, pVal, qVal, gVal);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePrivateKey = (DSAPrivateKey) kf.generatePrivate(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
static DsaPrivateKey generate(int keySize) throws KeyczarException {
DsaPrivateKey key = new DsaPrivateKey();
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(KEY_GEN_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
key.size = keySize;
kpg.initialize(key.size());
KeyPair pair = kpg.generateKeyPair();
key.jcePrivateKey = (DSAPrivateKey) pair.getPrivate();
DSAPublicKey pubKey = (DSAPublicKey) pair.getPublic();
key.publicKey.set(pubKey.getY(), pubKey.getParams().getP(),
pubKey.getParams().getQ(), pubKey.getParams().getG());
// Initialize the private key's JSON fields
key.x = Base64Coder.encode(key.jcePrivateKey.getX().toByteArray());
key.init();
return key;
}
static DsaPrivateKey read(String input) throws KeyczarException {
DsaPrivateKey key = Util.gson().fromJson(input, DsaPrivateKey.class);
key.init();
return key;
}
private class DsaSigningStream implements SigningStream, VerifyingStream {
private Signature signature;
private VerifyingStream verifyingStream;
public DsaSigningStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
verifyingStream = (VerifyingStream) publicKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initSign() throws KeyczarException {
try {
signature.initSign(jcePrivateKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
verifyingStream.initVerify();
}
public void sign(ByteBuffer output) throws KeyczarException {
try {
byte[] sig = signature.sign();
output.put(sig);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateSign(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
verifyingStream.updateVerify(input);
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
return verifyingStream.verify(sig);
}
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.DSAPublicKeySpec;
/**
* Wrapping class for DSA Public Keys. These must be exported from existing DSA
* private key sets.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
class DsaPublicKey extends KeyczarPublicKey {
private static final String KEY_GEN_ALGORITHM = "DSA";
private static final String SIG_ALGORITHM = "SHA1withDSA";
private PublicKey jcePublicKey;
@Expose String y;
@Expose String p;
@Expose String q;
@Expose String g;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
@Override
public Stream getStream() throws KeyczarException {
return new DsaVerifyingStream();
}
@Override
KeyType getType() {
return KeyType.DSA_PUB;
}
static DsaPublicKey read(String input) throws KeyczarException {
DsaPublicKey key = Util.gson().fromJson(input, DsaPublicKey.class);
key.init();
return key;
}
@Override
public byte[] hash() {
return hash;
}
void set(BigInteger yVal, BigInteger pVal, BigInteger qVal, BigInteger gVal)
throws KeyczarException {
// Initialize the JSON fields
y = Base64Coder.encode(yVal.toByteArray());
p = Base64Coder.encode(pVal.toByteArray());
q = Base64Coder.encode(qVal.toByteArray());
g = Base64Coder.encode(gVal.toByteArray());
init();
}
void init() throws KeyczarException {
BigInteger yVal = new BigInteger(Base64Coder.decode(y));
BigInteger pVal = new BigInteger(Base64Coder.decode(p));
BigInteger qVal = new BigInteger(Base64Coder.decode(q));
BigInteger gVal = new BigInteger(Base64Coder.decode(g));
DSAPublicKeySpec spec = new DSAPublicKeySpec(yVal, pVal, qVal, gVal);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePublicKey = kf.generatePublic(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
byte[] fullHash = Util.prefixHash(
Util.stripLeadingZeros(pVal.toByteArray()),
Util.stripLeadingZeros(qVal.toByteArray()),
Util.stripLeadingZeros(gVal.toByteArray()),
Util.stripLeadingZeros(yVal.toByteArray()));
System.arraycopy(fullHash, 0, hash, 0, hash.length);
}
private class DsaVerifyingStream implements VerifyingStream {
private Signature signature;
public DsaVerifyingStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initVerify() throws KeyczarException {
try {
signature.initVerify(jcePublicKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
try {
return signature.verify(sig.array(), sig.position(), sig.limit()
- sig.position());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
}
}

View file

@ -0,0 +1,183 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.jce.EcCore;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* Wrapping class for EC Private Keys
*
* @author martclau@gmail.com
*
*/
class EcPrivateKey extends KeyczarKey implements KeyczarPrivateKey {
private static final String KEY_GEN_ALGORITHM = "EC";
private static final String SIG_ALGORITHM = "SHA256withECDSA";
@Expose private EcPublicKey publicKey;
@Expose private String pkcs8;
private PrivateKey jcePrivateKey;
private EcPrivateKey() {
publicKey = new EcPublicKey();
}
public String getKeyGenAlgorithm() {
return KEY_GEN_ALGORITHM;
}
public KeyczarPublicKey getPublic() {
return publicKey;
}
@Override
byte[] hash() {
return getPublic().hash();
}
@Override
Stream getStream() throws KeyczarException {
return new EcSigningStream();
}
@Override
KeyType getType() {
return KeyType.EC_PRIV;
}
public void setPublic(KeyczarPublicKey pub) throws KeyczarException {
publicKey = (EcPublicKey) pub;
publicKey.init();
}
static EcPrivateKey generate() throws KeyczarException {
return generate(KeyType.EC_PRIV.defaultSize());
}
void init() throws KeyczarException {
byte[] pkcs8Bytes = Base64Coder.decode(pkcs8);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePrivateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(pkcs8Bytes));
publicKey.init();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
static EcPrivateKey generate(int keySize) throws KeyczarException {
EcPrivateKey key = new EcPrivateKey();
try {
// Make sure we use our own impl; there may be other EC key generators...
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_GEN_ALGORITHM,
EcCore.NAME);
key.size = keySize;
kpg.initialize(key.size());
KeyPair pair = kpg.generateKeyPair();
key.jcePrivateKey = pair.getPrivate();
key.publicKey.set(pair.getPublic().getEncoded());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
key.pkcs8 = Base64Coder.encode(key.jcePrivateKey.getEncoded());
key.init();
return key;
}
static EcPrivateKey read(String input) throws KeyczarException {
EcPrivateKey key = Util.gson().fromJson(input, EcPrivateKey.class);
key.init();
return key;
}
private class EcSigningStream implements SigningStream, VerifyingStream {
private Signature signature;
private VerifyingStream verifyingStream;
public EcSigningStream() throws KeyczarException {
try {
// Make sure we use our own impl; there may be other EC signature
// generators...
signature = Signature.getInstance(SIG_ALGORITHM, EcCore.NAME);
verifyingStream = (VerifyingStream) publicKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initSign() throws KeyczarException {
try {
signature.initSign(jcePrivateKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
verifyingStream.initVerify();
}
public void sign(ByteBuffer output) throws KeyczarException {
try {
byte[] sig = signature.sign();
output.put(sig);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateSign(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
verifyingStream.updateVerify(input);
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
return verifyingStream.verify(sig);
}
}
}

View file

@ -0,0 +1,132 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.X509EncodedKeySpec;
/**
* Wrapping class for EC Public Keys. These must be exported from existing EC
* private key sets.
*
* @author martclau@gmail.com
*
*/
class EcPublicKey extends KeyczarPublicKey {
private static final String KEY_GEN_ALGORITHM = "EC";
private static final String SIG_ALGORITHM = "SHA256withECDSA";
private PublicKey jcePublicKey;
@Expose String x509;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
void init() throws KeyczarException {
byte[] x509Bytes = Base64Coder.decode(x509);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePublicKey = kf.generatePublic(new X509EncodedKeySpec(x509Bytes));
byte[] fullHash = Util.prefixHash(x509Bytes);
System.arraycopy(fullHash, 0, hash, 0, hash.length);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
void set(byte[] x509Bytes) throws KeyczarException {
x509 = Base64Coder.encode(x509Bytes);
byte[] fullHash = Util.prefixHash(x509Bytes);
System.arraycopy(fullHash, 0, hash, 0, hash.length);
init();
}
@Override
byte[] hash() {
return hash;
}
@Override
public Stream getStream() throws KeyczarException {
return new EcVerifyingStream();
}
@Override
KeyType getType() {
return KeyType.EC_PUB;
}
static EcPublicKey read(String input) throws KeyczarException {
EcPublicKey key = Util.gson().fromJson(input, EcPublicKey.class);
key.init();
return key;
}
private class EcVerifyingStream implements VerifyingStream {
private Signature signature;
public EcVerifyingStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initVerify() throws KeyczarException {
try {
signature.initVerify(jcePublicKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
try {
return signature.verify(sig.array(), sig.position(), sig.limit()
- sig.position());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
}
}

View file

@ -0,0 +1,192 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.NoPrimaryKeyException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.EncryptingStream;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Encrypters are used strictly to encrypt data. Typically, Encrypters will read
* sets of public keys, although may also be instantiated with sets of symmetric
* keys.
*
* {@link Crypter} objects should be used with symmetric or private key sets to
* decrypt data.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Encrypter extends Keyczar {
private static final Logger ENCRYPTER_LOGGER =
Logger.getLogger(Encrypter.class);
private static final int ENCRYPT_CHUNK_SIZE = 1024;
private final StreamQueue<EncryptingStream> ENCRYPT_QUEUE =
new StreamQueue<EncryptingStream>();
/**
* Initialize a new Encrypter with a KeyczarReader. The corresponding key set
* must have a purpose of either
* {@link org.keyczar.enums.KeyPurpose#ENCRYPT} or
* {@link org.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Encrypter(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Encrypter with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of either
* {@link org.keyczar.enums.KeyPurpose#ENCRYPT} or
* {@link org.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Encrypter(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Returns the size of the ciphertext output that would result from encrypting
* an input of the given length.
*
* @param inputLength The length of the input.
* @return Length of the ciphertext that would be produced.
* @throws KeyczarException If the key set contains no primary encrypting key.
*/
public int ciphertextSize(int inputLength) throws KeyczarException {
EncryptingStream cryptStream = ENCRYPT_QUEUE.poll();
if (cryptStream == null) {
KeyczarKey encryptingKey = getPrimaryKey();
if (encryptingKey == null) {
throw new NoPrimaryKeyException();
}
cryptStream = (EncryptingStream) encryptingKey.getStream();
}
SigningStream signStream = cryptStream.getSigningStream();
int outputSize = HEADER_SIZE + cryptStream.maxOutputSize(inputLength) +
signStream.digestSize();
ENCRYPT_QUEUE.add(cryptStream);
return outputSize;
}
/**
* Encrypt the given input byte array.
*
* @param input The input to encrypt
* @return The encrypted ciphertext
* @throws KeyczarException If there is a JCE exception or the key set does
* not contain a primary encrypting key.
*/
public byte[] encrypt(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(ciphertextSize(input.length));
encrypt(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Encrypt the given input ByteBuffer.
*
* @param input The input buffer to encrypt. Will not be modified
* @param output The buffer to write the output ciphertext to.
* @throws KeyczarException If there is a JCE exception, the key set does
* not contain a primary encrypting key, or the output buffer is too small.
*/
public void encrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
ENCRYPTER_LOGGER.info(Messages.getString("Encrypter.Encrypting", input.remaining()));
KeyczarKey encryptingKey = getPrimaryKey();
if (encryptingKey == null) {
throw new NoPrimaryKeyException() ;
}
EncryptingStream cryptStream = ENCRYPT_QUEUE.poll();
if (cryptStream == null) {
cryptStream = (EncryptingStream) encryptingKey.getStream();
}
// Initialize the signing stream
SigningStream signStream = cryptStream.getSigningStream();
signStream.initSign();
// Write the key header
output.mark();
ByteBuffer outputToSign = output.asReadOnlyBuffer();
encryptingKey.copyHeader(output);
// Write the IV. May be an empty array of zero length
cryptStream.initEncrypt(output);
ByteBuffer inputCopy = input.asReadOnlyBuffer();
while (inputCopy.remaining() > ENCRYPT_CHUNK_SIZE) {
ByteBuffer inputChunk = inputCopy.slice();
inputChunk.limit(ENCRYPT_CHUNK_SIZE);
cryptStream.updateEncrypt(inputChunk, output);
inputCopy.position(inputCopy.position() + ENCRYPT_CHUNK_SIZE);
outputToSign.limit(output.position());
signStream.updateSign(outputToSign);
outputToSign.position(output.position());
}
// Sign any remaining plaintext
cryptStream.doFinalEncrypt(inputCopy, output);
output.limit(output.position() + signStream.digestSize());
// Set the limit on the output to sign
outputToSign.limit(output.position());
signStream.updateSign(outputToSign);
// Sign the final block of ciphertext output
signStream.sign(output);
ENCRYPT_QUEUE.add(cryptStream);
}
/**
* Encrypt a String and return a web-safe Base64 encoded ciphertext.
*
* @param input An String to encrypt.
* @return A web-safe Base64 encoded ciphertext.
* @throws KeyczarException If there is a JCE exception or the key set does
* not contain a primary encrypting key.
*/
public String encrypt(String input) throws KeyczarException {
return Base64Coder.encode(encrypt(input.getBytes()));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.ENCRYPT
|| purpose == KeyPurpose.DECRYPT_AND_ENCRYPT;
}
}

View file

@ -0,0 +1,296 @@
package org.keyczar;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.enums.KeyStatus;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
/**
* Wrapper class to access Keyczar utility methods of reading and manipulating
* key metadata files. Also contains additional utility methods for pushing
* updates to meta files on disk and exporting public key sets.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class GenericKeyczar extends Keyczar {
GenericKeyczar(KeyczarReader reader) throws KeyczarException {
super(reader);
}
GenericKeyczar(String location) throws KeyczarException {
super(location);
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return true;
}
KeyMetadata getMetadata() {
return this.kmd;
}
Set<KeyVersion> getVersions() {
return Collections.unmodifiableSet(versionMap.keySet());
}
KeyczarKey getKey(KeyVersion v) {
return versionMap.get(v);
}
/**
* Promotes the status of key with given version number. Promoting ACTIVE key
* automatically demotes current PRIMARY key to ACTIVE.
*
* @param versionNumber integer version number to promote
* @throws KeyczarException if invalid version number or trying to promote
* a primary key.
*/
void promote(int versionNumber) throws KeyczarException {
KeyVersion version = getVersion(versionNumber);
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.PromotedVersion", version));
switch (version.getStatus()) {
case PRIMARY:
throw new KeyczarException(
Messages.getString("Keyczar.CantPromotePrimary"));
case ACTIVE:
version.setStatus(KeyStatus.PRIMARY); // promote to PRIMARY
if (primaryVersion != null) {
primaryVersion.setStatus(KeyStatus.ACTIVE); // only one PRIMARY key
}
primaryVersion = version;
break;
case INACTIVE:
version.setStatus(KeyStatus.ACTIVE);
break;
}
}
/**
* Demotes the status of key with given version number. Demoting PRIMARY key
* results in a key set with no primary version.
*
* @param versionNumber integer version number to demote
* @throws KeyczarException if invalid version number or trying to demote
* a key scheduled for revocation.
*/
void demote(int versionNumber) throws KeyczarException {
KeyVersion version = getVersion(versionNumber);
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.DemotingVersion", version));
switch (version.getStatus()) {
case PRIMARY:
version.setStatus(KeyStatus.ACTIVE);
primaryVersion = null; // no more PRIMARY keys in the set
break;
case ACTIVE:
version.setStatus(KeyStatus.INACTIVE);
break;
case INACTIVE:
throw new KeyczarException(
Messages.getString("Keyczar.CantDemoteScheduled"));
}
}
/**
* Uses default key size to add a new key version.
*
* @param status KeyStatus desired for new key version
*/
void addVersion(KeyStatus status) throws KeyczarException {
addVersion(status, kmd.getType().defaultSize());
}
/**
* Adds a new key version with given status and next available version
* number to key set. Generates a new key of same type (repeated until hash
* identifier is unique) for this version. Uses supplied key size in lieu
* of the default key size. If this is an unacceptable key size, defaults
* to the default key size.
*
* @param status KeyStatus desired for new key version
* @param keySize desired key size in bits
* @throws KeyczarException if key type is unsupported.
*/
void addVersion(KeyStatus status, int keySize) throws KeyczarException {
KeyVersion version = new KeyVersion(numVersions() + 1, status, false);
if (status == KeyStatus.PRIMARY) {
if (primaryVersion != null) {
primaryVersion.setStatus(KeyStatus.ACTIVE);
}
primaryVersion = version;
}
KeyczarKey key;
if (keySize < kmd.getType().defaultSize()) { // print a warning statement
KEYCZAR_LOGGER.warn(Messages.getString("Keyczar.SizeWarning",
keySize, kmd.getType().defaultSize(), kmd.getType().toString()));
}
do { // Make sure no keys collide on their identifiers
key = KeyczarKey.genKey(kmd.getType(), keySize);
} while (getKey(key.hash()) != null);
addKey(version, key);
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.NewVersion", version));
}
int numVersions() {
return versionMap.size();
}
/**
* Returns the version corresponding to the version number if it exists.
*
* @param versionNumber
* @return KeyVersion if it exists
* @throws KeyczarException if version number doesn't exist
*/
KeyVersion getVersion(int versionNumber) throws KeyczarException {
KeyVersion version = kmd.getVersion(versionNumber);
if (version == null) {
throw new KeyczarException(
Messages.getString("Keyczar.NoSuchVersion", versionNumber));
}
return version;
}
/**
* Revokes the key with given version number if it is scheduled to be revoked.
*
* @param versionNumber integer version number to be revoked
* @throws KeyczarException if version number nonexistent or key is not
* scheduled for revocation.
*/
void revoke(int versionNumber) throws KeyczarException {
KeyVersion version = getVersion(versionNumber);
if (version.getStatus() == KeyStatus.INACTIVE) {
kmd.removeVersion(versionNumber);
} else {
throw new KeyczarException(Messages.getString("Keyczar.CantRevoke"));
}
}
/**
* For the managed key set, exports a set of public keys at given location.
* Client's key must be a private key for DSA or RSA. For DSA private key,
* purpose must be SIGN_AND_VERIFY. For RSA private key, purpose can also
* be DECRYPT_AND_ENCRYPT.KeyczarTool
*
* @param destination String pathname of directory to export key set to
* @throws KeyczarException if unable to export key set.
*/
void publicKeyExport(String destination) throws KeyczarException {
KeyMetadata kmd = getMetadata();
// Can only export if type is DSA_PRIV and purpose is SIGN_AND_VERIFY
KeyMetadata publicKmd = null;
switch(kmd.getType()) {
case DSA_PRIV: // DSA Private Key
if (kmd.getPurpose() == KeyPurpose.SIGN_AND_VERIFY) {
publicKmd = new KeyMetadata(kmd.getName(), KeyPurpose.VERIFY,
KeyType.DSA_PUB);
}
break;
case RSA_PRIV: // RSA Private Key
switch(kmd.getPurpose()) {
case DECRYPT_AND_ENCRYPT:
publicKmd = new KeyMetadata(kmd.getName(), KeyPurpose.ENCRYPT,
KeyType.RSA_PUB);
break;
case SIGN_AND_VERIFY:
publicKmd = new KeyMetadata(kmd.getName(), KeyPurpose.VERIFY,
KeyType.RSA_PUB);
break;
}
break;
}
if (publicKmd == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.CannotExportPubKey",
kmd.getType(), kmd.getPurpose()));
}
for (KeyVersion version : getVersions()) {
KeyczarKey publicKey =
((KeyczarPrivateKey) getKey(version)).getPublic();
if (KeyczarTool.getMock() == null) {
writeFile(publicKey.toString(), destination
+ version.getVersionNumber());
} else { // for testing, update mock object
KeyczarTool.getMock().setPublicKey(version.getVersionNumber(), publicKey);
}
publicKmd.addVersion(version);
}
if (KeyczarTool.getMock() == null) {
writeFile(publicKmd.toString(), destination
+ KeyczarFileReader.META_FILE);
} else { // for testing, update mock public kmd
KeyczarTool.getMock().setPublicKeyMetadata(publicKmd);
}
}
/**
* Pushes updated KeyMetadata and KeyVersion info to files at given
* directory location. Version files are named by their number and the
* meta file is named meta.
*
* @param location String pathname of directory to write to
* @throws KeyczarException if unable to write to given location.
*/
void write(String location) throws KeyczarException {
writeFile(kmd.toString(), location
+ KeyczarFileReader.META_FILE);
for (KeyVersion version : getVersions()) {
writeFile(getKey(version).toString(), location
+ version.getVersionNumber());
}
}
/**
* Encrypts the key files before writing them out to disk
*
* @param location Location of key set
* @param encrypter The encrypter object used to encrypt keys
* @throws KeyczarException If unable to write to a given location
*/
void writeEncrypted(String location, Encrypter encrypter)
throws KeyczarException {
KeyMetadata kmd = getMetadata();
kmd.setEncrypted(true);
writeFile(kmd.toString(), location + KeyczarFileReader.META_FILE);
for (KeyVersion version : getVersions()) {
writeFile(encrypter.encrypt(getKey(version).toString()), location
+ version.getVersionNumber());
}
}
/**
* Utility function to write given data to a file at given location.
*
* @param data String data to be written
* @param location String pathname of destination file
* @throws KeyczarException if unable to write to file.
*/
void writeFile(String data, String location)
throws KeyczarException {
File outputFile = new File(location);
try {
FileWriter writer = new FileWriter(outputFile);
writer.write(data);
writer.close();
} catch (IOException e) {
throw new KeyczarException(
Messages.getString("KeyczarTool.UnableToWrite",
outputFile.toString()), e);
}
}
}

View file

@ -0,0 +1,147 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Wrapping class for HMAC-SHA1 keys
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class HmacKey extends KeyczarKey {
private static final String MAC_ALGORITHM = "HMACSHA1";
@Expose private String hmacKeyString;
private Key hmacKey;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
static HmacKey generate() throws KeyczarException {
return generate(KeyType.HMAC_SHA1.defaultSize());
}
static HmacKey generate(int keySize) throws KeyczarException {
HmacKey key = new HmacKey();
key.size = keySize;
byte[] keyBytes = Util.rand(key.size() / 8);
key.hmacKeyString = Base64Coder.encode(keyBytes);
key.init();
return key;
}
void init() throws KeyczarException {
byte[] keyBytes = Base64Coder.decode(hmacKeyString);
byte[] fullHash = Util.hash(keyBytes);
System.arraycopy(fullHash, 0, hash, 0, hash.length);
hmacKey = new SecretKeySpec(keyBytes, MAC_ALGORITHM);
}
/*
* This method is for AesKey to grab the key bytes to compute an identifying
* hash.
*/
byte[] keyBytes() {
return hmacKey.getEncoded();
}
@Override
Stream getStream() throws KeyczarException {
return new HmacStream();
}
@Override
KeyType getType() {
return KeyType.HMAC_SHA1;
}
@Override
byte[] hash() {
return hash;
}
static HmacKey read(String input) throws KeyczarException {
HmacKey key = Util.gson().fromJson(input, HmacKey.class);
key.init();
return key;
}
private class HmacStream implements VerifyingStream, SigningStream {
private Mac hmac;
public HmacStream() throws KeyczarException {
try {
hmac = Mac.getInstance(MAC_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initSign() throws KeyczarException {
try {
hmac.init(hmacKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
initSign();
}
public void sign(ByteBuffer output) {
output.put(hmac.doFinal());
}
public void updateSign(ByteBuffer input) {
hmac.update(input);
}
public void updateVerify(ByteBuffer input) {
updateSign(input);
}
public boolean verify(ByteBuffer signature) {
byte[] sigBytes = new byte[signature.remaining()];
signature.get(sigBytes);
return Arrays.equals(hmac.doFinal(), sigBytes);
}
}
}

View file

@ -0,0 +1,157 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.enums.KeyType;
import org.keyczar.util.Util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Encodes metadata for a set of keys which consists of the following:
* <ul>
* <li>a string-valued name,
* <li>a KeyPurpose,
* <li>a KeyType, and
* <li>a set of KeyVersion values.
* </ul>
*
* <p>JSON Representation consists of the following fields:
* <ul>
* <li>"name": a String name,
* <li>"purpose": JSON representation of KeyPurpose value,
* <li>"type": JSON representation of KeyType value,
* <li>"versions": JSON representation of an array of KeyVersion values.
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class KeyMetadata {
@Expose String name = "";
@Expose KeyPurpose purpose = KeyPurpose.TEST;
@Expose KeyType type = KeyType.TEST;
@Expose List<KeyVersion> versions = new ArrayList<KeyVersion>();
@Expose boolean encrypted = false;
protected Map<Integer, KeyVersion> versionMap =
new HashMap<Integer, KeyVersion>(); // link version number to version
@SuppressWarnings("unused")
private KeyMetadata() {
// For GSON
}
KeyMetadata(String n, KeyPurpose p, KeyType t) {
name = n;
purpose = p;
type = t;
}
@Override
public String toString() {
return Util.gson().toJson(this);
}
/**
* Adds given key version to key set.
*
* @param version KeyVersion of key to be added
* @return true if add was successful, false if version number collides
*/
boolean addVersion(KeyVersion version) {
int versionNumber = version.getVersionNumber();
if (!versionMap.containsKey(versionNumber)) {
versionMap.put(versionNumber, version);
versions.add(version);
return true;
}
return false;
}
/**
* Removes given key version from key set.
*
* @param versionNumber integer version number of key to be removed
* @return true if remove was successful
*/
boolean removeVersion(int versionNumber) {
if (versionMap.containsKey(versionNumber)) {
KeyVersion version = versionMap.get(versionNumber);
versions.remove(version);
versionMap.remove(versionNumber);
return true;
}
return false;
}
String getName() {
return name;
}
KeyPurpose getPurpose() {
return purpose;
}
KeyType getType() {
return type;
}
void setEncrypted(boolean encrypted) {
this.encrypted = encrypted;
}
boolean isEncrypted() {
return encrypted;
}
/**
* Returns the version corresponding to the version number.
*
* @param versionNumber
* @return KeyVersion corresponding to given number, or null if nonexistent
*/
KeyVersion getVersion(int versionNumber) {
return versionMap.get(versionNumber);
}
List<KeyVersion> getVersions() {
return versions;
}
/**
* Parses JSON string to create a KeyMetadata object. Initializes it with
* versions listed in the JSON array.
*
* @param jsonString
* @return KeyMetadata corresponding to JSON input
*/
static KeyMetadata read(String jsonString) {
KeyMetadata kmd = Util.gson().fromJson(jsonString, KeyMetadata.class);
for (KeyVersion version : kmd.getVersions()) {
kmd.versionMap.put(version.getVersionNumber(), version);
}
return kmd;
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyStatus;
import org.keyczar.util.Util;
/**
* A key version consists of the following:
* <ul>
* <li>an integer value version number, counting from 1,
* <li>a KeyStatus, and
* <li>a boolean representing whether this key is exportable
* outside of Keyczar.
* </ul>
* <p>JSON Representation consists of the following fields:
* <ul>
* <li>"status": JSON representation of KeyStatus value,
* <li>"versionNumber": integer version number,
* <li>"exportable": boolean value.
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class KeyVersion {
@Expose private boolean exportable = false;
@Expose private KeyStatus status = KeyStatus.ACTIVE;
@Expose private int versionNumber = 0;
@SuppressWarnings("unused")
private KeyVersion() {
// For GSON
}
KeyVersion(int v, boolean export) {
this(v, KeyStatus.ACTIVE, export);
}
KeyVersion(int v, KeyStatus s, boolean export) {
versionNumber = v;
status = s;
exportable = export;
}
@Override
public String toString() {
return Util.gson().toJson(this);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof KeyVersion)) {
return false;
}
KeyVersion v = (KeyVersion) o;
return getVersionNumber() == v.getVersionNumber();
// only depend on version number, otherwise changing status changes identity
}
@Override
public int hashCode() {
return versionNumber; // identity depends only on version number
}
KeyStatus getStatus() {
return status;
}
int getVersionNumber() {
return versionNumber;
}
boolean isExportable() {
return exportable;
}
/**
* Updates the status of this KeyVersion to given status if not null.
* @param status
*/
void setStatus(KeyStatus status) {
this.status = (status == null) ? this.status : status;
}
static KeyVersion read(String jsonString) {
return Util.gson().fromJson(jsonString, KeyVersion.class);
}
}

View file

@ -0,0 +1,153 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.enums.KeyStatus;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.EncryptedReader;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.util.Util;
import java.util.HashMap;
/**
* Manages a Keyczar key set.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
abstract class Keyczar {
static final Logger KEYCZAR_LOGGER = Logger.getLogger(Keyczar.class);
static final byte FORMAT_VERSION = 0;
static final byte[] FORMAT_BYTES = { FORMAT_VERSION };
static final int KEY_HASH_SIZE = 4;
static final int HEADER_SIZE = 1 + KEY_HASH_SIZE;
final KeyMetadata kmd;
KeyVersion primaryVersion;
final HashMap<KeyVersion, KeyczarKey> versionMap =
new HashMap<KeyVersion, KeyczarKey>();
final HashMap<KeyHash, KeyczarKey> hashMap =
new HashMap<KeyHash, KeyczarKey>(); // keep track of used hash identifiers
private class KeyHash {
private byte[] data;
private KeyHash(byte[] d) {
if (d.length != KEY_HASH_SIZE) {
throw new IllegalArgumentException();
}
data = d;
}
@Override
public boolean equals(Object o) {
return (o instanceof KeyHash && o.hashCode() == this.hashCode());
}
@Override
public int hashCode() {
return Util.toInt(data);
}
}
/**
* Instantiates a new Keyczar object by passing it a Keyczar reader object
*
* @param reader A KeyczarReader to read keys from
* @throws KeyczarException
*/
public Keyczar(KeyczarReader reader) throws KeyczarException {
// Reads keys from the KeyczarReader
kmd = KeyMetadata.read(reader.getMetadata());
if (!isAcceptablePurpose(kmd.getPurpose())) {
throw new KeyczarException(
Messages.getString("Keyczar.UnacceptablePurpose", kmd.getPurpose()));
}
if (kmd.isEncrypted() && !(reader instanceof EncryptedReader)) {
throw new KeyczarException(
Messages.getString("Keyczar.NeedEncryptedReader"));
}
for (KeyVersion version : kmd.getVersions()) {
if (version.getStatus() == KeyStatus.PRIMARY) {
if (primaryVersion != null) {
throw new KeyczarException(
Messages.getString("Keyczar.SinglePrimary"));
}
primaryVersion = version;
}
KeyczarKey key = KeyczarKey.readKey(kmd.getType(),
reader.getKey(version.getVersionNumber()));
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.ReadVersion", version));
hashMap.put(new KeyHash(key.hash()), key);
versionMap.put(version, key);
}
}
/**
* Instantiates a new Keyczar object with a KeyczarFileReader instantiated
* with the given file location
*
* @param fileLocation
* @throws KeyczarException
*/
public Keyczar(String fileLocation) throws KeyczarException {
this(new KeyczarFileReader(fileLocation));
}
@Override
public String toString() {
return kmd.toString();
}
/**
* Adds a new KeyczarKey (new version) to the key store. Associates it
* with given version. Adds new KeyVersion to the key set.
*
* @param version KeyVersion
* @param key KeyczarKey
*/
void addKey(KeyVersion version, KeyczarKey key) {
hashMap.put(new KeyHash(key.hash()), key);
versionMap.put(version, key);
kmd.addVersion(version);
}
KeyczarKey getPrimaryKey() {
if (primaryVersion == null) {
return null;
}
return versionMap.get(primaryVersion);
}
KeyczarKey getKey(byte[] hash) {
return hashMap.get(new KeyHash(hash));
}
/**
* Returns true if the purpose is acceptable for this key set.
*
* @param purpose
* @return true if the purpose is acceptable, false otherwise.
*/
abstract boolean isAcceptablePurpose(KeyPurpose purpose);
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.EncryptedReader;
import org.keyczar.interfaces.KeyczarReader;
/**
* Reads metadata and encrypted key files from the given reader.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class KeyczarEncryptedReader implements EncryptedReader {
private KeyczarReader reader;
private Crypter crypter;
/**
* Reads encrypted key files from the given reader and decrypts them
* with the given crypter.
*
* @param reader The reader to read files from.
* @param crypter The crypter to decrypt keys with.
*/
public KeyczarEncryptedReader(KeyczarReader reader, Crypter crypter) {
this.reader = reader;
this.crypter = crypter;
}
public String getKey(int version) throws KeyczarException {
return crypter.decrypt(reader.getKey(version));
}
public String getMetadata() throws KeyczarException {
return reader.getMetadata();
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Reads metadata and key files from the given location.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class KeyczarFileReader implements KeyczarReader {
private String location;
static final String META_FILE = "meta";
public KeyczarFileReader(String fileLocation) {
if (fileLocation != null && !fileLocation.endsWith(File.separator)) {
fileLocation += File.separator;
}
location = fileLocation;
}
public String getKey(int version) throws KeyczarException {
return readFile(location + version);
}
public String getMetadata() throws KeyczarException {
return readFile(location + META_FILE);
}
private String readFile(String filename) throws KeyczarException {
try {
RandomAccessFile file = new RandomAccessFile(filename, "r");
byte[] contents = new byte[(int) file.length()];
file.read(contents);
file.close();
return new String(contents);
} catch (IOException e) {
throw new KeyczarException(
Messages.getString("KeyczarFileReader.FileError", filename), e);
}
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.UnsupportedTypeException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.Stream;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* Common base wrapper class for different types of KeyczarKeys (e.g. AesKey).
* Allows generating arbitrary key types or parsing key info from JSON
* string representations. Binds each key to a hash identifier and exposes
* the Stream used to access the key material.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
abstract class KeyczarKey {
@Expose int size = getType().defaultSize();
void copyHeader(ByteBuffer dest) {
dest.put(Keyczar.FORMAT_VERSION);
dest.put(hash());
}
@Override
public boolean equals(Object o) {
try {
KeyczarKey key = (KeyczarKey) o;
return Arrays.equals(key.hash(), this.hash());
} catch (ClassCastException e) {
return false;
}
}
@Override
public int hashCode() {
return Util.toInt(this.hash());
}
abstract Stream getStream() throws KeyczarException;
/**
* Return this key's type
*
* @return KeyType of this key
*/
abstract KeyType getType();
/**
* Return this key's hash value
*
* @return A byte array hash of this key material
*/
abstract byte[] hash();
int size() {
return size;
}
/**
* Generates private key of desired type and of the default size.
*
* @param type KeyType desired
* @return KeyczarKey of desired type
* @throws KeyczarException for unsupported key types
*/
static KeyczarKey genKey(KeyType type) throws KeyczarException {
return genKey(type, type.defaultSize());
}
@Override
public String toString() {
return Util.gson().toJson(this);
}
/**
* Generates private key of the desired type and size. Cannot generate public
* key, instead must export public key set from private keys.
*
* If given size is unacceptable, falls back to using default size for the
* desired key type.
*
* @param type KeyType desired
* @param keySize desired length of key
* @return KeyczarKey of desired type
* @throws KeyczarException for unsupported key types
*/
static KeyczarKey genKey(KeyType type, int keySize) throws KeyczarException {
if (!type.isAcceptableSize(keySize)) {
keySize = type.defaultSize(); // fall back to default
}
switch (type) {
case AES:
return AesKey.generate(keySize);
case HMAC_SHA1:
return HmacKey.generate(keySize);
case DSA_PRIV:
return DsaPrivateKey.generate(keySize);
case RSA_PRIV:
return RsaPrivateKey.generate(keySize);
case EC_PRIV:
return EcPrivateKey.generate(keySize);
case RSA_PUB: case DSA_PUB:
throw new KeyczarException(
Messages.getString("KeyczarKey.PublicKeyExport", type));
}
throw new UnsupportedTypeException(type);
}
/**
* Converts a JSON string representation of a KeyczarKey into the appropriate
* KeyczarKey object.
*
* @param type KeyType being read from JSON input
* @param key JSON String representation of a KeyczarKey
* @return KeyczareKey of given type
* @throws KeyczarException if type mismatch with JSON input or unsupported
* key type
*/
static KeyczarKey readKey(KeyType type, String key) throws KeyczarException {
switch (type) {
case AES:
return AesKey.read(key);
case HMAC_SHA1:
return HmacKey.read(key);
case DSA_PRIV:
return DsaPrivateKey.read(key);
case DSA_PUB:
return DsaPublicKey.read(key);
case RSA_PRIV:
return RsaPrivateKey.read(key);
case RSA_PUB:
return RsaPublicKey.read(key);
case EC_PRIV:
return EcPrivateKey.read(key);
case EC_PUB:
return EcPublicKey.read(key);
}
throw new UnsupportedTypeException(type);
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
/**
* Interface for Keyczar Private Keys
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
interface KeyczarPrivateKey {
/**
* Get the public key paired with this private key.
*
* @return KeyczarPublicKey associated with this KeyczarPrivateKey
*/
KeyczarPublicKey getPublic();
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
/**
* A placeholder public key class. We would use an interface, except want public
* keys to be instances of KeyczarKeys
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
abstract class KeyczarPublicKey extends KeyczarKey {
// Nothing here
}

View file

@ -0,0 +1,443 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.keyczar.enums.Command;
import org.keyczar.enums.Flag;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.enums.KeyStatus;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Command line tool for generating Keyczar key files. The following commands
* are supported:
* <ul>
* <li>create: create a new key store
* <li>addkey: add new key to existing store
* <li>pubkey: export a public key set from existing private key store
* <li>promote: promote status of a key version in existing store
* <li>demote: demote status of a key version in existing store
* <li>revoke: revoke key version in existing store (if scheduled to be)
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public class KeyczarTool {
static MockKeyczarReader mock = null;
/**
* Sets the mock KeyczarReader used only for testing.
*
* @param reader
*/
public static void setReader(MockKeyczarReader reader) {
mock = reader;
}
/**
* Returns a mock for testing purposes
*
* @return A mock KeyCzar reader
*/
public static MockKeyczarReader getMock() {
return mock;
}
/**
* Uses setFlags() to parse command line arguments and delegates to the
* appropriate command function or prints the usage instructions if command
* syntax is invalid.
*
* @param args from the command line
*/
public static void main(String[] args){
if (args.length == 0) {
printUsage();
} else {
try {
Command c = Command.getCommand(args[0]);
HashMap<Flag, String> flagMap = new HashMap<Flag, String>();
for (String arg : args) {
if (arg.startsWith("--")) {
arg = arg.substring(2); // Trim off the leading dashes
String[] nameValuePair = arg.split("=");
if (nameValuePair.length > 1) {
Flag f = Flag.getFlag(nameValuePair[0]);
flagMap.put(f, nameValuePair[1]);
}
}
}
// All commands need a location.
String locationFlag = flagMap.get(Flag.LOCATION);
if (locationFlag != null && !locationFlag.endsWith(File.separator)) {
locationFlag += File.separator;
}
switch (c) {
case CREATE:
String nameFlag = flagMap.get(Flag.NAME);
KeyPurpose purposeFlag =
KeyPurpose.getPurpose(flagMap.get(Flag.PURPOSE));
String asymmetricFlag = flagMap.get(Flag.ASYMMETRIC);
create(locationFlag, nameFlag, purposeFlag, asymmetricFlag); break;
case ADDKEY:
KeyStatus statusFlag = KeyStatus.getStatus(
flagMap.get(Flag.STATUS));
String crypterFlag = flagMap.get(Flag.CRYPTER);
int sizeFlag = -1;
if (flagMap.containsKey(Flag.SIZE)) {
sizeFlag = Integer.parseInt(flagMap.get(Flag.SIZE));
}
addKey(locationFlag, statusFlag, crypterFlag, sizeFlag);
break;
case PUBKEY:
publicKeys(locationFlag, flagMap.get(Flag.DESTINATION));
break;
case PROMOTE:
promote(locationFlag, Integer.parseInt(flagMap.get(Flag.VERSION)));
break;
case DEMOTE:
demote(locationFlag, Integer.parseInt(flagMap.get(Flag.VERSION)));
break;
case REVOKE:
revoke(locationFlag, Integer.parseInt(flagMap.get(Flag.VERSION)));
break;
case USEKEY:
if (args.length > 2) {
useKey(args[1], locationFlag, flagMap.get(Flag.DESTINATION),
flagMap.get(Flag.CRYPTER));
} else {
printUsage();
}
break;
}
} catch (NumberFormatException e) {
e.printStackTrace();
printUsage();
} catch (IllegalArgumentException e) {
e.printStackTrace();
printUsage();
} catch (NullPointerException e) {
e.printStackTrace();
printUsage();
} catch (KeyczarException e) {
e.printStackTrace();
printUsage();
}
}
}
private static void useKey(String msg, String locationFlag,
String destinationFlag, String crypterFlag) throws KeyczarException {
GenericKeyczar genericKeyczar =
createGenericKeyczar(locationFlag, crypterFlag);
if (destinationFlag == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefinePublic"));
}
String answer = "";
KeyczarReader reader = new KeyczarFileReader(locationFlag);
if (crypterFlag != null) {
Crypter keyCrypter = new Crypter(crypterFlag);
reader = new KeyczarEncryptedReader(reader, keyCrypter);
}
switch (genericKeyczar.getMetadata().getPurpose()) {
case DECRYPT_AND_ENCRYPT:
Crypter crypter = new Crypter(reader);
answer = crypter.encrypt(msg);
break;
case SIGN_AND_VERIFY:
Signer signer = new Signer(reader);
answer = signer.sign(msg);
break;
default:
throw new KeyczarException(
Messages.getString("KeyczarTool.UnsupportedPurpose",
genericKeyczar.getMetadata().getPurpose()));
}
genericKeyczar.writeFile(answer, destinationFlag);
}
/**
* Adds key of given status to key set and pushes update to meta file.
* Requires location and status flags.
* @param sizeFlag
* @param crypterFlag
* @param statusFlag
* @param locationFlag
*
* @throws KeyczarException if location flag is not set or
* key type is unsupported
*/
private static void addKey(String locationFlag, KeyStatus statusFlag,
String crypterFlag, int sizeFlag) throws KeyczarException {
GenericKeyczar genericKeyczar =
createGenericKeyczar(locationFlag, crypterFlag);
if (sizeFlag == -1) { // use default size
genericKeyczar.addVersion(statusFlag);
} else { // use given size
genericKeyczar.addVersion(statusFlag, sizeFlag);
}
if (crypterFlag != null) {
Encrypter encrypter = new Encrypter(crypterFlag);
updateGenericKeyczar(genericKeyczar, encrypter, locationFlag);
} else {
updateGenericKeyczar(genericKeyczar, locationFlag);
}
}
/**
* Creates a new KeyMetadata object, deciding its name, purpose and type
* based on command line flags. Outputs its JSON representation in a file
* named meta in the directory given by the location flag.
* @param asymmetricFlag
* @param purposeFlag
* @param nameFlag
* @param locationFlag
*
* @throws KeyczarException if location or purpose flags are not set
*/
private static void create(String locationFlag, String nameFlag,
KeyPurpose purposeFlag, String asymmetricFlag) throws KeyczarException {
KeyMetadata kmd = null;
if (purposeFlag == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefinePurpose"));
}
switch (purposeFlag) {
case TEST:
kmd = new KeyMetadata(nameFlag, KeyPurpose.TEST, KeyType.TEST);
break;
case SIGN_AND_VERIFY:
if (asymmetricFlag != null) {
if (asymmetricFlag.equalsIgnoreCase("rsa")) {
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.RSA_PRIV);
} else if (asymmetricFlag.equalsIgnoreCase("ec")) {
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.EC_PRIV);
} else { // Default to DSA
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.DSA_PRIV);
}
} else { // HMAC-SHA1
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.HMAC_SHA1);
}
break;
case DECRYPT_AND_ENCRYPT:
if (asymmetricFlag != null) { // Default to RSA
kmd = new KeyMetadata(nameFlag, KeyPurpose.DECRYPT_AND_ENCRYPT,
KeyType.RSA_PRIV);
} else { // AES
kmd = new KeyMetadata(nameFlag, KeyPurpose.DECRYPT_AND_ENCRYPT,
KeyType.AES);
}
break;
}
if (kmd == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.UnsupportedPurpose", purposeFlag));
}
if (mock == null) {
if (locationFlag == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefineLocation"));
}
File file = new File(locationFlag + KeyczarFileReader.META_FILE);
if (file.exists()) {
throw new KeyczarException(
Messages.getString("KeyczarTool.FileExists", file));
}
try {
FileOutputStream metaOutput = new FileOutputStream(file);
metaOutput.write(kmd.toString().getBytes());
metaOutput.close();
} catch (IOException e) {
throw new KeyczarException(Messages.getString(
"KeyczarTool.UnableToWrite", file.toString()), e);
}
} else { // for testing purposes, update mock kmd
mock.setMetadata(kmd);
}
}
/**
* If the version flag is set, promotes the status of given key version.
* Pushes update to meta file. Requires location and version flags.
* @param versionFlag The version to promote
* @param locationFlag The location of the key set
*
* @throws KeyczarException if location or version flag is not set
* or promotion is illegal.
*/
private static void promote(String locationFlag, int versionFlag)
throws KeyczarException {
if (versionFlag < 0) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MissingVersion"));
}
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.promote(versionFlag);
updateGenericKeyczar(genericKeyczar, locationFlag);
}
/**
* If the version flag is set, demotes the status of given key version.
* Pushes update to meta file. Requires location and version flags.
* @param versionFlag The verion to demote
* @param locationFlag The location of the key set
*
* @throws KeyczarException if location or version flag is not set
* or demotion is illegal.
*/
private static void demote(String locationFlag, int versionFlag)
throws KeyczarException {
if (versionFlag < 0) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MissingVersion"));
}
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.demote(versionFlag);
updateGenericKeyczar(genericKeyczar, locationFlag);
}
/**
* Creates and exports public key files to given destination based on
* private key set at given location.
* @param destinationFlag Destionation of public keys
* @param locationFlag Location of private key set
*
* @throws KeyczarException if location or destination flag is not set.
*/
private static void publicKeys(String locationFlag, String destinationFlag)
throws KeyczarException {
if (mock == null && destinationFlag == null) { // only if not testing
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefineDestination"));
}
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.publicKeyExport(destinationFlag);
}
/**
* If the version flag is set, revokes the key of the given version.
* Pushes update to meta file. Deletes old key file. Requires location
* and version flags.
* @param versionFlag The version to revoke
* @param locationFlag The location of the key set
*
* @throws KeyczarException if location or version flag is not set or if
* unable to delete revoked key file.
*/
private static void revoke(String locationFlag, int versionFlag)
throws KeyczarException {
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.revoke(versionFlag);
// update meta files, key files
updateGenericKeyczar(genericKeyczar, locationFlag);
if (mock == null) { // not necessary for testing
File revokedVersion = new File(locationFlag + versionFlag);
if (!revokedVersion.delete()) { // delete old key file
throw new KeyczarException(
Messages.getString("KeyczarTool.UnableToDelete"));
}
} else {
mock.removeKey(versionFlag);
}
}
/**
* Prints the usage instructions with list of commands and flags.
*/
private static void printUsage() {
ArrayList<String> usageParams = new ArrayList<String>();
for (Command c : Command.values()) {
usageParams.add(c.toString());
}
for (Flag f : Flag.values()) {
usageParams.add(f.toString());
}
System.out.println(
Messages.getString("KeyczarTool.Usage", usageParams.toArray()));
}
private static GenericKeyczar createGenericKeyczar(String locationFlag)
throws KeyczarException {
return createGenericKeyczar(locationFlag, null);
}
/**
* Creates a GenericKeyczar object based on locationFlag if it is set.
* Alternatively, it can use the mock KeyczarReader if it is set.
* @param locationFlag The location of the key set
* @param crypterFlag The location of a crypter to decrypt the key set
* @return GenericKeyczar if locationFlag set
* @throws KeyczarException if locationFlag not set
*/
private static GenericKeyczar createGenericKeyczar(String locationFlag,
String crypterFlag) throws KeyczarException {
if (mock != null) {
return new GenericKeyczar(mock);
}
if (locationFlag == null) {
throw new KeyczarException(Messages.getString("KeyczarTool.NeedLocation",
Messages.getString("KeyczarTool.Location")));
}
KeyczarReader reader = new KeyczarFileReader(locationFlag);
if (crypterFlag != null) {
Crypter keyDecrypter = new Crypter(crypterFlag);
reader = new KeyczarEncryptedReader(reader, keyDecrypter);
}
return new GenericKeyczar(reader);
}
private static void updateGenericKeyczar(GenericKeyczar genericKeyczar,
String locationFlag) throws KeyczarException {
updateGenericKeyczar(genericKeyczar, null, locationFlag);
}
private static void updateGenericKeyczar(GenericKeyczar genericKeyczar,
Encrypter encrypter, String locationFlag) throws KeyczarException {
if (mock != null) {
mock.setMetadata(genericKeyczar.getMetadata()); // update metadata
for (KeyVersion version : genericKeyczar.getVersions()) {
mock.setKey(version.getVersionNumber(), genericKeyczar.getKey(version));
} // update key data
} else if (encrypter != null) {
genericKeyczar.writeEncrypted(locationFlag, encrypter);
} else {
genericKeyczar.write(locationFlag);
}
}
}

View file

@ -0,0 +1,118 @@
package org.keyczar;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.enums.KeyStatus;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.BadVersionException;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.util.Util;
import java.util.HashMap;
import java.util.Map;
/**
* A mock representation of a KeyczarReader used for testing.
*
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public class MockKeyczarReader implements KeyczarReader {
private Map<Integer, KeyczarKey> keys, publicKeys; // link version #s to keys
private KeyMetadata kmd, publicKmd;
public MockKeyczarReader(String n, KeyPurpose p, KeyType t) {
kmd = new KeyMetadata(n, p, t);
publicKmd = null;
keys = new HashMap<Integer, KeyczarKey>();
publicKeys = new HashMap<Integer, KeyczarKey>();
}
public String getKey(int version) throws KeyczarException {
if (keys.containsKey(version)) {
return keys.get(version).toString();
} else {
throw new BadVersionException((byte) version);
}
}
public String getMetadata() {
return Util.gson().toJson(kmd);
}
public void setMetadata(KeyMetadata newKmd) {
kmd = newKmd;
}
public void setPublicKeyMetadata(KeyMetadata publicKmd) {
this.publicKmd = publicKmd;
}
public void setKey(int versionNumber, KeyczarKey key) {
keys.put(versionNumber, key);
}
public void setPublicKey(int versionNumber, KeyczarKey key) {
publicKeys.put(versionNumber, key);
}
public void removeKey(int versionNumber) {
keys.remove(versionNumber);
}
public String name() {
return kmd.getName();
}
public KeyPurpose purpose() {
return kmd.getPurpose();
}
public KeyType type() {
return kmd.getType();
}
public boolean addKey(int versionNumber, KeyStatus status)
throws KeyczarException {
KeyczarKey key = KeyczarKey.genKey(kmd.getType());
keys.put(versionNumber, key);
return kmd.addVersion(new KeyVersion(versionNumber, status, false));
}
public boolean addKey(int versionNumber, KeyStatus status, int size)
throws KeyczarException {
KeyczarKey key = KeyczarKey.genKey(kmd.getType(), size);
keys.put(versionNumber, key);
return kmd.addVersion(new KeyVersion(versionNumber, status, false));
}
public KeyStatus getStatus(int versionNumber) {
return kmd.getVersion(versionNumber).getStatus();
}
public boolean existsVersion(int versionNumber) {
return keys.containsKey(versionNumber);
}
public boolean exportedPublicKeySet() {
return publicKmd != null;
}
public boolean hasPublicKey(int versionNumber) {
KeyczarPrivateKey privateKey = (KeyczarPrivateKey) keys.get(versionNumber);
KeyczarPublicKey publicKey =
(KeyczarPublicKey) publicKeys.get(versionNumber);
return privateKey != null && publicKey != null &&
publicKey.equals(privateKey.getPublic());
}
public int numKeys() {
return keys.size();
}
public int getKeySize(int versionNumber) {
return keys.get(versionNumber).size();
}
}

View file

@ -0,0 +1,286 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.DecryptingStream;
import org.keyczar.interfaces.EncryptingStream;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;
/**
* Wrapping class for RSA Private Keys
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class RsaPrivateKey extends KeyczarKey implements KeyczarPrivateKey {
private static final String CRYPT_ALGORITHM =
"RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING";
private static final String KEY_GEN_ALGORITHM = "RSA";
@Expose private RsaPublicKey publicKey;
@Expose private String privateExponent;
@Expose private String primeP;
@Expose private String primeQ;
@Expose private String primeExponentP;
@Expose private String primeExponentQ;
@Expose private String crtCoefficient;
private static final String SIG_ALGORITHM = "SHA1withRSA";
private RSAPrivateCrtKey jcePrivateKey;
private RsaPrivateKey() {
publicKey = new RsaPublicKey();
}
@Override
Stream getStream() throws KeyczarException {
return new RsaPrivateStream();
}
@Override
KeyType getType() {
return KeyType.RSA_PRIV;
}
@Override
byte[] hash() {
return publicKey.hash();
}
static RsaPrivateKey read(String input) throws KeyczarException {
RsaPrivateKey key = Util.gson().fromJson(input, RsaPrivateKey.class);
key.init();
return key;
}
static RsaPrivateKey generate() throws KeyczarException {
return generate(KeyType.RSA_PRIV.defaultSize());
}
public KeyczarPublicKey getPublic() {
return publicKey;
}
private void init() throws KeyczarException {
// Read all the JSON fields and use it to instantiate a RSAPrivateCrtKey
try {
KeyFactory factory = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
BigInteger mod = new BigInteger(Base64Coder.decode(publicKey.modulus));
BigInteger pubExp =
new BigInteger(Base64Coder.decode(publicKey.publicExponent));
// Set the public key values
publicKey.set(mod, pubExp);
BigInteger privExp = new BigInteger(Base64Coder.decode(privateExponent));
BigInteger p = new BigInteger(Base64Coder.decode(primeP));
BigInteger q = new BigInteger(Base64Coder.decode(primeQ));
BigInteger expP = new BigInteger(Base64Coder.decode(primeExponentP));
BigInteger expQ = new BigInteger(Base64Coder.decode(primeExponentQ));
BigInteger crt = new BigInteger(Base64Coder.decode(crtCoefficient));
RSAPrivateCrtKeySpec spec =
new RSAPrivateCrtKeySpec(mod, pubExp, privExp, p, q, expP, expQ, crt);
jcePrivateKey = (RSAPrivateCrtKey) factory.generatePrivate(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
static RsaPrivateKey generate(int keySize) throws KeyczarException {
RsaPrivateKey key = new RsaPrivateKey();
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_GEN_ALGORITHM);
key.size = keySize;
key.publicKey.size = key.size;
kpg.initialize(key.size());
KeyPair pair = kpg.generateKeyPair();
key.jcePrivateKey = (RSAPrivateCrtKey) pair.getPrivate();
key.publicKey.set(key.jcePrivateKey.getModulus(),
key.jcePrivateKey.getPublicExponent());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
// Set all the JSON fields for this RSA Private CRT key
key.privateExponent =
Base64Coder.encode(key.jcePrivateKey.getPrivateExponent().toByteArray());
key.primeP =
Base64Coder.encode(key.jcePrivateKey.getPrimeP().toByteArray());
key.primeQ =
Base64Coder.encode(key.jcePrivateKey.getPrimeQ().toByteArray());
key.primeExponentP =
Base64Coder.encode(key.jcePrivateKey.getPrimeExponentP().toByteArray());
key.primeExponentQ =
Base64Coder.encode(key.jcePrivateKey.getPrimeExponentQ().toByteArray());
key.crtCoefficient =
Base64Coder.encode(key.jcePrivateKey.getCrtCoefficient().toByteArray());
return key;
}
private class RsaPrivateStream implements SigningStream, VerifyingStream,
DecryptingStream, EncryptingStream {
private Cipher cipher;
private EncryptingStream encryptingStream;
private Signature signature;
private VerifyingStream verifyingStream;
public RsaPrivateStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
verifyingStream = (VerifyingStream) publicKey.getStream();
cipher = Cipher.getInstance(CRYPT_ALGORITHM);
encryptingStream = (EncryptingStream) publicKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public int doFinalDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.doFinal(input, output);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int doFinalEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
return encryptingStream.doFinalEncrypt(input, output);
}
public SigningStream getSigningStream() throws KeyczarException {
return encryptingStream.getSigningStream();
}
public VerifyingStream getVerifyingStream() {
return new VerifyingStream() {
public int digestSize() {
return 0;
}
public void initVerify() {
// Do nothing
}
public void updateVerify(ByteBuffer input) {
// Do nothing
}
public boolean verify(ByteBuffer signature) {
// Do nothing
return true;
}
};
}
public void initDecrypt(ByteBuffer input) throws KeyczarException {
try {
cipher.init(Cipher.DECRYPT_MODE, jcePrivateKey);
} catch (InvalidKeyException e) {
throw new KeyczarException(e);
}
}
public int initEncrypt(ByteBuffer output) throws KeyczarException {
return encryptingStream.initEncrypt(output);
}
public void initSign() throws KeyczarException {
try {
signature.initSign(jcePrivateKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
verifyingStream.initVerify();
}
public int maxOutputSize(int inputLen) {
return getType().getOutputSize() * 2;
}
public void sign(ByteBuffer output) throws KeyczarException {
try {
byte[] sig = signature.sign();
output.put(sig);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public int updateDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.update(input, output);
} catch (ShortBufferException e) {
throw new KeyczarException(e);
}
}
public int updateEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
return encryptingStream.updateEncrypt(input, output);
}
public void updateSign(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
verifyingStream.updateVerify(input);
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
return verifyingStream.verify(sig);
}
}
}

View file

@ -0,0 +1,206 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import com.google.gson.annotations.Expose;
import org.keyczar.enums.KeyType;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.UnsupportedTypeException;
import org.keyczar.interfaces.EncryptingStream;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;
/**
* Wrapping class for RSA Public Keys. These must be exported from existing RSA
* private key sets.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
class RsaPublicKey extends KeyczarPublicKey {
private static final String CRYPT_ALGORITHM =
"RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING";
private static final String KEY_GEN_ALGORITHM = "RSA";
private static final String SIG_ALGORITHM = "SHA1withRSA";
private RSAPublicKey jcePublicKey;
@Expose String modulus;
@Expose String publicExponent;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
@Override
public byte[] hash() {
return hash;
}
@Override
Stream getStream() throws KeyczarException {
return new RsaStream();
}
@Override
KeyType getType() {
return KeyType.RSA_PUB;
}
void set(BigInteger mod, BigInteger pubExp) throws KeyczarException {
modulus = Base64Coder.encode(mod.toByteArray());
publicExponent = Base64Coder.encode(pubExp.toByteArray());
init();
}
void init() throws KeyczarException {
byte[] modBytes = Base64Coder.decode(modulus);
byte[] pubExpBytes = Base64Coder.decode(publicExponent);
BigInteger mod = new BigInteger(modBytes);
BigInteger pubExp = new BigInteger(pubExpBytes);
// Sets the JCE Public key value
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
RSAPublicKeySpec spec = new RSAPublicKeySpec(mod, pubExp);
jcePublicKey = (RSAPublicKey) kf.generatePublic(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
byte[] fullHash = Util.prefixHash(Util.stripLeadingZeros(modBytes),
Util.stripLeadingZeros(pubExpBytes));
System.arraycopy(fullHash, 0, hash, 0, hash.length);
}
static RsaPublicKey read(String input) throws KeyczarException {
RsaPublicKey key = Util.gson().fromJson(input, RsaPublicKey.class);
if (key.getType() != KeyType.RSA_PUB) {
throw new UnsupportedTypeException(key.getType());
}
key.init();
return key;
}
private class RsaStream implements VerifyingStream, EncryptingStream {
private Cipher cipher;
private Signature signature;
public RsaStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
cipher = Cipher.getInstance(CRYPT_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public int doFinalEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.doFinal(input, output);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public SigningStream getSigningStream() {
return new SigningStream() {
public int digestSize() {
return 0;
}
public void initSign() {
// Do nothing
}
public void sign(ByteBuffer output) {
// Do nothing
}
public void updateSign(ByteBuffer input) {
// Do nothing
}
};
}
public int initEncrypt(ByteBuffer output) throws KeyczarException {
try {
cipher.init(Cipher.ENCRYPT_MODE, jcePublicKey);
} catch (InvalidKeyException e) {
throw new KeyczarException(e);
}
return 0;
}
public void initVerify() throws KeyczarException {
try {
signature.initVerify(jcePublicKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int maxOutputSize(int inputLen) {
return getType().getOutputSize();
}
public int updateEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.update(input, output);
} catch (ShortBufferException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
try {
return signature.verify(sig.array(), sig.position(), sig.limit()
- sig.position());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
}
}

View file

@ -0,0 +1,198 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.NoPrimaryKeyException;
import org.keyczar.exceptions.ShortBufferException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
/**
* Signers may both sign and verify data using sets of symmetric or private
* keys. Sets of public keys may only be used with {@link Verifier} objects.
*
* {@link Signer} objects should be used with symmetric or private key sets to
* generate signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Signer extends Verifier {
static final int TIMESTAMP_SIZE = 8;
private static final Logger SIGNER_LOGGER = Logger.getLogger(Signer.class);
private final StreamQueue<SigningStream> SIGN_QUEUE =
new StreamQueue<SigningStream>();
/**
* Initialize a new Signer with a KeyczarReader. The corresponding key set
* must have a purpose {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Signer(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Signer with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Signer(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Returns the size of signatures produced by this Signer.
*
* @return The size of signatures produced by this Signer.
* @throws KeyczarException If this Signer does not have a primary or a
* JCE exception occurs.
*/
public int digestSize() throws KeyczarException {
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
return HEADER_SIZE + ((SigningStream) signingKey.getStream()).digestSize();
}
/**
* Sign the given input and return a signature.
*
* @param input The input to sign.
* @return A byte array representation of a signature.
* @throws KeyczarException If this Signer does not have a primary or a
* JCE exception occurs.
*/
public byte[] sign(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(digestSize());
sign(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Sign the given input and write the signature to the given ByteBuffer
*
* @param input The input to sign.
* @param output The ByteBuffer to write the signature in.
* @throws KeyczarException If this Signer does not have a primary or a
* JCE exception occurs.
*/
public void sign(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
sign(input, null, 0, output);
}
/**
* This allows other classes in the package to pass in hidden data and/or
* expiration data to be signed.
*
* @param input The input to be signed
* @param hidden Hidden data to be signed
* @param expirationTime The expiration time of this signature
* @param output The destination of this signature
* @throws KeyczarException
*/
void sign(ByteBuffer input, ByteBuffer hidden, long expirationTime,
ByteBuffer output) throws KeyczarException {
SIGNER_LOGGER.info(Messages.getString("Signer.Signing", input.remaining()));
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
SigningStream stream = SIGN_QUEUE.poll();
if (stream == null) {
stream = (SigningStream) signingKey.getStream();
}
int spaceNeeded = digestSize();
if (expirationTime > 0) {
spaceNeeded += TIMESTAMP_SIZE;
}
if (output.capacity() < spaceNeeded) {
throw new ShortBufferException(output.capacity(), spaceNeeded);
}
ByteBuffer header = ByteBuffer.allocate(HEADER_SIZE);
signingKey.copyHeader(header);
header.rewind();
stream.initSign();
// Sign the header and write it to the output buffer
output.mark();
output.put(header);
if (expirationTime > 0) {
// Write an expiration time following the header and sign it.
ByteBuffer expiration = ByteBuffer.wrap(Util.fromLong(expirationTime));
output.put(expiration);
expiration.rewind();
stream.updateSign(expiration);
}
if (hidden != null && hidden.remaining() > 0) {
// Sign any hidden data
stream.updateSign(hidden);
}
// Sign the input data
stream.updateSign(input);
// Sign the version byte
stream.updateSign(ByteBuffer.wrap(FORMAT_BYTES));
// Write the signature to the output
stream.sign(output);
output.limit(output.position());
SIGN_QUEUE.add(stream);
}
/**
* Signs the given input String and return the output as a web-safe Base64
* encoded String.
*
* @param input The input String to sign.
* @return A web-safe Base64-encoded representation of a signature on the
* input.
* @throws KeyczarException
*/
public String sign(String input) throws KeyczarException {
return Base64Coder.encode(sign(input.getBytes()));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.SIGN_AND_VERIFY;
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.keyczar.interfaces.Stream;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Caches StreamQueue objects for KeyczarKeys so they can reused.
*
* @author steveweis@gmail.com (Steve Weis)
*
* @param <T>
*/
class StreamCache<T extends Stream> {
private final ConcurrentHashMap<KeyczarKey, StreamQueue<T>> cacheMap =
new ConcurrentHashMap<KeyczarKey, StreamQueue<T>>();
void put(KeyczarKey key, T s) {
getQueue(key).add(s);
}
T get(KeyczarKey key) {
return getQueue(key).poll();
}
StreamQueue<T> getQueue(KeyczarKey key) {
StreamQueue<T> queue = cacheMap.get(key);
if (queue != null) {
return queue;
}
StreamQueue<T> freshQueue = new StreamQueue<T>();
queue = cacheMap.putIfAbsent(key, freshQueue);
if (queue != null) {
// Another thread already inserted a fresh queue with this key.
return queue;
}
return freshQueue;
}
}
/**
* A thread-safe queue for Streams and their derived classes.
*
* @author steveweis@gmail.com (Steve Weis)
*
* @param <T>
*/
class StreamQueue<T extends Stream> extends ConcurrentLinkedQueue<T> {
}

View file

@ -0,0 +1,128 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Timeout signers can generate signatures that are valid until a specified
* expiration time. Timeout signatures are verified by
* {@link org.keyczar.TimeoutVerifier} objects.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class TimeoutSigner extends TimeoutVerifier {
private Signer signer;
/**
* Initialize a new TimeoutSigner with a KeyczarReader.
* The corresponding key set must have a purpose
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutSigner(KeyczarReader reader) throws KeyczarException {
this.signer = new Signer(reader);
setVerifier(this.signer);
}
/**
* Initialize a new TimeoutSigner with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding
* key set must have a purpose of
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutSigner(String fileLocation) throws KeyczarException {
this.signer = new Signer(fileLocation);
setVerifier(this.signer);
}
/**
* Initialize a new TimeoutSigner with a Signer object.
*
* @param signer Signer to be used for timeout signatures
*/
public TimeoutSigner(Signer signer){
this.signer = signer;
setVerifier(this.signer);
}
/**
* Sign the given input and return a signature that is valid until the
* expiration time given as the number of milliseconds since "the epoch"
* of 1/1/1970 00:00:00 GMT
*
* @param input The input to be signed
* @param expirationTime The expiration time in milliseconds since 1/1/1970
* 00:00:00 GMT
* @return The signature as a web safe Base64 string
* @throws KeyczarException
*/
public String timeoutSign(String input, long expirationTime)
throws KeyczarException {
return Base64Coder.encode(timeoutSign(input.getBytes(), expirationTime));
}
/**
* Sign the given input and return a signature that is valid until the
* expiration time given as the number of milliseconds since "the epoch"
* of 1/1/1970 00:00:00 GMT
*
* @param input The input to be signed
* @param expirationTime The expiration time in milliseconds since 1/1/1970
* 00:00:00 GMT
* @return The signature
* @throws KeyczarException
*/
public byte[] timeoutSign(byte[] input, long expirationTime)
throws KeyczarException {
ByteBuffer output =
ByteBuffer.allocate(signer.digestSize() + Signer.TIMESTAMP_SIZE);
timeoutSign(ByteBuffer.wrap(input), expirationTime, output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Signs the input and produces a signature that is valid until the
* expiration time given as the number of milliseconds since "the epoch"
* of 1/1/1970 00:00:00 GMT
*
* @param input The input to be signed
* @param expirationTime The expiration time in milliseconds since 1/1/1970
* 00:00:00 GMT
* @param output The destination of this signature
* @throws KeyczarException
*/
public void timeoutSign(ByteBuffer input, long expirationTime,
ByteBuffer output) throws KeyczarException {
signer.sign(input, null, expirationTime, output);
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.ShortSignatureException;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.util.Date;
/**
* TimeoutVerifiers verify timeout signatures generated by
* {@link org.keyczar.TimeoutSigner} objects
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class TimeoutVerifier {
private Verifier verifier;
TimeoutVerifier() {
// Do nothing here.
}
/**
* Initialize a new TimeoutVerifier with a KeyczarReader.
* The corresponding key set must have a purpose
* {@link org.keyczar.enums.KeyPurpose#VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutVerifier(KeyczarReader reader) throws KeyczarException {
setVerifier(new Verifier(reader));
}
/**
* Initialize a new TimeoutVerifier with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding
* key set must have a purpose of
* {@link org.keyczar.enums.KeyPurpose#VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutVerifier(String fileLocation) throws KeyczarException {
setVerifier(new Verifier(fileLocation));
}
/**
* Initialize a new TimeoutVerifier with a Verifier object.
*
* @param verifier Signer to be used for timeout signatures
*/
public TimeoutVerifier(Verifier verifier) {
setVerifier(verifier);
}
void setVerifier(Verifier verifier) {
this.verifier = verifier;
}
/**
* Verifies the timeout signature on the given String
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(String data, String signature) throws KeyczarException {
return verify(data.getBytes(), Base64Coder.decode(signature));
}
/**
* Verifies a timeout signature on the given byte array of data
*
* @param data The data to verify the signature on
* @param signature The timeput signture to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(byte[] data, byte[] signature) throws KeyczarException {
return verify(ByteBuffer.wrap(data), ByteBuffer.wrap(signature));
}
/**
* Verify the timeout signature on the given data
*
* @param data
* @param timeoutSignature
* @return A boolean value indicating whether the timeout signature verified.
* This will be false if the signature has expired.
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(ByteBuffer data, ByteBuffer timeoutSignature)
throws KeyczarException {
if (timeoutSignature.remaining() < Keyczar.HEADER_SIZE + Signer.TIMESTAMP_SIZE) {
throw new ShortSignatureException(timeoutSignature.remaining());
}
byte[] header = new byte[Keyczar.HEADER_SIZE];
timeoutSignature.get(header);
// Get the timestamp and check that it has not expired
byte[] timestamp = new byte[Signer.TIMESTAMP_SIZE];
timeoutSignature.get(timestamp);
long expirationTime = Util.toLong(timestamp);
Date expiration = new Date(expirationTime);
Date now = new Date();
if (now.after(expiration)) {
return false;
}
ByteBuffer slicedSignature =
ByteBuffer.allocate(Keyczar.HEADER_SIZE + timeoutSignature.remaining());
slicedSignature.put(header);
slicedSignature.put(timeoutSignature);
slicedSignature.rewind();
// The timeout is signed in a timeout signature. Prepend it to the data and
// pass it to the parent implementation in Verfier
ByteBuffer prependedData =
ByteBuffer.allocate(Signer.TIMESTAMP_SIZE + data.remaining());
prependedData.put(timestamp);
prependedData.put(data);
prependedData.rewind();
return verifier.verify(prependedData, slicedSignature);
}
}

View file

@ -0,0 +1,163 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.NoPrimaryKeyException;
import org.keyczar.exceptions.ShortBufferException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.util.Base64Coder;
import org.keyczar.util.Util;
import java.nio.ByteBuffer;
/**
* UnversionedSigners may both sign and verify data using sets of symmetric or
* private keys. Sets of public keys may only be used with {@link Verifier}
* objects.
*
* UnversionedSigners do not include any key versioning in their outputs. They
* will return standard signatures (i.e. HMAC-SHA1, RSA-SHA1, DSA-SHA1).
*
* {@link UnversionedSigner} objects should be used with symmetric or private key sets to
* generate signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class UnversionedSigner extends UnversionedVerifier {
static final int TIMESTAMP_SIZE = 8;
private static final Logger SIGNER_LOGGER = Logger.getLogger(UnversionedSigner.class);
private final StreamQueue<SigningStream> SIGN_QUEUE =
new StreamQueue<SigningStream>();
/**
* Initialize a new UnversionedSigner with a KeyczarReader. The corresponding
* key set must have a purpose
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedSigner(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new UnversionedSigner with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding key
* set must have a purpose of
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedSigner(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Returns the size of signatures produced by this UnversionedSigner.
*
* @return The size of signatures produced by this UnversionedSigner.
* @throws KeyczarException If this UnversionedSigner does not have a primary
* or a JCE exception occurs.
*/
public int digestSize() throws KeyczarException {
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
return ((SigningStream) signingKey.getStream()).digestSize();
}
/**
* Sign the given input and return a signature.
*
* @param input The input to sign.
* @return A byte array representation of a signature.
* @throws KeyczarException If this UnversionedSigner does not have a primary
* or a JCE exception occurs.
*/
public byte[] sign(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(digestSize());
sign(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* This allows other classes in the package to pass in hidden data and/or
* expiration data to be signed.
*
* @param input The input to be signed
* @param output The destination of this signature
* @throws KeyczarException
*/
void sign(ByteBuffer input, ByteBuffer output) throws KeyczarException {
SIGNER_LOGGER.info(Messages.getString("Signer.Signing", input.remaining()));
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
SigningStream stream = SIGN_QUEUE.poll();
if (stream == null) {
stream = (SigningStream) signingKey.getStream();
}
int spaceNeeded = digestSize();
if (output.capacity() < spaceNeeded) {
throw new ShortBufferException(output.capacity(), spaceNeeded);
}
stream.initSign();
// Sign the header and write it to the output buffer
output.mark();
// Sign the input data
stream.updateSign(input);
// Write the signature to the output
stream.sign(output);
output.limit(output.position());
SIGN_QUEUE.add(stream);
}
/**
* Signs the given input String and return the output as a web-safe Base64
* encoded String.
*
* @param input The input String to sign.
* @return A web-safe Base64-encoded representation of a signature on the
* input.
* @throws KeyczarException
*/
public String sign(String input) throws KeyczarException {
return Base64Coder.encode(sign(input.getBytes()));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.SIGN_AND_VERIFY;
}
}

View file

@ -0,0 +1,153 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.BadVersionException;
import org.keyczar.exceptions.KeyNotFoundException;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.ShortSignatureException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.Map.Entry;
/**
* Unversioned Verifiers are used strictly to verify standard signatures
* (i.e. HMAC-SHA1, DSA-SHA1, RSA-SHA1) with no key version information.
* Typically, UnversionedVerifiers will read sets of public keys, although may
* also be instantiated with sets of symmetric or private keys.
*
* Since UnversionedVerifiers verify standard signatures, they will try all keys
* in a set until one verifies.
*
* {@link UnversionedSigner} objects should be used with symmetric or private
* key sets to generate unversioned signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class UnversionedVerifier extends Keyczar {
private static final Logger VERIFIER_LOGGER =
Logger.getLogger(UnversionedVerifier.class);
private static final StreamCache<VerifyingStream> VERIFY_CACHE
= new StreamCache<VerifyingStream>();
/**
* Initialize a new UnversionedVerifier with a KeyczarReader.
* The corresponding key set must have a purpose of either
* {@link org.keyczar.enums.KeyPurpose#VERIFY} or
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedVerifier(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new UnversionedVerifier with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding key
* set must have a purpose of either
* {@link org.keyczar.enums.KeyPurpose#VERIFY} or
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedVerifier(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Verifies a standard signature on the given byte array of data
*
* @param data The data to verify the signature on
* @param signature The signture to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(byte[] data, byte[] signature) throws KeyczarException {
return verify(ByteBuffer.wrap(data), ByteBuffer.wrap(signature));
}
/**
* Verifies the standard signature on the data stored in the given ByteBuffer.
* This method will try all keys until one of them verifies the signature,
* or else will return false.
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(ByteBuffer data, ByteBuffer signature)
throws KeyczarException {
VERIFIER_LOGGER.info(
Messages.getString("UnversionedVerifier.Verifying", data.remaining()));
// Try to verify the signature with each key in the set.
for (Iterator<Entry<KeyVersion, KeyczarKey>> iter =
versionMap.entrySet().iterator(); iter.hasNext(); ) {
KeyczarKey key = iter.next().getValue();
ByteBuffer dataCopy = data.duplicate();
ByteBuffer signatureCopy = signature.duplicate();
VerifyingStream stream = VERIFY_CACHE.get(key);
if (stream == null) {
stream = (VerifyingStream) key.getStream();
}
stream.initVerify();
stream.updateVerify(dataCopy);
boolean result = stream.verify(signatureCopy);
VERIFY_CACHE.put(key, stream);
if (result) {
return true;
}
}
return false;
}
/**
* Verifies the signature on the given String
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(String data, String signature) throws KeyczarException {
return verify(data.getBytes(), Base64Coder.decode(signature));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return (purpose == KeyPurpose.VERIFY ||
purpose == KeyPurpose.SIGN_AND_VERIFY);
}
}

View file

@ -0,0 +1,154 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar;
import org.apache.log4j.Logger;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.exceptions.BadVersionException;
import org.keyczar.exceptions.KeyNotFoundException;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.exceptions.ShortSignatureException;
import org.keyczar.i18n.Messages;
import org.keyczar.interfaces.KeyczarReader;
import org.keyczar.interfaces.VerifyingStream;
import org.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Verifiers are used strictly to verify signatures. Typically, Verifiers will
* read sets of public keys, although may also be instantiated with sets of
* symmetric or private keys.
*
* {@link Signer} objects should be used with symmetric or private key sets to
* generate signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Verifier extends Keyczar {
private static final Logger VERIFIER_LOGGER =
Logger.getLogger(Verifier.class);
private static final StreamCache<VerifyingStream> VERIFY_CACHE
= new StreamCache<VerifyingStream>();
/**
* Initialize a new Verifier with a KeyczarReader. The corresponding key set
* must have a purpose of either {@link org.keyczar.enums.KeyPurpose#VERIFY} or
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Verifier(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Verifier with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of either
* {@link org.keyczar.enums.KeyPurpose#VERIFY} or
* {@link org.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Verifier(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Verifies a signature on the given byte array of data
*
* @param data The data to verify the signature on
* @param signature The signture to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(byte[] data, byte[] signature) throws KeyczarException {
return verify(ByteBuffer.wrap(data), ByteBuffer.wrap(signature));
}
/**
* Verifies the signature on the data stored in the given ByteBuffer
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(ByteBuffer data, ByteBuffer signature)
throws KeyczarException {
VERIFIER_LOGGER.info(
Messages.getString("Verifier.Verifying", data.remaining()));
if (signature.remaining() < HEADER_SIZE) {
throw new ShortSignatureException(signature.remaining());
}
byte version = signature.get();
if (version != FORMAT_VERSION) {
throw new BadVersionException(version);
}
byte[] hash = new byte[KEY_HASH_SIZE];
signature.get(hash);
KeyczarKey key = getKey(hash);
if (key == null) {
throw new KeyNotFoundException(hash);
}
VerifyingStream stream = VERIFY_CACHE.get(key);
if (stream == null) {
stream = (VerifyingStream) key.getStream();
}
stream.initVerify();
stream.updateVerify(data);
// The signed data is terminated with the current Keyczar format
stream.updateVerify(ByteBuffer.wrap(FORMAT_BYTES));
boolean result = stream.verify(signature);
VERIFY_CACHE.put(key, stream);
return result;
}
/**
* Verifies the signature on the given String
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(String data, String signature) throws KeyczarException {
return verify(data.getBytes(), Base64Coder.decode(signature));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return (purpose == KeyPurpose.VERIFY ||
purpose == KeyPurpose.SIGN_AND_VERIFY);
}
}

View file

@ -0,0 +1,224 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.CipherMode;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.ShortBufferException;
import cz.cvut.keyczar.interfaces.DecryptingStream;
import cz.cvut.keyczar.interfaces.EncryptingStream;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
* Wrapping class for AES keys. Currently the default is to use CBC mode.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class AesKey extends KeyczarKey {
private Key aesKey;
private int blockSize;
private static final String AES_ALGORITHM = "AES";
private static final CipherMode DEFAULT_MODE = CipherMode.CBC;
@Expose private String aesKeyString = "";
@Expose private HmacKey hmacKey = new HmacKey();
@Expose private CipherMode mode = DEFAULT_MODE;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
static AesKey generate() throws KeyczarException {
return generate(KeyType.AES.defaultSize());
}
static AesKey generate(int keySize) throws KeyczarException {
AesKey key = new AesKey();
key.size = keySize;
byte[] aesBytes = Util.rand(key.size() / 8);
key.aesKeyString = Base64Coder.encode(aesBytes);
key.mode = DEFAULT_MODE;
key.hmacKey = HmacKey.generate();
key.init();
return key;
}
@Override
KeyType getType() {
return KeyType.AES;
}
@Override
byte[] hash() {
return hash;
}
static AesKey read(String input) throws KeyczarException {
AesKey key = Util.gson().fromJson(input, AesKey.class);
key.hmacKey.init();
key.init();
return key;
}
private void init() throws KeyczarException {
byte[] aesBytes = Base64Coder.decode(aesKeyString);
aesKey = new SecretKeySpec(aesBytes, AES_ALGORITHM);
blockSize = aesBytes.length;
byte[] fullHash =
Util.hash(Util.fromInt(blockSize), aesBytes, hmacKey.keyBytes());
System.arraycopy(fullHash, 0, hash, 0, hash.length);
}
@Override
Stream getStream() throws KeyczarException {
return new AesStream();
}
private class AesStream implements EncryptingStream, DecryptingStream {
private Cipher encryptingCipher;
private Cipher decryptingCipher;
private SigningStream signStream;
boolean ivRead = false;
public AesStream() throws KeyczarException {
/*
* The JCE Cipher.init() call essentially reallocates a new Cipher object
* We avoid this by initializing two Cipher objects with zero-valued IVs,
* Then passing IVs for CBC mode ourselves. The Ciphers will be cached in
* this stream
*/
IvParameterSpec zeroIv = new IvParameterSpec(new byte[blockSize]);
try {
encryptingCipher = Cipher.getInstance(mode.getMode());
encryptingCipher.init(Cipher.ENCRYPT_MODE, aesKey, zeroIv);
decryptingCipher = Cipher.getInstance(mode.getMode());
decryptingCipher.init(Cipher.DECRYPT_MODE, aesKey, zeroIv);
signStream = (SigningStream) hmacKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public SigningStream getSigningStream() {
return signStream;
}
public VerifyingStream getVerifyingStream() {
return (VerifyingStream) signStream;
}
public void initDecrypt(ByteBuffer input) {
// This will simply decrypt the first block, leaving the CBC Cipher
// ready for the next block of input.
byte[] iv = new byte[blockSize];
input.get(iv);
decryptingCipher.update(iv);
ivRead = true;
}
public int initEncrypt(ByteBuffer output) throws KeyczarException {
// Generate a random value and encrypt it. This will be the IV.
byte[] ivPreImage = new byte[blockSize];
Util.rand(ivPreImage);
try {
return encryptingCipher.update(ByteBuffer.wrap(ivPreImage), output);
} catch (javax.crypto.ShortBufferException e) {
throw new ShortBufferException(e);
}
}
public int updateDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
if (ivRead && input.remaining() >= blockSize) {
// The next output block will be the IV preimage, which we'll discard
byte[] temp = new byte[blockSize];
input.get(temp);
decryptingCipher.update(temp); // discard IV preimage byte array
ivRead = false;
}
try {
return decryptingCipher.update(input, output);
} catch (javax.crypto.ShortBufferException e) {
throw new ShortBufferException(e);
}
}
public int updateEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return encryptingCipher.update(input, output);
} catch (javax.crypto.ShortBufferException e) {
throw new ShortBufferException(e);
}
}
public int doFinalDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
if (ivRead) {
if (input.remaining() == 0) {
// This can occur if someone encrypts an 0-length array
return 0;
}
// The next output block will be the IV preimage, which we'll discard
byte[] temp = new byte[blockSize];
input.get(temp);
decryptingCipher.update(temp); // discard IV preimage byte array
ivRead = false;
}
try {
if (input.remaining() == 0) {
byte[] outputBytes = decryptingCipher.doFinal();
output.put(outputBytes);
return outputBytes.length;
} else {
return decryptingCipher.doFinal(input, output);
}
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int doFinalEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return encryptingCipher.doFinal(input, output);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int maxOutputSize(int inputLen) {
return mode.getOutputSize(blockSize, inputLen);
}
}
}

202
src/cz/cvut/keyczar/COPYING Normal file
View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2008
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,191 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.exceptions.BadVersionException;
import cz.cvut.keyczar.exceptions.InvalidSignatureException;
import cz.cvut.keyczar.exceptions.KeyNotFoundException;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.ShortCiphertextException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.DecryptingStream;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Crypters may both encrypt and decrypt data using sets of symmetric or private
* keys. Sets of public keys may only be used with {@link Encrypter} objects.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Crypter extends Encrypter {
private static final int DECRYPT_CHUNK_SIZE = 1024;
private static final Logger logger = Logger.getLogger(Crypter.class);
private static final StreamCache<DecryptingStream> CRYPT_CACHE
= new StreamCache<DecryptingStream>();
/**
* Initialize a new Crypter with a KeyczarReader. The corresponding key set
* must have a purpose {@link cz.cvut.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Crypter(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Crypter with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of
* {@link cz.cvut.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Crypter(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Decrypt the given byte array of ciphertext
*
* @param input The input ciphertext
* @return The decrypted plaintext
* @throws KeyczarException If the input is malformed, the ciphertext
* signature does not verify, the decryption key is not found, or a JCE
* error occurs.
*/
public byte[] decrypt(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(input.length);
decrypt(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Decrypt the given ciphertext input ByteBuffer and write the decrypted
* plaintext to the output ByteBuffer
*
* @param input The input ciphertext. Will not be modified.
* @param output The output buffer to write the decrypted plaintext
* @throws KeyczarException If the input is malformed, the ciphertext
* signature does not verify, the decryption key is not found, or a JCE
* error occurs.
*/
public void decrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
ByteBuffer inputCopy = input.asReadOnlyBuffer();
logger.info(
Messages.getString("Crypter.Decrypting", inputCopy.remaining()));
if (inputCopy.remaining() < HEADER_SIZE) {
throw new ShortCiphertextException(inputCopy.remaining());
}
byte version = inputCopy.get();
if (version != FORMAT_VERSION) {
throw new BadVersionException(version);
}
byte[] hash = new byte[KEY_HASH_SIZE];
inputCopy.get(hash);
KeyczarKey key = getKey(hash);
if (key == null) {
throw new KeyNotFoundException(hash);
}
// The input to decrypt is now positioned at the start of the ciphertext
inputCopy.mark();
DecryptingStream cryptStream = CRYPT_CACHE.get(key);
if (cryptStream == null) {
cryptStream = (DecryptingStream) key.getStream();
}
VerifyingStream verifyStream = cryptStream.getVerifyingStream();
if (inputCopy.remaining() < verifyStream.digestSize()) {
throw new ShortCiphertextException(inputCopy.remaining());
}
// Slice off the signature into another buffer
inputCopy.position(inputCopy.limit() - verifyStream.digestSize());
ByteBuffer signature = inputCopy.slice();
// Reset the position of the input to start of the ciphertext
inputCopy.reset();
inputCopy.limit(inputCopy.limit() - verifyStream.digestSize());
// Initialize the crypt stream. This may read an IV if any.
cryptStream.initDecrypt(inputCopy);
// Verify the header and IV if any
ByteBuffer headerAndIvToVerify = input.asReadOnlyBuffer();
headerAndIvToVerify.limit(inputCopy.position());
verifyStream.initVerify();
verifyStream.updateVerify(headerAndIvToVerify);
output.mark();
// This will process large input in chunks, rather than all at once. This
// avoids making two passes through memory.
while (inputCopy.remaining() > DECRYPT_CHUNK_SIZE) {
ByteBuffer ciphertextChunk = inputCopy.slice();
ciphertextChunk.limit(DECRYPT_CHUNK_SIZE);
cryptStream.updateDecrypt(ciphertextChunk, output);
ciphertextChunk.rewind();
verifyStream.updateVerify(ciphertextChunk);
inputCopy.position(inputCopy.position() + DECRYPT_CHUNK_SIZE);
}
inputCopy.mark();
verifyStream.updateVerify(inputCopy);
if (!verifyStream.verify(signature)) {
throw new InvalidSignatureException();
}
inputCopy.reset();
cryptStream.doFinalDecrypt(inputCopy, output);
output.limit(output.position());
CRYPT_CACHE.put(key, cryptStream);
}
/**
* Decrypt the given web-safe Base64 encoded ciphertext and return the
* decrypted plaintext as a String.
*
* @param ciphertext The encrypted ciphertext in web-safe Base64 format
* @return The decrypted plaintext as a string
* @throws KeyczarException If the input is malformed, the ciphertext
* signature does not verify, the decryption key is not found, the input is
* not web-safe Base64 encoded, or a JCE error occurs.
*/
public String decrypt(String ciphertext) throws KeyczarException {
return new String(decrypt(Base64Coder.decode(ciphertext)));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.DECRYPT_AND_ENCRYPT;
}
}

View file

@ -0,0 +1,195 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.DSAPrivateKeySpec;
/**
* Wrapping class for DSA Private Keys
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class DsaPrivateKey extends KeyczarKey implements KeyczarPrivateKey {
private static final String KEY_GEN_ALGORITHM = "DSA";
private static final String SIG_ALGORITHM = "SHA1withDSA";
@Expose private DsaPublicKey publicKey;
@Expose private String x;
private DSAPrivateKey jcePrivateKey;
private DsaPrivateKey() {
publicKey = new DsaPublicKey();
}
@Override
byte[] hash() {
return getPublic().hash();
}
public String getKeyGenAlgorithm() {
return KEY_GEN_ALGORITHM;
}
public KeyczarPublicKey getPublic() {
return publicKey;
}
@Override
Stream getStream() throws KeyczarException {
return new DsaSigningStream();
}
@Override
KeyType getType() {
return KeyType.DSA_PRIV;
}
public void setPublic(KeyczarPublicKey pub) throws KeyczarException {
publicKey = (DsaPublicKey) pub;
publicKey.init();
}
static DsaPrivateKey generate() throws KeyczarException {
return generate(KeyType.DSA_PRIV.defaultSize());
}
void init() throws KeyczarException {
publicKey.init();
BigInteger xVal = new BigInteger(Base64Coder.decode(x));
BigInteger pVal = new BigInteger(Base64Coder.decode(publicKey.p));
BigInteger qVal = new BigInteger(Base64Coder.decode(publicKey.q));
BigInteger gVal = new BigInteger(Base64Coder.decode(publicKey.g));
DSAPrivateKeySpec spec = new DSAPrivateKeySpec(xVal, pVal, qVal, gVal);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePrivateKey = (DSAPrivateKey) kf.generatePrivate(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
static DsaPrivateKey generate(int keySize) throws KeyczarException {
DsaPrivateKey key = new DsaPrivateKey();
KeyPairGenerator kpg;
try {
kpg = KeyPairGenerator.getInstance(KEY_GEN_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
key.size = keySize;
kpg.initialize(key.size());
KeyPair pair = kpg.generateKeyPair();
key.jcePrivateKey = (DSAPrivateKey) pair.getPrivate();
DSAPublicKey pubKey = (DSAPublicKey) pair.getPublic();
key.publicKey.set(pubKey.getY(), pubKey.getParams().getP(),
pubKey.getParams().getQ(), pubKey.getParams().getG());
// Initialize the private key's JSON fields
key.x = Base64Coder.encode(key.jcePrivateKey.getX().toByteArray());
key.init();
return key;
}
static DsaPrivateKey read(String input) throws KeyczarException {
DsaPrivateKey key = Util.gson().fromJson(input, DsaPrivateKey.class);
key.init();
return key;
}
private class DsaSigningStream implements SigningStream, VerifyingStream {
private Signature signature;
private VerifyingStream verifyingStream;
public DsaSigningStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
verifyingStream = (VerifyingStream) publicKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initSign() throws KeyczarException {
try {
signature.initSign(jcePrivateKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
verifyingStream.initVerify();
}
public void sign(ByteBuffer output) throws KeyczarException {
try {
byte[] sig = signature.sign();
output.put(sig);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateSign(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
verifyingStream.updateVerify(input);
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
return verifyingStream.verify(sig);
}
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.DSAPublicKeySpec;
/**
* Wrapping class for DSA Public Keys. These must be exported from existing DSA
* private key sets.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
class DsaPublicKey extends KeyczarPublicKey {
private static final String KEY_GEN_ALGORITHM = "DSA";
private static final String SIG_ALGORITHM = "SHA1withDSA";
private PublicKey jcePublicKey;
@Expose String y;
@Expose String p;
@Expose String q;
@Expose String g;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
@Override
public Stream getStream() throws KeyczarException {
return new DsaVerifyingStream();
}
@Override
KeyType getType() {
return KeyType.DSA_PUB;
}
static DsaPublicKey read(String input) throws KeyczarException {
DsaPublicKey key = Util.gson().fromJson(input, DsaPublicKey.class);
key.init();
return key;
}
@Override
public byte[] hash() {
return hash;
}
void set(BigInteger yVal, BigInteger pVal, BigInteger qVal, BigInteger gVal)
throws KeyczarException {
// Initialize the JSON fields
y = Base64Coder.encode(yVal.toByteArray());
p = Base64Coder.encode(pVal.toByteArray());
q = Base64Coder.encode(qVal.toByteArray());
g = Base64Coder.encode(gVal.toByteArray());
init();
}
void init() throws KeyczarException {
BigInteger yVal = new BigInteger(Base64Coder.decode(y));
BigInteger pVal = new BigInteger(Base64Coder.decode(p));
BigInteger qVal = new BigInteger(Base64Coder.decode(q));
BigInteger gVal = new BigInteger(Base64Coder.decode(g));
DSAPublicKeySpec spec = new DSAPublicKeySpec(yVal, pVal, qVal, gVal);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePublicKey = kf.generatePublic(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
byte[] fullHash = Util.prefixHash(
Util.stripLeadingZeros(pVal.toByteArray()),
Util.stripLeadingZeros(qVal.toByteArray()),
Util.stripLeadingZeros(gVal.toByteArray()),
Util.stripLeadingZeros(yVal.toByteArray()));
System.arraycopy(fullHash, 0, hash, 0, hash.length);
}
private class DsaVerifyingStream implements VerifyingStream {
private Signature signature;
public DsaVerifyingStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initVerify() throws KeyczarException {
try {
signature.initVerify(jcePublicKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
try {
return signature.verify(sig.array(), sig.position(), sig.limit()
- sig.position());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
}
}

View file

@ -0,0 +1,183 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.jce.EcCore;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.PKCS8EncodedKeySpec;
/**
* Wrapping class for EC Private Keys
*
* @author martclau@gmail.com
*
*/
class EcPrivateKey extends KeyczarKey implements KeyczarPrivateKey {
private static final String KEY_GEN_ALGORITHM = "EC";
private static final String SIG_ALGORITHM = "SHA256withECDSA";
@Expose private EcPublicKey publicKey;
@Expose private String pkcs8;
private PrivateKey jcePrivateKey;
private EcPrivateKey() {
publicKey = new EcPublicKey();
}
public String getKeyGenAlgorithm() {
return KEY_GEN_ALGORITHM;
}
public KeyczarPublicKey getPublic() {
return publicKey;
}
@Override
byte[] hash() {
return getPublic().hash();
}
@Override
Stream getStream() throws KeyczarException {
return new EcSigningStream();
}
@Override
KeyType getType() {
return KeyType.EC_PRIV;
}
public void setPublic(KeyczarPublicKey pub) throws KeyczarException {
publicKey = (EcPublicKey) pub;
publicKey.init();
}
static EcPrivateKey generate() throws KeyczarException {
return generate(KeyType.EC_PRIV.defaultSize());
}
void init() throws KeyczarException {
byte[] pkcs8Bytes = Base64Coder.decode(pkcs8);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePrivateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(pkcs8Bytes));
publicKey.init();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
static EcPrivateKey generate(int keySize) throws KeyczarException {
EcPrivateKey key = new EcPrivateKey();
try {
// Make sure we use our own impl; there may be other EC key generators...
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_GEN_ALGORITHM,
EcCore.NAME);
key.size = keySize;
kpg.initialize(key.size());
KeyPair pair = kpg.generateKeyPair();
key.jcePrivateKey = pair.getPrivate();
key.publicKey.set(pair.getPublic().getEncoded());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
key.pkcs8 = Base64Coder.encode(key.jcePrivateKey.getEncoded());
key.init();
return key;
}
static EcPrivateKey read(String input) throws KeyczarException {
EcPrivateKey key = Util.gson().fromJson(input, EcPrivateKey.class);
key.init();
return key;
}
private class EcSigningStream implements SigningStream, VerifyingStream {
private Signature signature;
private VerifyingStream verifyingStream;
public EcSigningStream() throws KeyczarException {
try {
// Make sure we use our own impl; there may be other EC signature
// generators...
signature = Signature.getInstance(SIG_ALGORITHM, EcCore.NAME);
verifyingStream = (VerifyingStream) publicKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initSign() throws KeyczarException {
try {
signature.initSign(jcePrivateKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
verifyingStream.initVerify();
}
public void sign(ByteBuffer output) throws KeyczarException {
try {
byte[] sig = signature.sign();
output.put(sig);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateSign(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
verifyingStream.updateVerify(input);
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
return verifyingStream.verify(sig);
}
}
}

View file

@ -0,0 +1,132 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.spec.X509EncodedKeySpec;
/**
* Wrapping class for EC Public Keys. These must be exported from existing EC
* private key sets.
*
* @author martclau@gmail.com
*
*/
class EcPublicKey extends KeyczarPublicKey {
private static final String KEY_GEN_ALGORITHM = "EC";
private static final String SIG_ALGORITHM = "SHA256withECDSA";
private PublicKey jcePublicKey;
@Expose String x509;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
void init() throws KeyczarException {
byte[] x509Bytes = Base64Coder.decode(x509);
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
jcePublicKey = kf.generatePublic(new X509EncodedKeySpec(x509Bytes));
byte[] fullHash = Util.prefixHash(x509Bytes);
System.arraycopy(fullHash, 0, hash, 0, hash.length);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
void set(byte[] x509Bytes) throws KeyczarException {
x509 = Base64Coder.encode(x509Bytes);
byte[] fullHash = Util.prefixHash(x509Bytes);
System.arraycopy(fullHash, 0, hash, 0, hash.length);
init();
}
@Override
byte[] hash() {
return hash;
}
@Override
public Stream getStream() throws KeyczarException {
return new EcVerifyingStream();
}
@Override
KeyType getType() {
return KeyType.EC_PUB;
}
static EcPublicKey read(String input) throws KeyczarException {
EcPublicKey key = Util.gson().fromJson(input, EcPublicKey.class);
key.init();
return key;
}
private class EcVerifyingStream implements VerifyingStream {
private Signature signature;
public EcVerifyingStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initVerify() throws KeyczarException {
try {
signature.initVerify(jcePublicKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
try {
return signature.verify(sig.array(), sig.position(), sig.limit()
- sig.position());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
}
}

View file

@ -0,0 +1,192 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.NoPrimaryKeyException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.EncryptingStream;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Encrypters are used strictly to encrypt data. Typically, Encrypters will read
* sets of public keys, although may also be instantiated with sets of symmetric
* keys.
*
* {@link Crypter} objects should be used with symmetric or private key sets to
* decrypt data.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Encrypter extends Keyczar {
private static final Logger ENCRYPTER_LOGGER =
Logger.getLogger(Encrypter.class);
private static final int ENCRYPT_CHUNK_SIZE = 1024;
private final StreamQueue<EncryptingStream> ENCRYPT_QUEUE =
new StreamQueue<EncryptingStream>();
/**
* Initialize a new Encrypter with a KeyczarReader. The corresponding key set
* must have a purpose of either
* {@link cz.cvut.keyczar.enums.KeyPurpose#ENCRYPT} or
* {@link cz.cvut.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Encrypter(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Encrypter with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of either
* {@link cz.cvut.keyczar.enums.KeyPurpose#ENCRYPT} or
* {@link cz.cvut.keyczar.enums.KeyPurpose#DECRYPT_AND_ENCRYPT}
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Encrypter(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Returns the size of the ciphertext output that would result from encrypting
* an input of the given length.
*
* @param inputLength The length of the input.
* @return Length of the ciphertext that would be produced.
* @throws KeyczarException If the key set contains no primary encrypting key.
*/
public int ciphertextSize(int inputLength) throws KeyczarException {
EncryptingStream cryptStream = ENCRYPT_QUEUE.poll();
if (cryptStream == null) {
KeyczarKey encryptingKey = getPrimaryKey();
if (encryptingKey == null) {
throw new NoPrimaryKeyException();
}
cryptStream = (EncryptingStream) encryptingKey.getStream();
}
SigningStream signStream = cryptStream.getSigningStream();
int outputSize = HEADER_SIZE + cryptStream.maxOutputSize(inputLength) +
signStream.digestSize();
ENCRYPT_QUEUE.add(cryptStream);
return outputSize;
}
/**
* Encrypt the given input byte array.
*
* @param input The input to encrypt
* @return The encrypted ciphertext
* @throws KeyczarException If there is a JCE exception or the key set does
* not contain a primary encrypting key.
*/
public byte[] encrypt(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(ciphertextSize(input.length));
encrypt(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Encrypt the given input ByteBuffer.
*
* @param input The input buffer to encrypt. Will not be modified
* @param output The buffer to write the output ciphertext to.
* @throws KeyczarException If there is a JCE exception, the key set does
* not contain a primary encrypting key, or the output buffer is too small.
*/
public void encrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
ENCRYPTER_LOGGER.info(Messages.getString("Encrypter.Encrypting", input.remaining()));
KeyczarKey encryptingKey = getPrimaryKey();
if (encryptingKey == null) {
throw new NoPrimaryKeyException() ;
}
EncryptingStream cryptStream = ENCRYPT_QUEUE.poll();
if (cryptStream == null) {
cryptStream = (EncryptingStream) encryptingKey.getStream();
}
// Initialize the signing stream
SigningStream signStream = cryptStream.getSigningStream();
signStream.initSign();
// Write the key header
output.mark();
ByteBuffer outputToSign = output.asReadOnlyBuffer();
encryptingKey.copyHeader(output);
// Write the IV. May be an empty array of zero length
cryptStream.initEncrypt(output);
ByteBuffer inputCopy = input.asReadOnlyBuffer();
while (inputCopy.remaining() > ENCRYPT_CHUNK_SIZE) {
ByteBuffer inputChunk = inputCopy.slice();
inputChunk.limit(ENCRYPT_CHUNK_SIZE);
cryptStream.updateEncrypt(inputChunk, output);
inputCopy.position(inputCopy.position() + ENCRYPT_CHUNK_SIZE);
outputToSign.limit(output.position());
signStream.updateSign(outputToSign);
outputToSign.position(output.position());
}
// Sign any remaining plaintext
cryptStream.doFinalEncrypt(inputCopy, output);
output.limit(output.position() + signStream.digestSize());
// Set the limit on the output to sign
outputToSign.limit(output.position());
signStream.updateSign(outputToSign);
// Sign the final block of ciphertext output
signStream.sign(output);
ENCRYPT_QUEUE.add(cryptStream);
}
/**
* Encrypt a String and return a web-safe Base64 encoded ciphertext.
*
* @param input An String to encrypt.
* @return A web-safe Base64 encoded ciphertext.
* @throws KeyczarException If there is a JCE exception or the key set does
* not contain a primary encrypting key.
*/
public String encrypt(String input) throws KeyczarException {
return Base64Coder.encode(encrypt(input.getBytes()));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.ENCRYPT
|| purpose == KeyPurpose.DECRYPT_AND_ENCRYPT;
}
}

View file

@ -0,0 +1,296 @@
package cz.cvut.keyczar;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.enums.KeyStatus;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
/**
* Wrapper class to access Keyczar utility methods of reading and manipulating
* key metadata files. Also contains additional utility methods for pushing
* updates to meta files on disk and exporting public key sets.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class GenericKeyczar extends Keyczar {
GenericKeyczar(KeyczarReader reader) throws KeyczarException {
super(reader);
}
GenericKeyczar(String location) throws KeyczarException {
super(location);
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return true;
}
KeyMetadata getMetadata() {
return this.kmd;
}
Set<KeyVersion> getVersions() {
return Collections.unmodifiableSet(versionMap.keySet());
}
KeyczarKey getKey(KeyVersion v) {
return versionMap.get(v);
}
/**
* Promotes the status of key with given version number. Promoting ACTIVE key
* automatically demotes current PRIMARY key to ACTIVE.
*
* @param versionNumber integer version number to promote
* @throws KeyczarException if invalid version number or trying to promote
* a primary key.
*/
void promote(int versionNumber) throws KeyczarException {
KeyVersion version = getVersion(versionNumber);
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.PromotedVersion", version));
switch (version.getStatus()) {
case PRIMARY:
throw new KeyczarException(
Messages.getString("Keyczar.CantPromotePrimary"));
case ACTIVE:
version.setStatus(KeyStatus.PRIMARY); // promote to PRIMARY
if (primaryVersion != null) {
primaryVersion.setStatus(KeyStatus.ACTIVE); // only one PRIMARY key
}
primaryVersion = version;
break;
case INACTIVE:
version.setStatus(KeyStatus.ACTIVE);
break;
}
}
/**
* Demotes the status of key with given version number. Demoting PRIMARY key
* results in a key set with no primary version.
*
* @param versionNumber integer version number to demote
* @throws KeyczarException if invalid version number or trying to demote
* a key scheduled for revocation.
*/
void demote(int versionNumber) throws KeyczarException {
KeyVersion version = getVersion(versionNumber);
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.DemotingVersion", version));
switch (version.getStatus()) {
case PRIMARY:
version.setStatus(KeyStatus.ACTIVE);
primaryVersion = null; // no more PRIMARY keys in the set
break;
case ACTIVE:
version.setStatus(KeyStatus.INACTIVE);
break;
case INACTIVE:
throw new KeyczarException(
Messages.getString("Keyczar.CantDemoteScheduled"));
}
}
/**
* Uses default key size to add a new key version.
*
* @param status KeyStatus desired for new key version
*/
void addVersion(KeyStatus status) throws KeyczarException {
addVersion(status, kmd.getType().defaultSize());
}
/**
* Adds a new key version with given status and next available version
* number to key set. Generates a new key of same type (repeated until hash
* identifier is unique) for this version. Uses supplied key size in lieu
* of the default key size. If this is an unacceptable key size, defaults
* to the default key size.
*
* @param status KeyStatus desired for new key version
* @param keySize desired key size in bits
* @throws KeyczarException if key type is unsupported.
*/
void addVersion(KeyStatus status, int keySize) throws KeyczarException {
KeyVersion version = new KeyVersion(numVersions() + 1, status, false);
if (status == KeyStatus.PRIMARY) {
if (primaryVersion != null) {
primaryVersion.setStatus(KeyStatus.ACTIVE);
}
primaryVersion = version;
}
KeyczarKey key;
if (keySize < kmd.getType().defaultSize()) { // print a warning statement
KEYCZAR_LOGGER.warn(Messages.getString("Keyczar.SizeWarning",
keySize, kmd.getType().defaultSize(), kmd.getType().toString()));
}
do { // Make sure no keys collide on their identifiers
key = KeyczarKey.genKey(kmd.getType(), keySize);
} while (getKey(key.hash()) != null);
addKey(version, key);
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.NewVersion", version));
}
int numVersions() {
return versionMap.size();
}
/**
* Returns the version corresponding to the version number if it exists.
*
* @param versionNumber
* @return KeyVersion if it exists
* @throws KeyczarException if version number doesn't exist
*/
KeyVersion getVersion(int versionNumber) throws KeyczarException {
KeyVersion version = kmd.getVersion(versionNumber);
if (version == null) {
throw new KeyczarException(
Messages.getString("Keyczar.NoSuchVersion", versionNumber));
}
return version;
}
/**
* Revokes the key with given version number if it is scheduled to be revoked.
*
* @param versionNumber integer version number to be revoked
* @throws KeyczarException if version number nonexistent or key is not
* scheduled for revocation.
*/
void revoke(int versionNumber) throws KeyczarException {
KeyVersion version = getVersion(versionNumber);
if (version.getStatus() == KeyStatus.INACTIVE) {
kmd.removeVersion(versionNumber);
} else {
throw new KeyczarException(Messages.getString("Keyczar.CantRevoke"));
}
}
/**
* For the managed key set, exports a set of public keys at given location.
* Client's key must be a private key for DSA or RSA. For DSA private key,
* purpose must be SIGN_AND_VERIFY. For RSA private key, purpose can also
* be DECRYPT_AND_ENCRYPT.KeyczarTool
*
* @param destination String pathname of directory to export key set to
* @throws KeyczarException if unable to export key set.
*/
void publicKeyExport(String destination) throws KeyczarException {
KeyMetadata kmd = getMetadata();
// Can only export if type is DSA_PRIV and purpose is SIGN_AND_VERIFY
KeyMetadata publicKmd = null;
switch(kmd.getType()) {
case DSA_PRIV: // DSA Private Key
if (kmd.getPurpose() == KeyPurpose.SIGN_AND_VERIFY) {
publicKmd = new KeyMetadata(kmd.getName(), KeyPurpose.VERIFY,
KeyType.DSA_PUB);
}
break;
case RSA_PRIV: // RSA Private Key
switch(kmd.getPurpose()) {
case DECRYPT_AND_ENCRYPT:
publicKmd = new KeyMetadata(kmd.getName(), KeyPurpose.ENCRYPT,
KeyType.RSA_PUB);
break;
case SIGN_AND_VERIFY:
publicKmd = new KeyMetadata(kmd.getName(), KeyPurpose.VERIFY,
KeyType.RSA_PUB);
break;
}
break;
}
if (publicKmd == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.CannotExportPubKey",
kmd.getType(), kmd.getPurpose()));
}
for (KeyVersion version : getVersions()) {
KeyczarKey publicKey =
((KeyczarPrivateKey) getKey(version)).getPublic();
if (KeyczarTool.getMock() == null) {
writeFile(publicKey.toString(), destination
+ version.getVersionNumber());
} else { // for testing, update mock object
KeyczarTool.getMock().setPublicKey(version.getVersionNumber(), publicKey);
}
publicKmd.addVersion(version);
}
if (KeyczarTool.getMock() == null) {
writeFile(publicKmd.toString(), destination
+ KeyczarFileReader.META_FILE);
} else { // for testing, update mock public kmd
KeyczarTool.getMock().setPublicKeyMetadata(publicKmd);
}
}
/**
* Pushes updated KeyMetadata and KeyVersion info to files at given
* directory location. Version files are named by their number and the
* meta file is named meta.
*
* @param location String pathname of directory to write to
* @throws KeyczarException if unable to write to given location.
*/
void write(String location) throws KeyczarException {
writeFile(kmd.toString(), location
+ KeyczarFileReader.META_FILE);
for (KeyVersion version : getVersions()) {
writeFile(getKey(version).toString(), location
+ version.getVersionNumber());
}
}
/**
* Encrypts the key files before writing them out to disk
*
* @param location Location of key set
* @param encrypter The encrypter object used to encrypt keys
* @throws KeyczarException If unable to write to a given location
*/
void writeEncrypted(String location, Encrypter encrypter)
throws KeyczarException {
KeyMetadata kmd = getMetadata();
kmd.setEncrypted(true);
writeFile(kmd.toString(), location + KeyczarFileReader.META_FILE);
for (KeyVersion version : getVersions()) {
writeFile(encrypter.encrypt(getKey(version).toString()), location
+ version.getVersionNumber());
}
}
/**
* Utility function to write given data to a file at given location.
*
* @param data String data to be written
* @param location String pathname of destination file
* @throws KeyczarException if unable to write to file.
*/
void writeFile(String data, String location)
throws KeyczarException {
File outputFile = new File(location);
try {
FileWriter writer = new FileWriter(outputFile);
writer.write(data);
writer.close();
} catch (IOException e) {
throw new KeyczarException(
Messages.getString("KeyczarTool.UnableToWrite",
outputFile.toString()), e);
}
}
}

View file

@ -0,0 +1,165 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Key;
/**
* Wrapping class for HMAC-SHA1 keys
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public class HmacKey extends KeyczarKey {
private static final String MAC_ALGORITHM = "HMACSHA1";
@Expose private String hmacKeyString;
private Key hmacKey;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
static HmacKey generate() throws KeyczarException {
return generate(KeyType.HMAC_SHA1.defaultSize());
}
static HmacKey generate(int keySize) throws KeyczarException {
HmacKey key = new HmacKey();
key.size = keySize;
byte[] keyBytes = Util.rand(key.size() / 8);
key.hmacKeyString = Base64Coder.encode(keyBytes);
key.init();
return key;
}
void init() throws KeyczarException {
byte[] keyBytes = Base64Coder.decode(hmacKeyString);
byte[] fullHash = Util.hash(keyBytes);
System.arraycopy(fullHash, 0, hash, 0, hash.length);
hmacKey = new SecretKeySpec(keyBytes, MAC_ALGORITHM);
}
/*
* This method is for AesKey to grab the key bytes to compute an identifying
* hash.
*/
byte[] keyBytes() {
return hmacKey.getEncoded();
}
@Override
Stream getStream() throws KeyczarException {
return new HmacStream();
}
@Override
KeyType getType() {
return KeyType.HMAC_SHA1;
}
@Override
byte[] hash() {
return hash;
}
static HmacKey read(String input) throws KeyczarException {
HmacKey key = Util.gson().fromJson(input, HmacKey.class);
key.init();
return key;
}
private class HmacStream implements VerifyingStream, SigningStream {
private Mac hmac;
private long milis = 0;
private int nanos = 0;
public HmacStream() throws KeyczarException {
if ((System.getProperty("millis") != null) && (System.getProperty("nanos") != null)) {
this.milis = Long.parseLong(System.getProperty("millis"));
this.nanos = Integer.parseInt(System.getProperty("nanos"));
}
try {
hmac = Mac.getInstance(MAC_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public void initSign() throws KeyczarException {
try {
hmac.init(hmacKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
initSign();
}
public void sign(ByteBuffer output) {
output.put(hmac.doFinal());
}
public void updateSign(ByteBuffer input) {
hmac.update(input);
}
public void updateVerify(ByteBuffer input) {
updateSign(input);
}
public boolean verify(ByteBuffer signature) {
byte[] sigBytes = new byte[signature.remaining()];
signature.get(sigBytes);
byte[] macResult = hmac.doFinal();
if (macResult.length != sigBytes.length) {
return false;
}
for (int pos = 0; pos < macResult.length; pos++) {
if (macResult[pos] != sigBytes[pos]) {
return false;
}
if ((milis!=0) || (nanos!=0)) {
try { Thread.sleep(milis, nanos); } catch (InterruptedException e) {}
}
}
return true;
}
}
}

View file

@ -0,0 +1,157 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.util.Util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Encodes metadata for a set of keys which consists of the following:
* <ul>
* <li>a string-valued name,
* <li>a KeyPurpose,
* <li>a KeyType, and
* <li>a set of KeyVersion values.
* </ul>
*
* <p>JSON Representation consists of the following fields:
* <ul>
* <li>"name": a String name,
* <li>"purpose": JSON representation of KeyPurpose value,
* <li>"type": JSON representation of KeyType value,
* <li>"versions": JSON representation of an array of KeyVersion values.
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class KeyMetadata {
@Expose String name = "";
@Expose KeyPurpose purpose = KeyPurpose.TEST;
@Expose KeyType type = KeyType.TEST;
@Expose List<KeyVersion> versions = new ArrayList<KeyVersion>();
@Expose boolean encrypted = false;
protected Map<Integer, KeyVersion> versionMap =
new HashMap<Integer, KeyVersion>(); // link version number to version
@SuppressWarnings("unused")
private KeyMetadata() {
// For GSON
}
KeyMetadata(String n, KeyPurpose p, KeyType t) {
name = n;
purpose = p;
type = t;
}
@Override
public String toString() {
return Util.gson().toJson(this);
}
/**
* Adds given key version to key set.
*
* @param version KeyVersion of key to be added
* @return true if add was successful, false if version number collides
*/
boolean addVersion(KeyVersion version) {
int versionNumber = version.getVersionNumber();
if (!versionMap.containsKey(versionNumber)) {
versionMap.put(versionNumber, version);
versions.add(version);
return true;
}
return false;
}
/**
* Removes given key version from key set.
*
* @param versionNumber integer version number of key to be removed
* @return true if remove was successful
*/
boolean removeVersion(int versionNumber) {
if (versionMap.containsKey(versionNumber)) {
KeyVersion version = versionMap.get(versionNumber);
versions.remove(version);
versionMap.remove(versionNumber);
return true;
}
return false;
}
String getName() {
return name;
}
KeyPurpose getPurpose() {
return purpose;
}
KeyType getType() {
return type;
}
void setEncrypted(boolean encrypted) {
this.encrypted = encrypted;
}
boolean isEncrypted() {
return encrypted;
}
/**
* Returns the version corresponding to the version number.
*
* @param versionNumber
* @return KeyVersion corresponding to given number, or null if nonexistent
*/
KeyVersion getVersion(int versionNumber) {
return versionMap.get(versionNumber);
}
List<KeyVersion> getVersions() {
return versions;
}
/**
* Parses JSON string to create a KeyMetadata object. Initializes it with
* versions listed in the JSON array.
*
* @param jsonString
* @return KeyMetadata corresponding to JSON input
*/
static KeyMetadata read(String jsonString) {
KeyMetadata kmd = Util.gson().fromJson(jsonString, KeyMetadata.class);
for (KeyVersion version : kmd.getVersions()) {
kmd.versionMap.put(version.getVersionNumber(), version);
}
return kmd;
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyStatus;
import cz.cvut.keyczar.util.Util;
/**
* A key version consists of the following:
* <ul>
* <li>an integer value version number, counting from 1,
* <li>a KeyStatus, and
* <li>a boolean representing whether this key is exportable
* outside of Keyczar.
* </ul>
* <p>JSON Representation consists of the following fields:
* <ul>
* <li>"status": JSON representation of KeyStatus value,
* <li>"versionNumber": integer version number,
* <li>"exportable": boolean value.
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class KeyVersion {
@Expose private boolean exportable = false;
@Expose private KeyStatus status = KeyStatus.ACTIVE;
@Expose private int versionNumber = 0;
@SuppressWarnings("unused")
private KeyVersion() {
// For GSON
}
KeyVersion(int v, boolean export) {
this(v, KeyStatus.ACTIVE, export);
}
KeyVersion(int v, KeyStatus s, boolean export) {
versionNumber = v;
status = s;
exportable = export;
}
@Override
public String toString() {
return Util.gson().toJson(this);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof KeyVersion)) {
return false;
}
KeyVersion v = (KeyVersion) o;
return getVersionNumber() == v.getVersionNumber();
// only depend on version number, otherwise changing status changes identity
}
@Override
public int hashCode() {
return versionNumber; // identity depends only on version number
}
KeyStatus getStatus() {
return status;
}
int getVersionNumber() {
return versionNumber;
}
boolean isExportable() {
return exportable;
}
/**
* Updates the status of this KeyVersion to given status if not null.
* @param status
*/
void setStatus(KeyStatus status) {
this.status = (status == null) ? this.status : status;
}
static KeyVersion read(String jsonString) {
return Util.gson().fromJson(jsonString, KeyVersion.class);
}
}

View file

@ -0,0 +1,153 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.enums.KeyStatus;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.EncryptedReader;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.util.Util;
import java.util.HashMap;
/**
* Manages a Keyczar key set.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
abstract class Keyczar {
static final Logger KEYCZAR_LOGGER = Logger.getLogger(Keyczar.class);
static final byte FORMAT_VERSION = 0;
static final byte[] FORMAT_BYTES = { FORMAT_VERSION };
static final int KEY_HASH_SIZE = 4;
static final int HEADER_SIZE = 1 + KEY_HASH_SIZE;
final KeyMetadata kmd;
KeyVersion primaryVersion;
final HashMap<KeyVersion, KeyczarKey> versionMap =
new HashMap<KeyVersion, KeyczarKey>();
final HashMap<KeyHash, KeyczarKey> hashMap =
new HashMap<KeyHash, KeyczarKey>(); // keep track of used hash identifiers
private class KeyHash {
private byte[] data;
private KeyHash(byte[] d) {
if (d.length != KEY_HASH_SIZE) {
throw new IllegalArgumentException();
}
data = d;
}
@Override
public boolean equals(Object o) {
return (o instanceof KeyHash && o.hashCode() == this.hashCode());
}
@Override
public int hashCode() {
return Util.toInt(data);
}
}
/**
* Instantiates a new Keyczar object by passing it a Keyczar reader object
*
* @param reader A KeyczarReader to read keys from
* @throws KeyczarException
*/
public Keyczar(KeyczarReader reader) throws KeyczarException {
// Reads keys from the KeyczarReader
kmd = KeyMetadata.read(reader.getMetadata());
if (!isAcceptablePurpose(kmd.getPurpose())) {
throw new KeyczarException(
Messages.getString("Keyczar.UnacceptablePurpose", kmd.getPurpose()));
}
if (kmd.isEncrypted() && !(reader instanceof EncryptedReader)) {
throw new KeyczarException(
Messages.getString("Keyczar.NeedEncryptedReader"));
}
for (KeyVersion version : kmd.getVersions()) {
if (version.getStatus() == KeyStatus.PRIMARY) {
if (primaryVersion != null) {
throw new KeyczarException(
Messages.getString("Keyczar.SinglePrimary"));
}
primaryVersion = version;
}
KeyczarKey key = KeyczarKey.readKey(kmd.getType(),
reader.getKey(version.getVersionNumber()));
KEYCZAR_LOGGER.info(Messages.getString("Keyczar.ReadVersion", version));
hashMap.put(new KeyHash(key.hash()), key);
versionMap.put(version, key);
}
}
/**
* Instantiates a new Keyczar object with a KeyczarFileReader instantiated
* with the given file location
*
* @param fileLocation
* @throws KeyczarException
*/
public Keyczar(String fileLocation) throws KeyczarException {
this(new KeyczarFileReader(fileLocation));
}
@Override
public String toString() {
return kmd.toString();
}
/**
* Adds a new KeyczarKey (new version) to the key store. Associates it
* with given version. Adds new KeyVersion to the key set.
*
* @param version KeyVersion
* @param key KeyczarKey
*/
void addKey(KeyVersion version, KeyczarKey key) {
hashMap.put(new KeyHash(key.hash()), key);
versionMap.put(version, key);
kmd.addVersion(version);
}
KeyczarKey getPrimaryKey() {
if (primaryVersion == null) {
return null;
}
return versionMap.get(primaryVersion);
}
KeyczarKey getKey(byte[] hash) {
return hashMap.get(new KeyHash(hash));
}
/**
* Returns true if the purpose is acceptable for this key set.
*
* @param purpose
* @return true if the purpose is acceptable, false otherwise.
*/
abstract boolean isAcceptablePurpose(KeyPurpose purpose);
}

View file

@ -0,0 +1,52 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.EncryptedReader;
import cz.cvut.keyczar.interfaces.KeyczarReader;
/**
* Reads metadata and encrypted key files from the given reader.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class KeyczarEncryptedReader implements EncryptedReader {
private KeyczarReader reader;
private Crypter crypter;
/**
* Reads encrypted key files from the given reader and decrypts them
* with the given crypter.
*
* @param reader The reader to read files from.
* @param crypter The crypter to decrypt keys with.
*/
public KeyczarEncryptedReader(KeyczarReader reader, Crypter crypter) {
this.reader = reader;
this.crypter = crypter;
}
public String getKey(int version) throws KeyczarException {
return crypter.decrypt(reader.getKey(version));
}
public String getMetadata() throws KeyczarException {
return reader.getMetadata();
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Reads metadata and key files from the given location.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class KeyczarFileReader implements KeyczarReader {
private String location;
static final String META_FILE = "meta";
public KeyczarFileReader(String fileLocation) {
if (fileLocation != null && !fileLocation.endsWith(File.separator)) {
fileLocation += File.separator;
}
location = fileLocation;
}
public String getKey(int version) throws KeyczarException {
return readFile(location + version);
}
public String getMetadata() throws KeyczarException {
return readFile(location + META_FILE);
}
private String readFile(String filename) throws KeyczarException {
try {
RandomAccessFile file = new RandomAccessFile(filename, "r");
byte[] contents = new byte[(int) file.length()];
file.read(contents);
file.close();
return new String(contents);
} catch (IOException e) {
throw new KeyczarException(
Messages.getString("KeyczarFileReader.FileError", filename), e);
}
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.UnsupportedTypeException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.util.Arrays;
/**
* Common base wrapper class for different types of KeyczarKeys (e.g. AesKey).
* Allows generating arbitrary key types or parsing key info from JSON
* string representations. Binds each key to a hash identifier and exposes
* the Stream used to access the key material.
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
abstract class KeyczarKey {
@Expose int size = getType().defaultSize();
void copyHeader(ByteBuffer dest) {
dest.put(Keyczar.FORMAT_VERSION);
dest.put(hash());
}
@Override
public boolean equals(Object o) {
try {
KeyczarKey key = (KeyczarKey) o;
return Arrays.equals(key.hash(), this.hash());
} catch (ClassCastException e) {
return false;
}
}
@Override
public int hashCode() {
return Util.toInt(this.hash());
}
abstract Stream getStream() throws KeyczarException;
/**
* Return this key's type
*
* @return KeyType of this key
*/
abstract KeyType getType();
/**
* Return this key's hash value
*
* @return A byte array hash of this key material
*/
abstract byte[] hash();
int size() {
return size;
}
/**
* Generates private key of desired type and of the default size.
*
* @param type KeyType desired
* @return KeyczarKey of desired type
* @throws KeyczarException for unsupported key types
*/
static KeyczarKey genKey(KeyType type) throws KeyczarException {
return genKey(type, type.defaultSize());
}
@Override
public String toString() {
return Util.gson().toJson(this);
}
/**
* Generates private key of the desired type and size. Cannot generate public
* key, instead must export public key set from private keys.
*
* If given size is unacceptable, falls back to using default size for the
* desired key type.
*
* @param type KeyType desired
* @param keySize desired length of key
* @return KeyczarKey of desired type
* @throws KeyczarException for unsupported key types
*/
static KeyczarKey genKey(KeyType type, int keySize) throws KeyczarException {
if (!type.isAcceptableSize(keySize)) {
keySize = type.defaultSize(); // fall back to default
}
switch (type) {
case AES:
return AesKey.generate(keySize);
case HMAC_SHA1:
return HmacKey.generate(keySize);
case DSA_PRIV:
return DsaPrivateKey.generate(keySize);
case RSA_PRIV:
return RsaPrivateKey.generate(keySize);
case EC_PRIV:
return EcPrivateKey.generate(keySize);
case RSA_PUB: case DSA_PUB:
throw new KeyczarException(
Messages.getString("KeyczarKey.PublicKeyExport", type));
}
throw new UnsupportedTypeException(type);
}
/**
* Converts a JSON string representation of a KeyczarKey into the appropriate
* KeyczarKey object.
*
* @param type KeyType being read from JSON input
* @param key JSON String representation of a KeyczarKey
* @return KeyczareKey of given type
* @throws KeyczarException if type mismatch with JSON input or unsupported
* key type
*/
static KeyczarKey readKey(KeyType type, String key) throws KeyczarException {
switch (type) {
case AES:
return AesKey.read(key);
case HMAC_SHA1:
return HmacKey.read(key);
case DSA_PRIV:
return DsaPrivateKey.read(key);
case DSA_PUB:
return DsaPublicKey.read(key);
case RSA_PRIV:
return RsaPrivateKey.read(key);
case RSA_PUB:
return RsaPublicKey.read(key);
case EC_PRIV:
return EcPrivateKey.read(key);
case EC_PUB:
return EcPublicKey.read(key);
}
throw new UnsupportedTypeException(type);
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
/**
* Interface for Keyczar Private Keys
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
interface KeyczarPrivateKey {
/**
* Get the public key paired with this private key.
*
* @return KeyczarPublicKey associated with this KeyczarPrivateKey
*/
KeyczarPublicKey getPublic();
}

View file

@ -0,0 +1,29 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
/**
* A placeholder public key class. We would use an interface, except want public
* keys to be instances of KeyczarKeys
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
abstract class KeyczarPublicKey extends KeyczarKey {
// Nothing here
}

View file

@ -0,0 +1,443 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import cz.cvut.keyczar.enums.Command;
import cz.cvut.keyczar.enums.Flag;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.enums.KeyStatus;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Command line tool for generating Keyczar key files. The following commands
* are supported:
* <ul>
* <li>create: create a new key store
* <li>addkey: add new key to existing store
* <li>pubkey: export a public key set from existing private key store
* <li>promote: promote status of a key version in existing store
* <li>demote: demote status of a key version in existing store
* <li>revoke: revoke key version in existing store (if scheduled to be)
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public class KeyczarTool {
static MockKeyczarReader mock = null;
/**
* Sets the mock KeyczarReader used only for testing.
*
* @param reader
*/
public static void setReader(MockKeyczarReader reader) {
mock = reader;
}
/**
* Returns a mock for testing purposes
*
* @return A mock KeyCzar reader
*/
public static MockKeyczarReader getMock() {
return mock;
}
/**
* Uses setFlags() to parse command line arguments and delegates to the
* appropriate command function or prints the usage instructions if command
* syntax is invalid.
*
* @param args from the command line
*/
public static void main(String[] args){
if (args.length == 0) {
printUsage();
} else {
try {
Command c = Command.getCommand(args[0]);
HashMap<Flag, String> flagMap = new HashMap<Flag, String>();
for (String arg : args) {
if (arg.startsWith("--")) {
arg = arg.substring(2); // Trim off the leading dashes
String[] nameValuePair = arg.split("=");
if (nameValuePair.length > 1) {
Flag f = Flag.getFlag(nameValuePair[0]);
flagMap.put(f, nameValuePair[1]);
}
}
}
// All commands need a location.
String locationFlag = flagMap.get(Flag.LOCATION);
if (locationFlag != null && !locationFlag.endsWith(File.separator)) {
locationFlag += File.separator;
}
switch (c) {
case CREATE:
String nameFlag = flagMap.get(Flag.NAME);
KeyPurpose purposeFlag =
KeyPurpose.getPurpose(flagMap.get(Flag.PURPOSE));
String asymmetricFlag = flagMap.get(Flag.ASYMMETRIC);
create(locationFlag, nameFlag, purposeFlag, asymmetricFlag); break;
case ADDKEY:
KeyStatus statusFlag = KeyStatus.getStatus(
flagMap.get(Flag.STATUS));
String crypterFlag = flagMap.get(Flag.CRYPTER);
int sizeFlag = -1;
if (flagMap.containsKey(Flag.SIZE)) {
sizeFlag = Integer.parseInt(flagMap.get(Flag.SIZE));
}
addKey(locationFlag, statusFlag, crypterFlag, sizeFlag);
break;
case PUBKEY:
publicKeys(locationFlag, flagMap.get(Flag.DESTINATION));
break;
case PROMOTE:
promote(locationFlag, Integer.parseInt(flagMap.get(Flag.VERSION)));
break;
case DEMOTE:
demote(locationFlag, Integer.parseInt(flagMap.get(Flag.VERSION)));
break;
case REVOKE:
revoke(locationFlag, Integer.parseInt(flagMap.get(Flag.VERSION)));
break;
case USEKEY:
if (args.length > 2) {
useKey(args[1], locationFlag, flagMap.get(Flag.DESTINATION),
flagMap.get(Flag.CRYPTER));
} else {
printUsage();
}
break;
}
} catch (NumberFormatException e) {
e.printStackTrace();
printUsage();
} catch (IllegalArgumentException e) {
e.printStackTrace();
printUsage();
} catch (NullPointerException e) {
e.printStackTrace();
printUsage();
} catch (KeyczarException e) {
e.printStackTrace();
printUsage();
}
}
}
private static void useKey(String msg, String locationFlag,
String destinationFlag, String crypterFlag) throws KeyczarException {
GenericKeyczar genericKeyczar =
createGenericKeyczar(locationFlag, crypterFlag);
if (destinationFlag == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefinePublic"));
}
String answer = "";
KeyczarReader reader = new KeyczarFileReader(locationFlag);
if (crypterFlag != null) {
Crypter keyCrypter = new Crypter(crypterFlag);
reader = new KeyczarEncryptedReader(reader, keyCrypter);
}
switch (genericKeyczar.getMetadata().getPurpose()) {
case DECRYPT_AND_ENCRYPT:
Crypter crypter = new Crypter(reader);
answer = crypter.encrypt(msg);
break;
case SIGN_AND_VERIFY:
Signer signer = new Signer(reader);
answer = signer.sign(msg);
break;
default:
throw new KeyczarException(
Messages.getString("KeyczarTool.UnsupportedPurpose",
genericKeyczar.getMetadata().getPurpose()));
}
genericKeyczar.writeFile(answer, destinationFlag);
}
/**
* Adds key of given status to key set and pushes update to meta file.
* Requires location and status flags.
* @param sizeFlag
* @param crypterFlag
* @param statusFlag
* @param locationFlag
*
* @throws KeyczarException if location flag is not set or
* key type is unsupported
*/
private static void addKey(String locationFlag, KeyStatus statusFlag,
String crypterFlag, int sizeFlag) throws KeyczarException {
GenericKeyczar genericKeyczar =
createGenericKeyczar(locationFlag, crypterFlag);
if (sizeFlag == -1) { // use default size
genericKeyczar.addVersion(statusFlag);
} else { // use given size
genericKeyczar.addVersion(statusFlag, sizeFlag);
}
if (crypterFlag != null) {
Encrypter encrypter = new Encrypter(crypterFlag);
updateGenericKeyczar(genericKeyczar, encrypter, locationFlag);
} else {
updateGenericKeyczar(genericKeyczar, locationFlag);
}
}
/**
* Creates a new KeyMetadata object, deciding its name, purpose and type
* based on command line flags. Outputs its JSON representation in a file
* named meta in the directory given by the location flag.
* @param asymmetricFlag
* @param purposeFlag
* @param nameFlag
* @param locationFlag
*
* @throws KeyczarException if location or purpose flags are not set
*/
private static void create(String locationFlag, String nameFlag,
KeyPurpose purposeFlag, String asymmetricFlag) throws KeyczarException {
KeyMetadata kmd = null;
if (purposeFlag == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefinePurpose"));
}
switch (purposeFlag) {
case TEST:
kmd = new KeyMetadata(nameFlag, KeyPurpose.TEST, KeyType.TEST);
break;
case SIGN_AND_VERIFY:
if (asymmetricFlag != null) {
if (asymmetricFlag.equalsIgnoreCase("rsa")) {
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.RSA_PRIV);
} else if (asymmetricFlag.equalsIgnoreCase("ec")) {
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.EC_PRIV);
} else { // Default to DSA
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.DSA_PRIV);
}
} else { // HMAC-SHA1
kmd = new KeyMetadata(nameFlag, KeyPurpose.SIGN_AND_VERIFY,
KeyType.HMAC_SHA1);
}
break;
case DECRYPT_AND_ENCRYPT:
if (asymmetricFlag != null) { // Default to RSA
kmd = new KeyMetadata(nameFlag, KeyPurpose.DECRYPT_AND_ENCRYPT,
KeyType.RSA_PRIV);
} else { // AES
kmd = new KeyMetadata(nameFlag, KeyPurpose.DECRYPT_AND_ENCRYPT,
KeyType.AES);
}
break;
}
if (kmd == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.UnsupportedPurpose", purposeFlag));
}
if (mock == null) {
if (locationFlag == null) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefineLocation"));
}
File file = new File(locationFlag + KeyczarFileReader.META_FILE);
if (file.exists()) {
throw new KeyczarException(
Messages.getString("KeyczarTool.FileExists", file));
}
try {
FileOutputStream metaOutput = new FileOutputStream(file);
metaOutput.write(kmd.toString().getBytes());
metaOutput.close();
} catch (IOException e) {
throw new KeyczarException(Messages.getString(
"KeyczarTool.UnableToWrite", file.toString()), e);
}
} else { // for testing purposes, update mock kmd
mock.setMetadata(kmd);
}
}
/**
* If the version flag is set, promotes the status of given key version.
* Pushes update to meta file. Requires location and version flags.
* @param versionFlag The version to promote
* @param locationFlag The location of the key set
*
* @throws KeyczarException if location or version flag is not set
* or promotion is illegal.
*/
private static void promote(String locationFlag, int versionFlag)
throws KeyczarException {
if (versionFlag < 0) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MissingVersion"));
}
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.promote(versionFlag);
updateGenericKeyczar(genericKeyczar, locationFlag);
}
/**
* If the version flag is set, demotes the status of given key version.
* Pushes update to meta file. Requires location and version flags.
* @param versionFlag The verion to demote
* @param locationFlag The location of the key set
*
* @throws KeyczarException if location or version flag is not set
* or demotion is illegal.
*/
private static void demote(String locationFlag, int versionFlag)
throws KeyczarException {
if (versionFlag < 0) {
throw new KeyczarException(
Messages.getString("KeyczarTool.MissingVersion"));
}
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.demote(versionFlag);
updateGenericKeyczar(genericKeyczar, locationFlag);
}
/**
* Creates and exports public key files to given destination based on
* private key set at given location.
* @param destinationFlag Destionation of public keys
* @param locationFlag Location of private key set
*
* @throws KeyczarException if location or destination flag is not set.
*/
private static void publicKeys(String locationFlag, String destinationFlag)
throws KeyczarException {
if (mock == null && destinationFlag == null) { // only if not testing
throw new KeyczarException(
Messages.getString("KeyczarTool.MustDefineDestination"));
}
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.publicKeyExport(destinationFlag);
}
/**
* If the version flag is set, revokes the key of the given version.
* Pushes update to meta file. Deletes old key file. Requires location
* and version flags.
* @param versionFlag The version to revoke
* @param locationFlag The location of the key set
*
* @throws KeyczarException if location or version flag is not set or if
* unable to delete revoked key file.
*/
private static void revoke(String locationFlag, int versionFlag)
throws KeyczarException {
GenericKeyczar genericKeyczar = createGenericKeyczar(locationFlag);
genericKeyczar.revoke(versionFlag);
// update meta files, key files
updateGenericKeyczar(genericKeyczar, locationFlag);
if (mock == null) { // not necessary for testing
File revokedVersion = new File(locationFlag + versionFlag);
if (!revokedVersion.delete()) { // delete old key file
throw new KeyczarException(
Messages.getString("KeyczarTool.UnableToDelete"));
}
} else {
mock.removeKey(versionFlag);
}
}
/**
* Prints the usage instructions with list of commands and flags.
*/
private static void printUsage() {
ArrayList<String> usageParams = new ArrayList<String>();
for (Command c : Command.values()) {
usageParams.add(c.toString());
}
for (Flag f : Flag.values()) {
usageParams.add(f.toString());
}
System.out.println(
Messages.getString("KeyczarTool.Usage", usageParams.toArray()));
}
private static GenericKeyczar createGenericKeyczar(String locationFlag)
throws KeyczarException {
return createGenericKeyczar(locationFlag, null);
}
/**
* Creates a GenericKeyczar object based on locationFlag if it is set.
* Alternatively, it can use the mock KeyczarReader if it is set.
* @param locationFlag The location of the key set
* @param crypterFlag The location of a crypter to decrypt the key set
* @return GenericKeyczar if locationFlag set
* @throws KeyczarException if locationFlag not set
*/
private static GenericKeyczar createGenericKeyczar(String locationFlag,
String crypterFlag) throws KeyczarException {
if (mock != null) {
return new GenericKeyczar(mock);
}
if (locationFlag == null) {
throw new KeyczarException(Messages.getString("KeyczarTool.NeedLocation",
Messages.getString("KeyczarTool.Location")));
}
KeyczarReader reader = new KeyczarFileReader(locationFlag);
if (crypterFlag != null) {
Crypter keyDecrypter = new Crypter(crypterFlag);
reader = new KeyczarEncryptedReader(reader, keyDecrypter);
}
return new GenericKeyczar(reader);
}
private static void updateGenericKeyczar(GenericKeyczar genericKeyczar,
String locationFlag) throws KeyczarException {
updateGenericKeyczar(genericKeyczar, null, locationFlag);
}
private static void updateGenericKeyczar(GenericKeyczar genericKeyczar,
Encrypter encrypter, String locationFlag) throws KeyczarException {
if (mock != null) {
mock.setMetadata(genericKeyczar.getMetadata()); // update metadata
for (KeyVersion version : genericKeyczar.getVersions()) {
mock.setKey(version.getVersionNumber(), genericKeyczar.getKey(version));
} // update key data
} else if (encrypter != null) {
genericKeyczar.writeEncrypted(locationFlag, encrypter);
} else {
genericKeyczar.write(locationFlag);
}
}
}

View file

@ -0,0 +1,118 @@
package cz.cvut.keyczar;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.enums.KeyStatus;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.BadVersionException;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.util.Util;
import java.util.HashMap;
import java.util.Map;
/**
* A mock representation of a KeyczarReader used for testing.
*
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public class MockKeyczarReader implements KeyczarReader {
private Map<Integer, KeyczarKey> keys, publicKeys; // link version #s to keys
private KeyMetadata kmd, publicKmd;
public MockKeyczarReader(String n, KeyPurpose p, KeyType t) {
kmd = new KeyMetadata(n, p, t);
publicKmd = null;
keys = new HashMap<Integer, KeyczarKey>();
publicKeys = new HashMap<Integer, KeyczarKey>();
}
public String getKey(int version) throws KeyczarException {
if (keys.containsKey(version)) {
return keys.get(version).toString();
} else {
throw new BadVersionException((byte) version);
}
}
public String getMetadata() {
return Util.gson().toJson(kmd);
}
public void setMetadata(KeyMetadata newKmd) {
kmd = newKmd;
}
public void setPublicKeyMetadata(KeyMetadata publicKmd) {
this.publicKmd = publicKmd;
}
public void setKey(int versionNumber, KeyczarKey key) {
keys.put(versionNumber, key);
}
public void setPublicKey(int versionNumber, KeyczarKey key) {
publicKeys.put(versionNumber, key);
}
public void removeKey(int versionNumber) {
keys.remove(versionNumber);
}
public String name() {
return kmd.getName();
}
public KeyPurpose purpose() {
return kmd.getPurpose();
}
public KeyType type() {
return kmd.getType();
}
public boolean addKey(int versionNumber, KeyStatus status)
throws KeyczarException {
KeyczarKey key = KeyczarKey.genKey(kmd.getType());
keys.put(versionNumber, key);
return kmd.addVersion(new KeyVersion(versionNumber, status, false));
}
public boolean addKey(int versionNumber, KeyStatus status, int size)
throws KeyczarException {
KeyczarKey key = KeyczarKey.genKey(kmd.getType(), size);
keys.put(versionNumber, key);
return kmd.addVersion(new KeyVersion(versionNumber, status, false));
}
public KeyStatus getStatus(int versionNumber) {
return kmd.getVersion(versionNumber).getStatus();
}
public boolean existsVersion(int versionNumber) {
return keys.containsKey(versionNumber);
}
public boolean exportedPublicKeySet() {
return publicKmd != null;
}
public boolean hasPublicKey(int versionNumber) {
KeyczarPrivateKey privateKey = (KeyczarPrivateKey) keys.get(versionNumber);
KeyczarPublicKey publicKey =
(KeyczarPublicKey) publicKeys.get(versionNumber);
return privateKey != null && publicKey != null &&
publicKey.equals(privateKey.getPublic());
}
public int numKeys() {
return keys.size();
}
public int getKeySize(int versionNumber) {
return keys.get(versionNumber).size();
}
}

View file

@ -0,0 +1,286 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.DecryptingStream;
import cz.cvut.keyczar.interfaces.EncryptingStream;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.RSAPrivateCrtKeySpec;
import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;
/**
* Wrapping class for RSA Private Keys
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
class RsaPrivateKey extends KeyczarKey implements KeyczarPrivateKey {
private static final String CRYPT_ALGORITHM =
"RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING";
private static final String KEY_GEN_ALGORITHM = "RSA";
@Expose private RsaPublicKey publicKey;
@Expose private String privateExponent;
@Expose private String primeP;
@Expose private String primeQ;
@Expose private String primeExponentP;
@Expose private String primeExponentQ;
@Expose private String crtCoefficient;
private static final String SIG_ALGORITHM = "SHA1withRSA";
private RSAPrivateCrtKey jcePrivateKey;
private RsaPrivateKey() {
publicKey = new RsaPublicKey();
}
@Override
Stream getStream() throws KeyczarException {
return new RsaPrivateStream();
}
@Override
KeyType getType() {
return KeyType.RSA_PRIV;
}
@Override
byte[] hash() {
return publicKey.hash();
}
static RsaPrivateKey read(String input) throws KeyczarException {
RsaPrivateKey key = Util.gson().fromJson(input, RsaPrivateKey.class);
key.init();
return key;
}
static RsaPrivateKey generate() throws KeyczarException {
return generate(KeyType.RSA_PRIV.defaultSize());
}
public KeyczarPublicKey getPublic() {
return publicKey;
}
private void init() throws KeyczarException {
// Read all the JSON fields and use it to instantiate a RSAPrivateCrtKey
try {
KeyFactory factory = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
BigInteger mod = new BigInteger(Base64Coder.decode(publicKey.modulus));
BigInteger pubExp =
new BigInteger(Base64Coder.decode(publicKey.publicExponent));
// Set the public key values
publicKey.set(mod, pubExp);
BigInteger privExp = new BigInteger(Base64Coder.decode(privateExponent));
BigInteger p = new BigInteger(Base64Coder.decode(primeP));
BigInteger q = new BigInteger(Base64Coder.decode(primeQ));
BigInteger expP = new BigInteger(Base64Coder.decode(primeExponentP));
BigInteger expQ = new BigInteger(Base64Coder.decode(primeExponentQ));
BigInteger crt = new BigInteger(Base64Coder.decode(crtCoefficient));
RSAPrivateCrtKeySpec spec =
new RSAPrivateCrtKeySpec(mod, pubExp, privExp, p, q, expP, expQ, crt);
jcePrivateKey = (RSAPrivateCrtKey) factory.generatePrivate(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
static RsaPrivateKey generate(int keySize) throws KeyczarException {
RsaPrivateKey key = new RsaPrivateKey();
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KEY_GEN_ALGORITHM);
key.size = keySize;
key.publicKey.size = key.size;
kpg.initialize(key.size());
KeyPair pair = kpg.generateKeyPair();
key.jcePrivateKey = (RSAPrivateCrtKey) pair.getPrivate();
key.publicKey.set(key.jcePrivateKey.getModulus(),
key.jcePrivateKey.getPublicExponent());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
// Set all the JSON fields for this RSA Private CRT key
key.privateExponent =
Base64Coder.encode(key.jcePrivateKey.getPrivateExponent().toByteArray());
key.primeP =
Base64Coder.encode(key.jcePrivateKey.getPrimeP().toByteArray());
key.primeQ =
Base64Coder.encode(key.jcePrivateKey.getPrimeQ().toByteArray());
key.primeExponentP =
Base64Coder.encode(key.jcePrivateKey.getPrimeExponentP().toByteArray());
key.primeExponentQ =
Base64Coder.encode(key.jcePrivateKey.getPrimeExponentQ().toByteArray());
key.crtCoefficient =
Base64Coder.encode(key.jcePrivateKey.getCrtCoefficient().toByteArray());
return key;
}
private class RsaPrivateStream implements SigningStream, VerifyingStream,
DecryptingStream, EncryptingStream {
private Cipher cipher;
private EncryptingStream encryptingStream;
private Signature signature;
private VerifyingStream verifyingStream;
public RsaPrivateStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
verifyingStream = (VerifyingStream) publicKey.getStream();
cipher = Cipher.getInstance(CRYPT_ALGORITHM);
encryptingStream = (EncryptingStream) publicKey.getStream();
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public int doFinalDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.doFinal(input, output);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int doFinalEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
return encryptingStream.doFinalEncrypt(input, output);
}
public SigningStream getSigningStream() throws KeyczarException {
return encryptingStream.getSigningStream();
}
public VerifyingStream getVerifyingStream() {
return new VerifyingStream() {
public int digestSize() {
return 0;
}
public void initVerify() {
// Do nothing
}
public void updateVerify(ByteBuffer input) {
// Do nothing
}
public boolean verify(ByteBuffer signature) {
// Do nothing
return true;
}
};
}
public void initDecrypt(ByteBuffer input) throws KeyczarException {
try {
cipher.init(Cipher.DECRYPT_MODE, jcePrivateKey);
} catch (InvalidKeyException e) {
throw new KeyczarException(e);
}
}
public int initEncrypt(ByteBuffer output) throws KeyczarException {
return encryptingStream.initEncrypt(output);
}
public void initSign() throws KeyczarException {
try {
signature.initSign(jcePrivateKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public void initVerify() throws KeyczarException {
verifyingStream.initVerify();
}
public int maxOutputSize(int inputLen) {
return getType().getOutputSize() * 2;
}
public void sign(ByteBuffer output) throws KeyczarException {
try {
byte[] sig = signature.sign();
output.put(sig);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public int updateDecrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.update(input, output);
} catch (ShortBufferException e) {
throw new KeyczarException(e);
}
}
public int updateEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
return encryptingStream.updateEncrypt(input, output);
}
public void updateSign(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
verifyingStream.updateVerify(input);
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
return verifyingStream.verify(sig);
}
}
}

View file

@ -0,0 +1,206 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import com.google.gson.annotations.Expose;
import cz.cvut.keyczar.enums.KeyType;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.UnsupportedTypeException;
import cz.cvut.keyczar.interfaces.EncryptingStream;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.interfaces.Stream;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
import javax.crypto.ShortBufferException;
/**
* Wrapping class for RSA Public Keys. These must be exported from existing RSA
* private key sets.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
class RsaPublicKey extends KeyczarPublicKey {
private static final String CRYPT_ALGORITHM =
"RSA/ECB/OAEPWITHSHA1ANDMGF1PADDING";
private static final String KEY_GEN_ALGORITHM = "RSA";
private static final String SIG_ALGORITHM = "SHA1withRSA";
private RSAPublicKey jcePublicKey;
@Expose String modulus;
@Expose String publicExponent;
private byte[] hash = new byte[Keyczar.KEY_HASH_SIZE];
@Override
public byte[] hash() {
return hash;
}
@Override
Stream getStream() throws KeyczarException {
return new RsaStream();
}
@Override
KeyType getType() {
return KeyType.RSA_PUB;
}
void set(BigInteger mod, BigInteger pubExp) throws KeyczarException {
modulus = Base64Coder.encode(mod.toByteArray());
publicExponent = Base64Coder.encode(pubExp.toByteArray());
init();
}
void init() throws KeyczarException {
byte[] modBytes = Base64Coder.decode(modulus);
byte[] pubExpBytes = Base64Coder.decode(publicExponent);
BigInteger mod = new BigInteger(modBytes);
BigInteger pubExp = new BigInteger(pubExpBytes);
// Sets the JCE Public key value
try {
KeyFactory kf = KeyFactory.getInstance(KEY_GEN_ALGORITHM);
RSAPublicKeySpec spec = new RSAPublicKeySpec(mod, pubExp);
jcePublicKey = (RSAPublicKey) kf.generatePublic(spec);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
byte[] fullHash = Util.prefixHash(Util.stripLeadingZeros(modBytes),
Util.stripLeadingZeros(pubExpBytes));
System.arraycopy(fullHash, 0, hash, 0, hash.length);
}
static RsaPublicKey read(String input) throws KeyczarException {
RsaPublicKey key = Util.gson().fromJson(input, RsaPublicKey.class);
if (key.getType() != KeyType.RSA_PUB) {
throw new UnsupportedTypeException(key.getType());
}
key.init();
return key;
}
private class RsaStream implements VerifyingStream, EncryptingStream {
private Cipher cipher;
private Signature signature;
public RsaStream() throws KeyczarException {
try {
signature = Signature.getInstance(SIG_ALGORITHM);
cipher = Cipher.getInstance(CRYPT_ALGORITHM);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int digestSize() {
return getType().getOutputSize();
}
public int doFinalEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.doFinal(input, output);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public SigningStream getSigningStream() {
return new SigningStream() {
public int digestSize() {
return 0;
}
public void initSign() {
// Do nothing
}
public void sign(ByteBuffer output) {
// Do nothing
}
public void updateSign(ByteBuffer input) {
// Do nothing
}
};
}
public int initEncrypt(ByteBuffer output) throws KeyczarException {
try {
cipher.init(Cipher.ENCRYPT_MODE, jcePublicKey);
} catch (InvalidKeyException e) {
throw new KeyczarException(e);
}
return 0;
}
public void initVerify() throws KeyczarException {
try {
signature.initVerify(jcePublicKey);
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
public int maxOutputSize(int inputLen) {
return getType().getOutputSize();
}
public int updateEncrypt(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
try {
return cipher.update(input, output);
} catch (ShortBufferException e) {
throw new KeyczarException(e);
}
}
public void updateVerify(ByteBuffer input) throws KeyczarException {
try {
signature.update(input);
} catch (SignatureException e) {
throw new KeyczarException(e);
}
}
public boolean verify(ByteBuffer sig) throws KeyczarException {
try {
return signature.verify(sig.array(), sig.position(), sig.limit()
- sig.position());
} catch (GeneralSecurityException e) {
throw new KeyczarException(e);
}
}
}
}

View file

@ -0,0 +1,198 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.NoPrimaryKeyException;
import cz.cvut.keyczar.exceptions.ShortBufferException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.nio.ByteBuffer;
/**
* Signers may both sign and verify data using sets of symmetric or private
* keys. Sets of public keys may only be used with {@link Verifier} objects.
*
* {@link Signer} objects should be used with symmetric or private key sets to
* generate signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Signer extends Verifier {
static final int TIMESTAMP_SIZE = 8;
private static final Logger SIGNER_LOGGER = Logger.getLogger(Signer.class);
private final StreamQueue<SigningStream> SIGN_QUEUE =
new StreamQueue<SigningStream>();
/**
* Initialize a new Signer with a KeyczarReader. The corresponding key set
* must have a purpose {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Signer(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Signer with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Signer(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Returns the size of signatures produced by this Signer.
*
* @return The size of signatures produced by this Signer.
* @throws KeyczarException If this Signer does not have a primary or a
* JCE exception occurs.
*/
public int digestSize() throws KeyczarException {
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
return HEADER_SIZE + ((SigningStream) signingKey.getStream()).digestSize();
}
/**
* Sign the given input and return a signature.
*
* @param input The input to sign.
* @return A byte array representation of a signature.
* @throws KeyczarException If this Signer does not have a primary or a
* JCE exception occurs.
*/
public byte[] sign(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(digestSize());
sign(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Sign the given input and write the signature to the given ByteBuffer
*
* @param input The input to sign.
* @param output The ByteBuffer to write the signature in.
* @throws KeyczarException If this Signer does not have a primary or a
* JCE exception occurs.
*/
public void sign(ByteBuffer input, ByteBuffer output)
throws KeyczarException {
sign(input, null, 0, output);
}
/**
* This allows other classes in the package to pass in hidden data and/or
* expiration data to be signed.
*
* @param input The input to be signed
* @param hidden Hidden data to be signed
* @param expirationTime The expiration time of this signature
* @param output The destination of this signature
* @throws KeyczarException
*/
void sign(ByteBuffer input, ByteBuffer hidden, long expirationTime,
ByteBuffer output) throws KeyczarException {
SIGNER_LOGGER.info(Messages.getString("Signer.Signing", input.remaining()));
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
SigningStream stream = SIGN_QUEUE.poll();
if (stream == null) {
stream = (SigningStream) signingKey.getStream();
}
int spaceNeeded = digestSize();
if (expirationTime > 0) {
spaceNeeded += TIMESTAMP_SIZE;
}
if (output.capacity() < spaceNeeded) {
throw new ShortBufferException(output.capacity(), spaceNeeded);
}
ByteBuffer header = ByteBuffer.allocate(HEADER_SIZE);
signingKey.copyHeader(header);
header.rewind();
stream.initSign();
// Sign the header and write it to the output buffer
output.mark();
output.put(header);
if (expirationTime > 0) {
// Write an expiration time following the header and sign it.
ByteBuffer expiration = ByteBuffer.wrap(Util.fromLong(expirationTime));
output.put(expiration);
expiration.rewind();
stream.updateSign(expiration);
}
if (hidden != null && hidden.remaining() > 0) {
// Sign any hidden data
stream.updateSign(hidden);
}
// Sign the input data
stream.updateSign(input);
// Sign the version byte
stream.updateSign(ByteBuffer.wrap(FORMAT_BYTES));
// Write the signature to the output
stream.sign(output);
output.limit(output.position());
SIGN_QUEUE.add(stream);
}
/**
* Signs the given input String and return the output as a web-safe Base64
* encoded String.
*
* @param input The input String to sign.
* @return A web-safe Base64-encoded representation of a signature on the
* input.
* @throws KeyczarException
*/
public String sign(String input) throws KeyczarException {
return Base64Coder.encode(sign(input.getBytes()));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.SIGN_AND_VERIFY;
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import cz.cvut.keyczar.interfaces.Stream;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Caches StreamQueue objects for KeyczarKeys so they can reused.
*
* @author steveweis@gmail.com (Steve Weis)
*
* @param <T>
*/
class StreamCache<T extends Stream> {
private final ConcurrentHashMap<KeyczarKey, StreamQueue<T>> cacheMap =
new ConcurrentHashMap<KeyczarKey, StreamQueue<T>>();
void put(KeyczarKey key, T s) {
getQueue(key).add(s);
}
T get(KeyczarKey key) {
return getQueue(key).poll();
}
StreamQueue<T> getQueue(KeyczarKey key) {
StreamQueue<T> queue = cacheMap.get(key);
if (queue != null) {
return queue;
}
StreamQueue<T> freshQueue = new StreamQueue<T>();
queue = cacheMap.putIfAbsent(key, freshQueue);
if (queue != null) {
// Another thread already inserted a fresh queue with this key.
return queue;
}
return freshQueue;
}
}
/**
* A thread-safe queue for Streams and their derived classes.
*
* @author steveweis@gmail.com (Steve Weis)
*
* @param <T>
*/
class StreamQueue<T extends Stream> extends ConcurrentLinkedQueue<T> {
}

View file

@ -0,0 +1,128 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Timeout signers can generate signatures that are valid until a specified
* expiration time. Timeout signatures are verified by
* {@link cz.cvut.keyczar.TimeoutVerifier} objects.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class TimeoutSigner extends TimeoutVerifier {
private Signer signer;
/**
* Initialize a new TimeoutSigner with a KeyczarReader.
* The corresponding key set must have a purpose
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutSigner(KeyczarReader reader) throws KeyczarException {
this.signer = new Signer(reader);
setVerifier(this.signer);
}
/**
* Initialize a new TimeoutSigner with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding
* key set must have a purpose of
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutSigner(String fileLocation) throws KeyczarException {
this.signer = new Signer(fileLocation);
setVerifier(this.signer);
}
/**
* Initialize a new TimeoutSigner with a Signer object.
*
* @param signer Signer to be used for timeout signatures
*/
public TimeoutSigner(Signer signer){
this.signer = signer;
setVerifier(this.signer);
}
/**
* Sign the given input and return a signature that is valid until the
* expiration time given as the number of milliseconds since "the epoch"
* of 1/1/1970 00:00:00 GMT
*
* @param input The input to be signed
* @param expirationTime The expiration time in milliseconds since 1/1/1970
* 00:00:00 GMT
* @return The signature as a web safe Base64 string
* @throws KeyczarException
*/
public String timeoutSign(String input, long expirationTime)
throws KeyczarException {
return Base64Coder.encode(timeoutSign(input.getBytes(), expirationTime));
}
/**
* Sign the given input and return a signature that is valid until the
* expiration time given as the number of milliseconds since "the epoch"
* of 1/1/1970 00:00:00 GMT
*
* @param input The input to be signed
* @param expirationTime The expiration time in milliseconds since 1/1/1970
* 00:00:00 GMT
* @return The signature
* @throws KeyczarException
*/
public byte[] timeoutSign(byte[] input, long expirationTime)
throws KeyczarException {
ByteBuffer output =
ByteBuffer.allocate(signer.digestSize() + Signer.TIMESTAMP_SIZE);
timeoutSign(ByteBuffer.wrap(input), expirationTime, output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* Signs the input and produces a signature that is valid until the
* expiration time given as the number of milliseconds since "the epoch"
* of 1/1/1970 00:00:00 GMT
*
* @param input The input to be signed
* @param expirationTime The expiration time in milliseconds since 1/1/1970
* 00:00:00 GMT
* @param output The destination of this signature
* @throws KeyczarException
*/
public void timeoutSign(ByteBuffer input, long expirationTime,
ByteBuffer output) throws KeyczarException {
signer.sign(input, null, expirationTime, output);
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.ShortSignatureException;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.util.Base64Coder;
import cz.cvut.keyczar.util.Util;
import java.nio.ByteBuffer;
import java.util.Date;
/**
* TimeoutVerifiers verify timeout signatures generated by
* {@link cz.cvut.keyczar.TimeoutSigner} objects
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class TimeoutVerifier {
private Verifier verifier;
TimeoutVerifier() {
// Do nothing here.
}
/**
* Initialize a new TimeoutVerifier with a KeyczarReader.
* The corresponding key set must have a purpose
* {@link cz.cvut.keyczar.enums.KeyPurpose#VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutVerifier(KeyczarReader reader) throws KeyczarException {
setVerifier(new Verifier(reader));
}
/**
* Initialize a new TimeoutVerifier with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding
* key set must have a purpose of
* {@link cz.cvut.keyczar.enums.KeyPurpose#VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public TimeoutVerifier(String fileLocation) throws KeyczarException {
setVerifier(new Verifier(fileLocation));
}
/**
* Initialize a new TimeoutVerifier with a Verifier object.
*
* @param verifier Signer to be used for timeout signatures
*/
public TimeoutVerifier(Verifier verifier) {
setVerifier(verifier);
}
void setVerifier(Verifier verifier) {
this.verifier = verifier;
}
/**
* Verifies the timeout signature on the given String
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(String data, String signature) throws KeyczarException {
return verify(data.getBytes(), Base64Coder.decode(signature));
}
/**
* Verifies a timeout signature on the given byte array of data
*
* @param data The data to verify the signature on
* @param signature The timeput signture to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(byte[] data, byte[] signature) throws KeyczarException {
return verify(ByteBuffer.wrap(data), ByteBuffer.wrap(signature));
}
/**
* Verify the timeout signature on the given data
*
* @param data
* @param timeoutSignature
* @return A boolean value indicating whether the timeout signature verified.
* This will be false if the signature has expired.
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(ByteBuffer data, ByteBuffer timeoutSignature)
throws KeyczarException {
if (timeoutSignature.remaining() < Keyczar.HEADER_SIZE + Signer.TIMESTAMP_SIZE) {
throw new ShortSignatureException(timeoutSignature.remaining());
}
byte[] header = new byte[Keyczar.HEADER_SIZE];
timeoutSignature.get(header);
// Get the timestamp and check that it has not expired
byte[] timestamp = new byte[Signer.TIMESTAMP_SIZE];
timeoutSignature.get(timestamp);
long expirationTime = Util.toLong(timestamp);
Date expiration = new Date(expirationTime);
Date now = new Date();
if (now.after(expiration)) {
return false;
}
ByteBuffer slicedSignature =
ByteBuffer.allocate(Keyczar.HEADER_SIZE + timeoutSignature.remaining());
slicedSignature.put(header);
slicedSignature.put(timeoutSignature);
slicedSignature.rewind();
// The timeout is signed in a timeout signature. Prepend it to the data and
// pass it to the parent implementation in Verfier
ByteBuffer prependedData =
ByteBuffer.allocate(Signer.TIMESTAMP_SIZE + data.remaining());
prependedData.put(timestamp);
prependedData.put(data);
prependedData.rewind();
return verifier.verify(prependedData, slicedSignature);
}
}

View file

@ -0,0 +1,162 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.NoPrimaryKeyException;
import cz.cvut.keyczar.exceptions.ShortBufferException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.interfaces.SigningStream;
import cz.cvut.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* UnversionedSigners may both sign and verify data using sets of symmetric or
* private keys. Sets of public keys may only be used with {@link Verifier}
* objects.
*
* UnversionedSigners do not include any key versioning in their outputs. They
* will return standard signatures (i.e. HMAC-SHA1, RSA-SHA1, DSA-SHA1).
*
* {@link UnversionedSigner} objects should be used with symmetric or private key sets to
* generate signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class UnversionedSigner extends UnversionedVerifier {
static final int TIMESTAMP_SIZE = 8;
private static final Logger SIGNER_LOGGER = Logger.getLogger(UnversionedSigner.class);
private final StreamQueue<SigningStream> SIGN_QUEUE =
new StreamQueue<SigningStream>();
/**
* Initialize a new UnversionedSigner with a KeyczarReader. The corresponding
* key set must have a purpose
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedSigner(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new UnversionedSigner with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding key
* set must have a purpose of
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedSigner(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Returns the size of signatures produced by this UnversionedSigner.
*
* @return The size of signatures produced by this UnversionedSigner.
* @throws KeyczarException If this UnversionedSigner does not have a primary
* or a JCE exception occurs.
*/
public int digestSize() throws KeyczarException {
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
return ((SigningStream) signingKey.getStream()).digestSize();
}
/**
* Sign the given input and return a signature.
*
* @param input The input to sign.
* @return A byte array representation of a signature.
* @throws KeyczarException If this UnversionedSigner does not have a primary
* or a JCE exception occurs.
*/
public byte[] sign(byte[] input) throws KeyczarException {
ByteBuffer output = ByteBuffer.allocate(digestSize());
sign(ByteBuffer.wrap(input), output);
output.reset();
byte[] outputBytes = new byte[output.remaining()];
output.get(outputBytes);
return outputBytes;
}
/**
* This allows other classes in the package to pass in hidden data and/or
* expiration data to be signed.
*
* @param input The input to be signed
* @param output The destination of this signature
* @throws KeyczarException
*/
void sign(ByteBuffer input, ByteBuffer output) throws KeyczarException {
SIGNER_LOGGER.info(Messages.getString("Signer.Signing", input.remaining()));
KeyczarKey signingKey = getPrimaryKey();
if (signingKey == null) {
throw new NoPrimaryKeyException();
}
SigningStream stream = SIGN_QUEUE.poll();
if (stream == null) {
stream = (SigningStream) signingKey.getStream();
}
int spaceNeeded = digestSize();
if (output.capacity() < spaceNeeded) {
throw new ShortBufferException(output.capacity(), spaceNeeded);
}
stream.initSign();
// Sign the header and write it to the output buffer
output.mark();
// Sign the input data
stream.updateSign(input);
// Write the signature to the output
stream.sign(output);
output.limit(output.position());
SIGN_QUEUE.add(stream);
}
/**
* Signs the given input String and return the output as a web-safe Base64
* encoded String.
*
* @param input The input String to sign.
* @return A web-safe Base64-encoded representation of a signature on the
* input.
* @throws KeyczarException
*/
public String sign(String input) throws KeyczarException {
return Base64Coder.encode(sign(input.getBytes()));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return purpose == KeyPurpose.SIGN_AND_VERIFY;
}
}

View file

@ -0,0 +1,150 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.Map.Entry;
/**
* Unversioned Verifiers are used strictly to verify standard signatures
* (i.e. HMAC-SHA1, DSA-SHA1, RSA-SHA1) with no key version information.
* Typically, UnversionedVerifiers will read sets of public keys, although may
* also be instantiated with sets of symmetric or private keys.
*
* Since UnversionedVerifiers verify standard signatures, they will try all keys
* in a set until one verifies.
*
* {@link UnversionedSigner} objects should be used with symmetric or private
* key sets to generate unversioned signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class UnversionedVerifier extends Keyczar {
private static final Logger VERIFIER_LOGGER =
Logger.getLogger(UnversionedVerifier.class);
private static final StreamCache<VerifyingStream> VERIFY_CACHE
= new StreamCache<VerifyingStream>();
/**
* Initialize a new UnversionedVerifier with a KeyczarReader.
* The corresponding key set must have a purpose of either
* {@link cz.cvut.keyczar.enums.KeyPurpose#VERIFY} or
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedVerifier(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new UnversionedVerifier with a key set location. This will
* attempt to read the keys using a KeyczarFileReader. The corresponding key
* set must have a purpose of either
* {@link cz.cvut.keyczar.enums.KeyPurpose#VERIFY} or
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public UnversionedVerifier(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Verifies a standard signature on the given byte array of data
*
* @param data The data to verify the signature on
* @param signature The signture to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(byte[] data, byte[] signature) throws KeyczarException {
return verify(ByteBuffer.wrap(data), ByteBuffer.wrap(signature));
}
/**
* Verifies the standard signature on the data stored in the given ByteBuffer.
* This method will try all keys until one of them verifies the signature,
* or else will return false.
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(ByteBuffer data, ByteBuffer signature)
throws KeyczarException {
VERIFIER_LOGGER.info(
Messages.getString("UnversionedVerifier.Verifying", data.remaining()));
// Try to verify the signature with each key in the set.
for (Iterator<Entry<KeyVersion, KeyczarKey>> iter =
versionMap.entrySet().iterator(); iter.hasNext(); ) {
KeyczarKey key = iter.next().getValue();
ByteBuffer dataCopy = data.duplicate();
ByteBuffer signatureCopy = signature.duplicate();
VerifyingStream stream = VERIFY_CACHE.get(key);
if (stream == null) {
stream = (VerifyingStream) key.getStream();
}
stream.initVerify();
stream.updateVerify(dataCopy);
boolean result = stream.verify(signatureCopy);
VERIFY_CACHE.put(key, stream);
if (result) {
return true;
}
}
return false;
}
/**
* Verifies the signature on the given String
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(String data, String signature) throws KeyczarException {
return verify(data.getBytes(), Base64Coder.decode(signature));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return (purpose == KeyPurpose.VERIFY ||
purpose == KeyPurpose.SIGN_AND_VERIFY);
}
}

View file

@ -0,0 +1,154 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar;
import org.apache.log4j.Logger;
import cz.cvut.keyczar.enums.KeyPurpose;
import cz.cvut.keyczar.exceptions.BadVersionException;
import cz.cvut.keyczar.exceptions.KeyNotFoundException;
import cz.cvut.keyczar.exceptions.KeyczarException;
import cz.cvut.keyczar.exceptions.ShortSignatureException;
import cz.cvut.keyczar.i18n.Messages;
import cz.cvut.keyczar.interfaces.KeyczarReader;
import cz.cvut.keyczar.interfaces.VerifyingStream;
import cz.cvut.keyczar.util.Base64Coder;
import java.nio.ByteBuffer;
/**
* Verifiers are used strictly to verify signatures. Typically, Verifiers will
* read sets of public keys, although may also be instantiated with sets of
* symmetric or private keys.
*
* {@link Signer} objects should be used with symmetric or private key sets to
* generate signatures.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Verifier extends Keyczar {
private static final Logger VERIFIER_LOGGER =
Logger.getLogger(Verifier.class);
private static final StreamCache<VerifyingStream> VERIFY_CACHE
= new StreamCache<VerifyingStream>();
/**
* Initialize a new Verifier with a KeyczarReader. The corresponding key set
* must have a purpose of either {@link cz.cvut.keyczar.enums.KeyPurpose#VERIFY} or
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}.
*
* @param reader A reader to read keys from
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Verifier(KeyczarReader reader) throws KeyczarException {
super(reader);
}
/**
* Initialize a new Verifier with a key set location. This will attempt to
* read the keys using a KeyczarFileReader. The corresponding key set
* must have a purpose of either
* {@link cz.cvut.keyczar.enums.KeyPurpose#VERIFY} or
* {@link cz.cvut.keyczar.enums.KeyPurpose#SIGN_AND_VERIFY}
*
* @param fileLocation Directory containing a key set
* @throws KeyczarException In the event of an IO error reading keys or if the
* key set does not have the appropriate purpose.
*/
public Verifier(String fileLocation) throws KeyczarException {
super(fileLocation);
}
/**
* Verifies a signature on the given byte array of data
*
* @param data The data to verify the signature on
* @param signature The signture to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(byte[] data, byte[] signature) throws KeyczarException {
return verify(ByteBuffer.wrap(data), ByteBuffer.wrap(signature));
}
/**
* Verifies the signature on the data stored in the given ByteBuffer
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(ByteBuffer data, ByteBuffer signature)
throws KeyczarException {
VERIFIER_LOGGER.info(
Messages.getString("Verifier.Verifying", data.remaining()));
if (signature.remaining() < HEADER_SIZE) {
throw new ShortSignatureException(signature.remaining());
}
byte version = signature.get();
if (version != FORMAT_VERSION) {
throw new BadVersionException(version);
}
byte[] hash = new byte[KEY_HASH_SIZE];
signature.get(hash);
KeyczarKey key = getKey(hash);
if (key == null) {
throw new KeyNotFoundException(hash);
}
VerifyingStream stream = VERIFY_CACHE.get(key);
if (stream == null) {
stream = (VerifyingStream) key.getStream();
}
stream.initVerify();
stream.updateVerify(data);
// The signed data is terminated with the current Keyczar format
stream.updateVerify(ByteBuffer.wrap(FORMAT_BYTES));
boolean result = stream.verify(signature);
VERIFY_CACHE.put(key, stream);
return result;
}
/**
* Verifies the signature on the given String
*
* @param data The data to verify the signature on
* @param signature The signature to verify
* @return Whether this is a valid signature
* @throws KeyczarException If the signature is malformed or a JCE error
* occurs.
*/
public boolean verify(String data, String signature) throws KeyczarException {
return verify(data.getBytes(), Base64Coder.decode(signature));
}
@Override
boolean isAcceptablePurpose(KeyPurpose purpose) {
return (purpose == KeyPurpose.VERIFY ||
purpose == KeyPurpose.SIGN_AND_VERIFY);
}
}

View file

@ -0,0 +1,11 @@
K 25
svn:wc:ra_dav:version-url
V 61
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/annotations
END
ForTesting.java
K 25
svn:wc:ra_dav:version-url
V 77
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/annotations/ForTesting.java
END

View file

@ -0,0 +1,62 @@
10
dir
412
http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/annotations
http://keyczar.googlecode.com/svn
2008-08-06T21:37:46.564888Z
262
arkajit.dey
8f3b247a-914b-0410-8f51-05e301831c82
ForTesting.java
file
2010-03-15T07:45:43.333854Z
f64c97d4d49ed1a0c12dc1266dc15ae5
2008-08-06T21:37:46.564888Z
262
arkajit.dey
788

View file

@ -0,0 +1,28 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.annotations;
/**
* Indicates that a class or method is for testing purposes only
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public @interface ForTesting {
}

View file

@ -0,0 +1,28 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.annotations;
/**
* Indicates that a class or method is for testing purposes only
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public @interface ForTesting {
}

View file

@ -0,0 +1,41 @@
K 25
svn:wc:ra_dav:version-url
V 55
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums
END
CipherMode.java
K 25
svn:wc:ra_dav:version-url
V 71
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums/CipherMode.java
END
KeyPurpose.java
K 25
svn:wc:ra_dav:version-url
V 71
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums/KeyPurpose.java
END
Flag.java
K 25
svn:wc:ra_dav:version-url
V 65
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums/Flag.java
END
KeyType.java
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums/KeyType.java
END
KeyStatus.java
K 25
svn:wc:ra_dav:version-url
V 70
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums/KeyStatus.java
END
Command.java
K 25
svn:wc:ra_dav:version-url
V 68
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/enums/Command.java
END

View file

@ -0,0 +1,232 @@
10
dir
412
http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/enums
http://keyczar.googlecode.com/svn
2008-09-01T08:07:53.667381Z
302
martclau
8f3b247a-914b-0410-8f51-05e301831c82
CipherMode.java
file
2010-03-15T07:45:43.321855Z
ec6fcecb93544e9a3ab4baef864f25a9
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1976
KeyPurpose.java
file
2010-03-15T07:45:43.321855Z
01b049c6e13d03745617136fc0c4a7cd
2008-07-15T21:06:18.912209Z
167
steveweis
2339
Flag.java
file
2010-03-15T07:45:43.321855Z
fb08501bfc6168f31e8f62aafb87eab2
2008-08-06T21:37:46.564888Z
262
arkajit.dey
2073
KeyType.java
file
2010-03-15T07:45:43.322854Z
c50696da1b6be3d3a83b568200af3b1e
2008-09-01T08:07:53.667381Z
302
martclau
3706
KeyStatus.java
file
2010-03-15T07:45:43.322854Z
ad8d96e6508663f3ff91919129acc9e7
2008-08-07T17:21:16.096095Z
276
steveweis
2109
Command.java
file
2010-03-15T07:45:43.322854Z
74d129a2bf94c958dd258a28fa9b5d61
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1891

View file

@ -0,0 +1,80 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.enums;
import com.google.gson.annotations.Expose;
/**
* Encodes different modes of operation:
* Cipher Block Chaining (CBC) with initial value (IV)
* Counter (CTR) with IV
* Electronic Code Book (ECB), no IV
* DET-CBC, CBC without IV
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public enum CipherMode {
CBC(0, "AES/CBC/PKCS5Padding", true),
CTR(1, "AES/CTR/NoPadding", true),
ECB(2, "AES/ECB/NoPadding", false),
DET_CBC(3, "AES/CBC/PKCS5Padding", false);
private String jceMode;
@Expose
private int value;
private CipherMode(int v, String s, boolean useIv) {
value = v;
jceMode = s;
}
public String getMode() {
return jceMode;
}
int getValue() {
return value;
}
static CipherMode getMode(int value) {
switch (value) {
case 0:
return CBC;
case 1:
return CTR;
case 2:
return ECB;
case 3:
return DET_CBC;
}
return null;
}
public int getOutputSize(int blockSize, int inputLength) {
if (this == CBC) {
return (inputLength / blockSize + 2) * blockSize;
} else if (this == ECB) {
return blockSize;
} else if (this == CTR) {
return inputLength + blockSize / 2;
} else if (this == DET_CBC) {
return (inputLength / blockSize + 1) * blockSize;
} else {
return 0;
}
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.enums;
import org.keyczar.i18n.Messages;
/**
* Commands supported by KeyczarTool.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public enum Command {
CREATE("create"),
ADDKEY("addkey"),
PUBKEY("pubkey"),
PROMOTE("promote"),
DEMOTE("demote"),
REVOKE("revoke"),
USEKEY("usekey");
private final String name;
private Command(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public static Command getCommand(String command) {
if (command == null) {
throw new NullPointerException();
}
if (command.equalsIgnoreCase(CREATE.toString())) {
return CREATE;
} else if (command.equalsIgnoreCase(ADDKEY.toString())) {
return ADDKEY;
} else if (command.equalsIgnoreCase(PUBKEY.toString())) {
return PUBKEY;
} else if (command.equalsIgnoreCase(PROMOTE.toString())) {
return PROMOTE;
} else if (command.equalsIgnoreCase(DEMOTE.toString())) {
return DEMOTE;
} else if (command.equalsIgnoreCase(REVOKE.toString())) {
return REVOKE;
} else if (command.equalsIgnoreCase(USEKEY.toString())) {
return USEKEY;
}
throw new IllegalArgumentException(
Messages.getString("Command.UnknownCommand", command));
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.enums;
import org.keyczar.i18n.Messages;
/**
* Flags supported by KeyczarTool.
*
* @author steveweis@gmail.com (Steve Weis)
*/
public enum Flag {
LOCATION("location"),
NAME("name"),
SIZE("size"),
STATUS("status"),
PURPOSE("purpose"),
DESTINATION("destination"),
VERSION("version"),
ASYMMETRIC("asymmetric"),
CRYPTER("crypter");
private final String name;
private Flag(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public static Flag getFlag(String name) {
if (name == null) {
throw new NullPointerException();
}
if (name.equalsIgnoreCase(LOCATION.toString())) {
return LOCATION;
} else if (name.equalsIgnoreCase(NAME.toString())) {
return NAME;
} else if (name.equalsIgnoreCase(SIZE.toString())) {
return SIZE;
} else if (name.equalsIgnoreCase(STATUS.toString())) {
return STATUS;
} else if (name.equalsIgnoreCase(PURPOSE.toString())) {
return PURPOSE;
} else if (name.equalsIgnoreCase(DESTINATION.toString())) {
return DESTINATION;
} else if (name.equalsIgnoreCase(VERSION.toString())) {
return VERSION;
} else if (name.equalsIgnoreCase(ASYMMETRIC.toString())) {
return ASYMMETRIC;
} else if (name.equalsIgnoreCase(CRYPTER.toString())) {
return CRYPTER;
}
throw new IllegalArgumentException(
Messages.getString("Flag.UnknownFlag", name));
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.enums;
/**
* Encodes different possible uses of a key:
* <ul>
* <li>Decrypt and Encrypt,
* <li>Encrypt Only,
* <li>Sign and Verify,
* <li>Verify Only, and
* <li>Test.
* </ul>
*
* <p>JSON Representation currently supports these strings:
* <ul>
* <li>"DECRYPT_AND_ENCRYPT"
* <li>"ENCRYPT"
* <li>"SIGN_AND_VERIFY"
* <li>"VERIFY"
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public enum KeyPurpose {
DECRYPT_AND_ENCRYPT(0, "crypt"),
ENCRYPT(1, "encrypt"),
SIGN_AND_VERIFY(2, "sign"),
VERIFY(3, "verify"),
TEST(127, "test");
private int value;
private String name;
private KeyPurpose(int v, String s) {
value = v;
name = s;
}
int getValue() {
return value;
}
String getName() {
return name;
}
public static KeyPurpose getPurpose(int value) {
switch (value) {
case 0:
return DECRYPT_AND_ENCRYPT;
case 1:
return ENCRYPT;
case 2:
return SIGN_AND_VERIFY;
case 3:
return VERIFY;
case 127:
return TEST;
}
return null;
}
public static KeyPurpose getPurpose(String name) {
if (name != null) {
if (name.equalsIgnoreCase(DECRYPT_AND_ENCRYPT.getName())) {
return DECRYPT_AND_ENCRYPT;
} else if (name.equalsIgnoreCase(ENCRYPT.getName())) {
return ENCRYPT;
} else if (name.equalsIgnoreCase(SIGN_AND_VERIFY.getName())) {
return SIGN_AND_VERIFY;
} else if (name.equalsIgnoreCase(VERIFY.getName())) {
return VERIFY;
} else if (name.equalsIgnoreCase(TEST.getName())) {
return TEST;
}
}
return null;
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.enums;
/**
* Encodes different possible statuses of keys:
* <ul>
* <li>Primary: This key can verify or decrypt existing data and can sign or
* encrypt new data.
* <li>Active: This key can only verify or decrypt existing data.
* <li>Inactive: This key can only verify or decrypt existing
* data and may be revoked at any time.
* </ul>
*
* <p>JSON Representation is one of the strings:
* <ul>
* <li>"PRIMARY"
* <li>"ACTIVE"
* <li>"INACTIVE"
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public enum KeyStatus {
PRIMARY(0, "primary"),
ACTIVE(1, "active"),
INACTIVE(2, "inactive");
private int value;
private String name;
private KeyStatus(int v, String s) {
value = v;
name = s;
}
int getValue() {
return value;
}
String getName() {
return name;
}
public static KeyStatus getStatus(int value) {
switch (value) {
case 0:
return PRIMARY;
case 1:
return ACTIVE;
case 2:
return INACTIVE;
}
return null;
}
public static KeyStatus getStatus(String name) {
if (name != null) {
if (name.equalsIgnoreCase(PRIMARY.getName())) {
return PRIMARY;
} else if (name.equalsIgnoreCase(ACTIVE.getName())) {
return ACTIVE;
} else if (name.equalsIgnoreCase(INACTIVE.getName())) {
return INACTIVE;
}
}
return ACTIVE; // default status
}
}

View file

@ -0,0 +1,142 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.enums;
import com.google.gson.annotations.Expose;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Encodes different types of keys each with (default size, output size). Some
* have multiple acceptable sizes given in a list with the first as default.
* <ul>
* <li>AES: ((128, 192, 256), 0)
* <li>HMAC-SHA1: (256, 20)
* <li>DSA Private: (1024, 48)
* <li>DSA Public: (1024, 48)
* <li>RSA Private: ((2048, 1024, 768, 512), 256)
* <li>RSA Public: ((2048, 1024, 768, 512), 256)
* <li>EC Private: ((256, 384, 521, 192), 70)
* <li>EC Public: ((256, 384, 521, 192), 70)
* <li>Test: (1, 0)
* </ul>
*
* <p>JSON Representation currently supports these strings:
* <ul>
* <li>"AES"
* <li>"HMAC_SHA1"
* <li>"DSA_PRIV"
* <li>"DSA_PUB"
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public enum KeyType {
AES("AES", 0, Arrays.asList(128, 192, 256), 0),
HMAC_SHA1("HMAC-SHA1",1, Arrays.asList(256), 20),
DSA_PRIV("DSA Private", 2, Arrays.asList(1024), 48),
DSA_PUB("DSA Public", 3, Arrays.asList(1024), 48),
RSA_PRIV("RSA Private", 4, Arrays.asList(2048, 1024, 768, 512), 256),
RSA_PUB("RSA Public", 5, Arrays.asList(2048, 1024, 768, 512), 256),
EC_PRIV("EC Private", 6, Arrays.asList(256, 384, 521, 192), 70),
EC_PUB("EC Public", 7, Arrays.asList(256, 384, 521, 192), 70),
TEST("Test", 127, Arrays.asList(1), 0);
private int outputSize;
private List<Integer> acceptableSizes;
private String name;
@Expose private int value;
/**
* Takes a list of acceptable sizes for key lengths. The first one is assumed
* to be the default size.
*
* @param v
* @param sizes
* @param outputSize
*/
private KeyType(String n, int v, List<Integer> sizes, int outputSize) {
name = n;
value = v;
this.acceptableSizes = sizes;
this.outputSize = outputSize;
}
/**
* Returns the default (recommended) key size.
*
* @return default key size in bits
*/
public int defaultSize() {
return acceptableSizes.get(0);
}
public int getOutputSize() {
return outputSize;
}
/**
* Checks whether a given key size is acceptable.
*
* @param size integer key size
* @return True if size is acceptable, False otherwise.
*/
public boolean isAcceptableSize(int size) {
return acceptableSizes.contains(size);
}
public List<Integer> getAcceptableSizes() {
return Collections.unmodifiableList(acceptableSizes);
}
int getValue() {
return value;
}
static KeyType getType(int value) {
switch (value) {
case 0:
return AES;
case 1:
return HMAC_SHA1;
case 2:
return DSA_PRIV;
case 3:
return DSA_PUB;
case 4:
return RSA_PRIV;
case 5:
return RSA_PUB;
case 6:
return EC_PRIV;
case 7:
return EC_PUB;
case 127:
return TEST;
}
return null;
}
@Override
public String toString() {
return name;
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.enums;
import com.google.gson.annotations.Expose;
/**
* Encodes different modes of operation:
* Cipher Block Chaining (CBC) with initial value (IV)
* Counter (CTR) with IV
* Electronic Code Book (ECB), no IV
* DET-CBC, CBC without IV
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public enum CipherMode {
CBC(0, "AES/CBC/PKCS5Padding", true),
CTR(1, "AES/CTR/NoPadding", true),
ECB(2, "AES/ECB/NoPadding", false),
DET_CBC(3, "AES/CBC/PKCS5Padding", false);
private String jceMode;
@Expose
private int value;
private CipherMode(int v, String s, boolean useIv) {
value = v;
jceMode = s;
}
public String getMode() {
return jceMode;
}
int getValue() {
return value;
}
static CipherMode getMode(int value) {
switch (value) {
case 0:
return CBC;
case 1:
return CTR;
case 2:
return ECB;
case 3:
return DET_CBC;
}
return null;
}
public int getOutputSize(int blockSize, int inputLength) {
if (this == CBC) {
return (inputLength / blockSize + 2) * blockSize;
} else if (this == ECB) {
return blockSize;
} else if (this == CTR) {
return inputLength + blockSize / 2;
} else if (this == DET_CBC) {
return (inputLength / blockSize + 1) * blockSize;
} else {
return 0;
}
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.enums;
import cz.cvut.keyczar.i18n.Messages;
/**
* Commands supported by KeyczarTool.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public enum Command {
CREATE("create"),
ADDKEY("addkey"),
PUBKEY("pubkey"),
PROMOTE("promote"),
DEMOTE("demote"),
REVOKE("revoke"),
USEKEY("usekey");
private final String name;
private Command(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public static Command getCommand(String command) {
if (command == null) {
throw new NullPointerException();
}
if (command.equalsIgnoreCase(CREATE.toString())) {
return CREATE;
} else if (command.equalsIgnoreCase(ADDKEY.toString())) {
return ADDKEY;
} else if (command.equalsIgnoreCase(PUBKEY.toString())) {
return PUBKEY;
} else if (command.equalsIgnoreCase(PROMOTE.toString())) {
return PROMOTE;
} else if (command.equalsIgnoreCase(DEMOTE.toString())) {
return DEMOTE;
} else if (command.equalsIgnoreCase(REVOKE.toString())) {
return REVOKE;
} else if (command.equalsIgnoreCase(USEKEY.toString())) {
return USEKEY;
}
throw new IllegalArgumentException(
Messages.getString("Command.UnknownCommand", command));
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.enums;
import cz.cvut.keyczar.i18n.Messages;
/**
* Flags supported by KeyczarTool.
*
* @author steveweis@gmail.com (Steve Weis)
*/
public enum Flag {
LOCATION("location"),
NAME("name"),
SIZE("size"),
STATUS("status"),
PURPOSE("purpose"),
DESTINATION("destination"),
VERSION("version"),
ASYMMETRIC("asymmetric"),
CRYPTER("crypter");
private final String name;
private Flag(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public static Flag getFlag(String name) {
if (name == null) {
throw new NullPointerException();
}
if (name.equalsIgnoreCase(LOCATION.toString())) {
return LOCATION;
} else if (name.equalsIgnoreCase(NAME.toString())) {
return NAME;
} else if (name.equalsIgnoreCase(SIZE.toString())) {
return SIZE;
} else if (name.equalsIgnoreCase(STATUS.toString())) {
return STATUS;
} else if (name.equalsIgnoreCase(PURPOSE.toString())) {
return PURPOSE;
} else if (name.equalsIgnoreCase(DESTINATION.toString())) {
return DESTINATION;
} else if (name.equalsIgnoreCase(VERSION.toString())) {
return VERSION;
} else if (name.equalsIgnoreCase(ASYMMETRIC.toString())) {
return ASYMMETRIC;
} else if (name.equalsIgnoreCase(CRYPTER.toString())) {
return CRYPTER;
}
throw new IllegalArgumentException(
Messages.getString("Flag.UnknownFlag", name));
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.enums;
/**
* Encodes different possible uses of a key:
* <ul>
* <li>Decrypt and Encrypt,
* <li>Encrypt Only,
* <li>Sign and Verify,
* <li>Verify Only, and
* <li>Test.
* </ul>
*
* <p>JSON Representation currently supports these strings:
* <ul>
* <li>"DECRYPT_AND_ENCRYPT"
* <li>"ENCRYPT"
* <li>"SIGN_AND_VERIFY"
* <li>"VERIFY"
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public enum KeyPurpose {
DECRYPT_AND_ENCRYPT(0, "crypt"),
ENCRYPT(1, "encrypt"),
SIGN_AND_VERIFY(2, "sign"),
VERIFY(3, "verify"),
TEST(127, "test");
private int value;
private String name;
private KeyPurpose(int v, String s) {
value = v;
name = s;
}
int getValue() {
return value;
}
String getName() {
return name;
}
public static KeyPurpose getPurpose(int value) {
switch (value) {
case 0:
return DECRYPT_AND_ENCRYPT;
case 1:
return ENCRYPT;
case 2:
return SIGN_AND_VERIFY;
case 3:
return VERIFY;
case 127:
return TEST;
}
return null;
}
public static KeyPurpose getPurpose(String name) {
if (name != null) {
if (name.equalsIgnoreCase(DECRYPT_AND_ENCRYPT.getName())) {
return DECRYPT_AND_ENCRYPT;
} else if (name.equalsIgnoreCase(ENCRYPT.getName())) {
return ENCRYPT;
} else if (name.equalsIgnoreCase(SIGN_AND_VERIFY.getName())) {
return SIGN_AND_VERIFY;
} else if (name.equalsIgnoreCase(VERIFY.getName())) {
return VERIFY;
} else if (name.equalsIgnoreCase(TEST.getName())) {
return TEST;
}
}
return null;
}
}

View file

@ -0,0 +1,85 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.enums;
/**
* Encodes different possible statuses of keys:
* <ul>
* <li>Primary: This key can verify or decrypt existing data and can sign or
* encrypt new data.
* <li>Active: This key can only verify or decrypt existing data.
* <li>Inactive: This key can only verify or decrypt existing
* data and may be revoked at any time.
* </ul>
*
* <p>JSON Representation is one of the strings:
* <ul>
* <li>"PRIMARY"
* <li>"ACTIVE"
* <li>"INACTIVE"
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public enum KeyStatus {
PRIMARY(0, "primary"),
ACTIVE(1, "active"),
INACTIVE(2, "inactive");
private int value;
private String name;
private KeyStatus(int v, String s) {
value = v;
name = s;
}
int getValue() {
return value;
}
String getName() {
return name;
}
public static KeyStatus getStatus(int value) {
switch (value) {
case 0:
return PRIMARY;
case 1:
return ACTIVE;
case 2:
return INACTIVE;
}
return null;
}
public static KeyStatus getStatus(String name) {
if (name != null) {
if (name.equalsIgnoreCase(PRIMARY.getName())) {
return PRIMARY;
} else if (name.equalsIgnoreCase(ACTIVE.getName())) {
return ACTIVE;
} else if (name.equalsIgnoreCase(INACTIVE.getName())) {
return INACTIVE;
}
}
return ACTIVE; // default status
}
}

View file

@ -0,0 +1,142 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.enums;
import com.google.gson.annotations.Expose;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Encodes different types of keys each with (default size, output size). Some
* have multiple acceptable sizes given in a list with the first as default.
* <ul>
* <li>AES: ((128, 192, 256), 0)
* <li>HMAC-SHA1: (256, 20)
* <li>DSA Private: (1024, 48)
* <li>DSA Public: (1024, 48)
* <li>RSA Private: ((2048, 1024, 768, 512), 256)
* <li>RSA Public: ((2048, 1024, 768, 512), 256)
* <li>EC Private: ((256, 384, 521, 192), 70)
* <li>EC Public: ((256, 384, 521, 192), 70)
* <li>Test: (1, 0)
* </ul>
*
* <p>JSON Representation currently supports these strings:
* <ul>
* <li>"AES"
* <li>"HMAC_SHA1"
* <li>"DSA_PRIV"
* <li>"DSA_PUB"
* </ul>
*
* @author steveweis@gmail.com (Steve Weis)
* @author arkajit.dey@gmail.com (Arkajit Dey)
*
*/
public enum KeyType {
AES("AES", 0, Arrays.asList(128, 192, 256), 0),
HMAC_SHA1("HMAC-SHA1",1, Arrays.asList(256), 20),
DSA_PRIV("DSA Private", 2, Arrays.asList(1024), 48),
DSA_PUB("DSA Public", 3, Arrays.asList(1024), 48),
RSA_PRIV("RSA Private", 4, Arrays.asList(2048, 1024, 768, 512), 256),
RSA_PUB("RSA Public", 5, Arrays.asList(2048, 1024, 768, 512), 256),
EC_PRIV("EC Private", 6, Arrays.asList(256, 384, 521, 192), 70),
EC_PUB("EC Public", 7, Arrays.asList(256, 384, 521, 192), 70),
TEST("Test", 127, Arrays.asList(1), 0);
private int outputSize;
private List<Integer> acceptableSizes;
private String name;
@Expose private int value;
/**
* Takes a list of acceptable sizes for key lengths. The first one is assumed
* to be the default size.
*
* @param v
* @param sizes
* @param outputSize
*/
private KeyType(String n, int v, List<Integer> sizes, int outputSize) {
name = n;
value = v;
this.acceptableSizes = sizes;
this.outputSize = outputSize;
}
/**
* Returns the default (recommended) key size.
*
* @return default key size in bits
*/
public int defaultSize() {
return acceptableSizes.get(0);
}
public int getOutputSize() {
return outputSize;
}
/**
* Checks whether a given key size is acceptable.
*
* @param size integer key size
* @return True if size is acceptable, False otherwise.
*/
public boolean isAcceptableSize(int size) {
return acceptableSizes.contains(size);
}
public List<Integer> getAcceptableSizes() {
return Collections.unmodifiableList(acceptableSizes);
}
int getValue() {
return value;
}
static KeyType getType(int value) {
switch (value) {
case 0:
return AES;
case 1:
return HMAC_SHA1;
case 2:
return DSA_PRIV;
case 3:
return DSA_PUB;
case 4:
return RSA_PRIV;
case 5:
return RSA_PUB;
case 6:
return EC_PRIV;
case 7:
return EC_PUB;
case 127:
return TEST;
}
return null;
}
@Override
public String toString() {
return name;
}
}

View file

@ -0,0 +1,65 @@
K 25
svn:wc:ra_dav:version-url
V 60
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions
END
ShortSignatureException.java
K 25
svn:wc:ra_dav:version-url
V 89
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/ShortSignatureException.java
END
Base64DecodingException.java
K 25
svn:wc:ra_dav:version-url
V 89
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/Base64DecodingException.java
END
KeyNotFoundException.java
K 25
svn:wc:ra_dav:version-url
V 86
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/KeyNotFoundException.java
END
KeyczarException.java
K 25
svn:wc:ra_dav:version-url
V 82
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/KeyczarException.java
END
InvalidSignatureException.java
K 25
svn:wc:ra_dav:version-url
V 91
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/InvalidSignatureException.java
END
ShortBufferException.java
K 25
svn:wc:ra_dav:version-url
V 86
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/ShortBufferException.java
END
NoPrimaryKeyException.java
K 25
svn:wc:ra_dav:version-url
V 87
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/NoPrimaryKeyException.java
END
UnsupportedTypeException.java
K 25
svn:wc:ra_dav:version-url
V 90
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/UnsupportedTypeException.java
END
BadVersionException.java
K 25
svn:wc:ra_dav:version-url
V 85
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/BadVersionException.java
END
ShortCiphertextException.java
K 25
svn:wc:ra_dav:version-url
V 90
/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/exceptions/ShortCiphertextException.java
END

View file

@ -0,0 +1,368 @@
10
dir
412
http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/exceptions
http://keyczar.googlecode.com/svn
2008-08-06T21:37:46.564888Z
262
arkajit.dey
8f3b247a-914b-0410-8f51-05e301831c82
ShortSignatureException.java
file
2010-03-15T07:45:43.699854Z
0ed05648f5bd34e6c4ead640ae86f519
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1010
Base64DecodingException.java
file
2010-03-15T07:45:43.699854Z
42444c8e183ea6eec3865677d14d7f3d
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1028
KeyNotFoundException.java
file
2010-03-15T07:45:43.699854Z
170463660f137a0cb40114e94d99da44
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1226
KeyczarException.java
file
2010-03-15T07:45:43.700854Z
9430dce1b1fc9718a4d8010d0836a758
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1099
InvalidSignatureException.java
file
2010-03-15T07:45:43.732855Z
5676bc4f7605c605bd0c0ca2a754285f
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1074
ShortBufferException.java
file
2010-03-15T07:45:43.733854Z
796ce03cc2c28c6622c225ad285fe1b3
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1086
NoPrimaryKeyException.java
file
2010-03-15T07:45:43.733854Z
6cabbdc6b09bc58a24fc41806f5f1b96
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1066
UnsupportedTypeException.java
file
2010-03-15T07:45:43.733854Z
fd8cc9eb5e5242d1cd58edbd557288f5
2008-08-06T21:37:46.564888Z
262
arkajit.dey
988
BadVersionException.java
file
2010-03-15T07:45:43.734854Z
bc79d0d20f773de8a34a0566eecdf065
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1063
ShortCiphertextException.java
file
2010-03-15T07:45:43.734854Z
b90fc50dce541ae3b2a1904c347193f3
2008-08-06T21:37:46.564888Z
262
arkajit.dey
1091

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* Keyczar output that is not properly prepended by the current Keyczar version
* is parsed.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class BadVersionException extends KeyczarException {
private static final long serialVersionUID = 7164364283899332453L;
public BadVersionException(byte badVersion) {
super(Messages.getString("BadVersionNumber", badVersion));
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
/**
* An error occurs in attempting to decode a web-safe Base64 string
* (e.g. bad characters not in the alphabet, bad padding).
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class Base64DecodingException extends KeyczarException {
public Base64DecodingException(Throwable cause) {
super(cause);
}
public Base64DecodingException(String string) {
super(string);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* The signature attached to a given ciphertext or other Keyczar output doesn't
* properly correspond to it.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class InvalidSignatureException extends KeyczarException {
private static final long serialVersionUID = -9209043556761224393L;
public InvalidSignatureException() {
super(Messages.getString("InvalidSignatureException"));
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* Key with a particular hash is not found.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class KeyNotFoundException extends KeyczarException {
private static final long serialVersionUID = -2745196315795456118L;
public KeyNotFoundException(byte[] hash) {
super(Messages.getString("KeyWithHashIdentifier",
Integer.toHexString(((hash[0] & 0xFF) << 24) | ((hash[1] & 0xFF) << 16)
| ((hash[2] & 0xFF) << 8) | ((hash[3] & 0xFF)))));
}
KeyNotFoundException(String string) {
super(string);
}
}

View file

@ -0,0 +1,40 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
/**
* Base class of all possible exceptions thrown by Keyczar.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class KeyczarException extends Exception {
private static final long serialVersionUID = 7893435087558002323L;
public KeyczarException(String message) {
super(message);
}
public KeyczarException(String message, Throwable cause) {
super(message, cause);
}
public KeyczarException(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* Primary key is missing when trying to perform an operation
* (e.g. decrypt, sign) that requires a primary key.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class NoPrimaryKeyException extends KeyNotFoundException {
private static final long serialVersionUID = 2435853068538255446L;
public NoPrimaryKeyException() {
super(Messages.getString("NoPrimaryKeyFound"));
}
}

View file

@ -0,0 +1,37 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* An input buffer is too short.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class ShortBufferException extends KeyczarException {
private static final long serialVersionUID = -3056628233532649L;
public ShortBufferException(int given, int needed) {
super(Messages.getString("InputBufferTooShort", given, needed));
}
public ShortBufferException(Throwable cause) {
super(cause);
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* Keyczar is trying to decrypt a ciphertext that is too short to be valid
* (e.g. missing appropriate header information).
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class ShortCiphertextException extends KeyczarException {
private static final long serialVersionUID = 7512790265291518499L;
public ShortCiphertextException(int len) {
super(Messages.getString("CiphertextTooShort", len));
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.i18n.Messages;
/**
* Keyczar signature is too short to be valid.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class ShortSignatureException extends KeyczarException {
private static final long serialVersionUID = 4756259412053573790L;
public ShortSignatureException(int len) {
super(Messages.getString("SignatureTooShort", len));
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keyczar.exceptions;
import org.keyczar.enums.KeyType;
import org.keyczar.i18n.Messages;
/**
* A key type was used in an inappropriate purpose.
*
* @author steveweis@gmail.com (Steve Weis)
*/
public class UnsupportedTypeException extends KeyczarException {
public UnsupportedTypeException(KeyType type) {
super(Messages.getString("InvalidTypeInInput", type));
}
}

View file

@ -0,0 +1,34 @@
/*
* Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cz.cvut.keyczar.exceptions;
import cz.cvut.keyczar.i18n.Messages;
/**
* Keyczar output that is not properly prepended by the current Keyczar version
* is parsed.
*
* @author steveweis@gmail.com (Steve Weis)
*
*/
public class BadVersionException extends KeyczarException {
private static final long serialVersionUID = 7164364283899332453L;
public BadVersionException(byte badVersion) {
super(Messages.getString("BadVersionNumber", badVersion));
}
}

Some files were not shown because too many files have changed in this diff Show more