From 2034d263bd0af64b314b97e39c89850fe30ca629 Mon Sep 17 00:00:00 2001 From: Peter Boraros Date: Sat, 5 Nov 2011 03:20:24 +0100 Subject: [PATCH] Initial import. --- README | 0 bin/createKey.sh | 15 + bin/libs.sh | 1 + bin/signMessage.sh | 4 + bin/startServer.sh | 31 + keyczar.iml | 21 + keyczar.ipr | 258 ++++ keyczar.iws | 777 ++++++++++++ pom.xml | 124 ++ src/cz/cvut/keyczar/.svn/all-wcprops | 179 +++ src/cz/cvut/keyczar/.svn/entries | 1038 +++++++++++++++++ .../.svn/text-base/AesKey.java.svn-base | 224 ++++ .../keyczar/.svn/text-base/COPYING.svn-base | 202 ++++ .../.svn/text-base/Crypter.java.svn-base | 191 +++ .../text-base/DsaPrivateKey.java.svn-base | 196 ++++ .../.svn/text-base/DsaPublicKey.java.svn-base | 150 +++ .../.svn/text-base/EcPrivateKey.java.svn-base | 183 +++ .../.svn/text-base/EcPublicKey.java.svn-base | 132 +++ .../.svn/text-base/Encrypter.java.svn-base | 192 +++ .../text-base/GenericKeyczar.java.svn-base | 296 +++++ .../.svn/text-base/HmacKey.java.svn-base | 147 +++ .../.svn/text-base/KeyMetadata.java.svn-base | 157 +++ .../.svn/text-base/KeyVersion.java.svn-base | 107 ++ .../.svn/text-base/Keyczar.java.svn-base | 153 +++ .../KeyczarEncryptedReader.java.svn-base | 52 + .../text-base/KeyczarFileReader.java.svn-base | 65 ++ .../.svn/text-base/KeyczarKey.java.svn-base | 167 +++ .../text-base/KeyczarPrivateKey.java.svn-base | 33 + .../text-base/KeyczarPublicKey.java.svn-base | 29 + .../.svn/text-base/KeyczarTool.java.svn-base | 443 +++++++ .../text-base/MockKeyczarReader.java.svn-base | 118 ++ .../text-base/RsaPrivateKey.java.svn-base | 286 +++++ .../.svn/text-base/RsaPublicKey.java.svn-base | 206 ++++ .../.svn/text-base/Signer.java.svn-base | 198 ++++ .../.svn/text-base/StreamCache.java.svn-base | 67 ++ .../text-base/TimeoutSigner.java.svn-base | 128 ++ .../text-base/TimeoutVerifier.java.svn-base | 150 +++ .../text-base/UnversionedSigner.java.svn-base | 163 +++ .../UnversionedVerifier.java.svn-base | 153 +++ .../.svn/text-base/Verifier.java.svn-base | 154 +++ src/cz/cvut/keyczar/AesKey.java | 224 ++++ src/cz/cvut/keyczar/COPYING | 202 ++++ src/cz/cvut/keyczar/Crypter.java | 191 +++ src/cz/cvut/keyczar/DsaPrivateKey.java | 195 ++++ src/cz/cvut/keyczar/DsaPublicKey.java | 150 +++ src/cz/cvut/keyczar/EcPrivateKey.java | 183 +++ src/cz/cvut/keyczar/EcPublicKey.java | 132 +++ src/cz/cvut/keyczar/Encrypter.java | 192 +++ src/cz/cvut/keyczar/GenericKeyczar.java | 296 +++++ src/cz/cvut/keyczar/HmacKey.java | 165 +++ src/cz/cvut/keyczar/KeyMetadata.java | 157 +++ src/cz/cvut/keyczar/KeyVersion.java | 107 ++ src/cz/cvut/keyczar/Keyczar.java | 153 +++ .../cvut/keyczar/KeyczarEncryptedReader.java | 52 + src/cz/cvut/keyczar/KeyczarFileReader.java | 65 ++ src/cz/cvut/keyczar/KeyczarKey.java | 167 +++ src/cz/cvut/keyczar/KeyczarPrivateKey.java | 33 + src/cz/cvut/keyczar/KeyczarPublicKey.java | 29 + src/cz/cvut/keyczar/KeyczarTool.java | 443 +++++++ src/cz/cvut/keyczar/MockKeyczarReader.java | 118 ++ src/cz/cvut/keyczar/RsaPrivateKey.java | 286 +++++ src/cz/cvut/keyczar/RsaPublicKey.java | 206 ++++ src/cz/cvut/keyczar/Signer.java | 198 ++++ src/cz/cvut/keyczar/StreamCache.java | 67 ++ src/cz/cvut/keyczar/TimeoutSigner.java | 128 ++ src/cz/cvut/keyczar/TimeoutVerifier.java | 150 +++ src/cz/cvut/keyczar/UnversionedSigner.java | 162 +++ src/cz/cvut/keyczar/UnversionedVerifier.java | 150 +++ src/cz/cvut/keyczar/Verifier.java | 154 +++ .../cvut/keyczar/annotations/.svn/all-wcprops | 11 + src/cz/cvut/keyczar/annotations/.svn/entries | 62 + .../.svn/text-base/ForTesting.java.svn-base | 28 + .../cvut/keyczar/annotations/ForTesting.java | 28 + src/cz/cvut/keyczar/enums/.svn/all-wcprops | 41 + src/cz/cvut/keyczar/enums/.svn/entries | 232 ++++ .../.svn/text-base/CipherMode.java.svn-base | 80 ++ .../.svn/text-base/Command.java.svn-base | 69 ++ .../enums/.svn/text-base/Flag.java.svn-base | 74 ++ .../.svn/text-base/KeyPurpose.java.svn-base | 96 ++ .../.svn/text-base/KeyStatus.java.svn-base | 85 ++ .../.svn/text-base/KeyType.java.svn-base | 142 +++ src/cz/cvut/keyczar/enums/CipherMode.java | 80 ++ src/cz/cvut/keyczar/enums/Command.java | 69 ++ src/cz/cvut/keyczar/enums/Flag.java | 74 ++ src/cz/cvut/keyczar/enums/KeyPurpose.java | 96 ++ src/cz/cvut/keyczar/enums/KeyStatus.java | 85 ++ src/cz/cvut/keyczar/enums/KeyType.java | 142 +++ .../cvut/keyczar/exceptions/.svn/all-wcprops | 65 ++ src/cz/cvut/keyczar/exceptions/.svn/entries | 368 ++++++ .../BadVersionException.java.svn-base | 34 + .../Base64DecodingException.java.svn-base | 34 + .../InvalidSignatureException.java.svn-base | 34 + .../KeyNotFoundException.java.svn-base | 39 + .../text-base/KeyczarException.java.svn-base | 40 + .../NoPrimaryKeyException.java.svn-base | 34 + .../ShortBufferException.java.svn-base | 37 + .../ShortCiphertextException.java.svn-base | 34 + .../ShortSignatureException.java.svn-base | 33 + .../UnsupportedTypeException.java.svn-base | 34 + .../exceptions/BadVersionException.java | 34 + .../exceptions/Base64DecodingException.java | 34 + .../exceptions/InvalidSignatureException.java | 34 + .../exceptions/KeyNotFoundException.java | 39 + .../keyczar/exceptions/KeyczarException.java | 40 + .../exceptions/NoPrimaryKeyException.java | 34 + .../exceptions/ShortBufferException.java | 37 + .../exceptions/ShortCiphertextException.java | 34 + .../exceptions/ShortSignatureException.java | 33 + .../exceptions/UnsupportedTypeException.java | 34 + .../keyczar/experimental/.svn/all-wcprops | 11 + src/cz/cvut/keyczar/experimental/.svn/entries | 62 + .../.svn/text-base/UriSigner.java.svn-base | 195 ++++ .../cvut/keyczar/experimental/UriSigner.java | 195 ++++ .../keyczar/homework/CreateSignedFile.java | 32 + .../keyczar/homework/MessageVerifier.java | 140 +++ .../keyczar/homework/VerificationServer.java | 66 ++ src/cz/cvut/keyczar/i18n/.svn/all-wcprops | 35 + src/cz/cvut/keyczar/i18n/.svn/entries | 198 ++++ .../.svn/text-base/Messages.java.svn-base | 37 + .../text-base/messages.properties.svn-base | 89 ++ .../text-base/messages_hi.properties.svn-base | 121 ++ .../text-base/messages_jp.properties.svn-base | 130 +++ .../text-base/messages_pt.properties.svn-base | 179 +++ src/cz/cvut/keyczar/i18n/Messages.java | 37 + src/cz/cvut/keyczar/i18n/messages.properties | 89 ++ .../cvut/keyczar/i18n/messages_hi.properties | 121 ++ .../cvut/keyczar/i18n/messages_jp.properties | 130 +++ .../cvut/keyczar/i18n/messages_pt.properties | 179 +++ .../cvut/keyczar/interfaces/.svn/all-wcprops | 47 + src/cz/cvut/keyczar/interfaces/.svn/entries | 266 +++++ .../text-base/DecryptingStream.java.svn-base | 85 ++ .../text-base/EncryptedReader.java.svn-base | 26 + .../text-base/EncryptingStream.java.svn-base | 86 ++ .../text-base/KeyczarReader.java.svn-base | 44 + .../text-base/SigningStream.java.svn-base | 61 + .../.svn/text-base/Stream.java.svn-base | 27 + .../text-base/VerifyingStream.java.svn-base | 59 + .../keyczar/interfaces/DecryptingStream.java | 85 ++ .../keyczar/interfaces/EncryptedReader.java | 26 + .../keyczar/interfaces/EncryptingStream.java | 86 ++ .../keyczar/interfaces/KeyczarReader.java | 44 + .../keyczar/interfaces/SigningStream.java | 61 + src/cz/cvut/keyczar/interfaces/Stream.java | 27 + .../keyczar/interfaces/VerifyingStream.java | 59 + src/cz/cvut/keyczar/jce/.svn/all-wcprops | 41 + src/cz/cvut/keyczar/jce/.svn/entries | 232 ++++ .../jce/.svn/text-base/EcCore.java.svn-base | 688 +++++++++++ .../text-base/EcKeyFactoryImpl.java.svn-base | 142 +++ .../EcKeyPairGeneratorImpl.java.svn-base | 63 + .../text-base/EcPrivateKeyImpl.java.svn-base | 92 ++ .../text-base/EcPublicKeyImpl.java.svn-base | 89 ++ .../text-base/EcSignatureImpl.java.svn-base | 225 ++++ src/cz/cvut/keyczar/jce/EcCore.java | 688 +++++++++++ src/cz/cvut/keyczar/jce/EcKeyFactoryImpl.java | 141 +++ .../keyczar/jce/EcKeyPairGeneratorImpl.java | 63 + src/cz/cvut/keyczar/jce/EcPrivateKeyImpl.java | 92 ++ src/cz/cvut/keyczar/jce/EcPublicKeyImpl.java | 89 ++ src/cz/cvut/keyczar/jce/EcSignatureImpl.java | 225 ++++ src/cz/cvut/keyczar/util/.svn/all-wcprops | 17 + src/cz/cvut/keyczar/util/.svn/entries | 96 ++ .../.svn/text-base/Base64Coder.java.svn-base | 192 +++ .../util/.svn/text-base/Util.java.svn-base | 279 +++++ src/cz/cvut/keyczar/util/Base64Coder.java | 192 +++ src/cz/cvut/keyczar/util/Util.java | 278 +++++ src/log4j.properties | 4 + 165 files changed, 21641 insertions(+) create mode 100644 README create mode 100755 bin/createKey.sh create mode 100644 bin/libs.sh create mode 100755 bin/signMessage.sh create mode 100755 bin/startServer.sh create mode 100644 keyczar.iml create mode 100644 keyczar.ipr create mode 100644 keyczar.iws create mode 100644 pom.xml create mode 100644 src/cz/cvut/keyczar/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/.svn/entries create mode 100644 src/cz/cvut/keyczar/.svn/text-base/AesKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/COPYING.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/Crypter.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/DsaPrivateKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/DsaPublicKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/EcPrivateKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/EcPublicKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/Encrypter.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/GenericKeyczar.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/HmacKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyMetadata.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyVersion.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/Keyczar.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyczarEncryptedReader.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyczarFileReader.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyczarKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyczarPrivateKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyczarPublicKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/KeyczarTool.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/MockKeyczarReader.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/RsaPrivateKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/RsaPublicKey.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/Signer.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/StreamCache.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/TimeoutSigner.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/TimeoutVerifier.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/UnversionedSigner.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/UnversionedVerifier.java.svn-base create mode 100644 src/cz/cvut/keyczar/.svn/text-base/Verifier.java.svn-base create mode 100644 src/cz/cvut/keyczar/AesKey.java create mode 100644 src/cz/cvut/keyczar/COPYING create mode 100644 src/cz/cvut/keyczar/Crypter.java create mode 100644 src/cz/cvut/keyczar/DsaPrivateKey.java create mode 100644 src/cz/cvut/keyczar/DsaPublicKey.java create mode 100644 src/cz/cvut/keyczar/EcPrivateKey.java create mode 100644 src/cz/cvut/keyczar/EcPublicKey.java create mode 100644 src/cz/cvut/keyczar/Encrypter.java create mode 100644 src/cz/cvut/keyczar/GenericKeyczar.java create mode 100644 src/cz/cvut/keyczar/HmacKey.java create mode 100644 src/cz/cvut/keyczar/KeyMetadata.java create mode 100644 src/cz/cvut/keyczar/KeyVersion.java create mode 100644 src/cz/cvut/keyczar/Keyczar.java create mode 100644 src/cz/cvut/keyczar/KeyczarEncryptedReader.java create mode 100644 src/cz/cvut/keyczar/KeyczarFileReader.java create mode 100644 src/cz/cvut/keyczar/KeyczarKey.java create mode 100644 src/cz/cvut/keyczar/KeyczarPrivateKey.java create mode 100644 src/cz/cvut/keyczar/KeyczarPublicKey.java create mode 100644 src/cz/cvut/keyczar/KeyczarTool.java create mode 100644 src/cz/cvut/keyczar/MockKeyczarReader.java create mode 100644 src/cz/cvut/keyczar/RsaPrivateKey.java create mode 100644 src/cz/cvut/keyczar/RsaPublicKey.java create mode 100644 src/cz/cvut/keyczar/Signer.java create mode 100644 src/cz/cvut/keyczar/StreamCache.java create mode 100644 src/cz/cvut/keyczar/TimeoutSigner.java create mode 100644 src/cz/cvut/keyczar/TimeoutVerifier.java create mode 100644 src/cz/cvut/keyczar/UnversionedSigner.java create mode 100644 src/cz/cvut/keyczar/UnversionedVerifier.java create mode 100644 src/cz/cvut/keyczar/Verifier.java create mode 100644 src/cz/cvut/keyczar/annotations/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/annotations/.svn/entries create mode 100644 src/cz/cvut/keyczar/annotations/.svn/text-base/ForTesting.java.svn-base create mode 100644 src/cz/cvut/keyczar/annotations/ForTesting.java create mode 100644 src/cz/cvut/keyczar/enums/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/enums/.svn/entries create mode 100644 src/cz/cvut/keyczar/enums/.svn/text-base/CipherMode.java.svn-base create mode 100644 src/cz/cvut/keyczar/enums/.svn/text-base/Command.java.svn-base create mode 100644 src/cz/cvut/keyczar/enums/.svn/text-base/Flag.java.svn-base create mode 100644 src/cz/cvut/keyczar/enums/.svn/text-base/KeyPurpose.java.svn-base create mode 100644 src/cz/cvut/keyczar/enums/.svn/text-base/KeyStatus.java.svn-base create mode 100644 src/cz/cvut/keyczar/enums/.svn/text-base/KeyType.java.svn-base create mode 100644 src/cz/cvut/keyczar/enums/CipherMode.java create mode 100644 src/cz/cvut/keyczar/enums/Command.java create mode 100644 src/cz/cvut/keyczar/enums/Flag.java create mode 100644 src/cz/cvut/keyczar/enums/KeyPurpose.java create mode 100644 src/cz/cvut/keyczar/enums/KeyStatus.java create mode 100644 src/cz/cvut/keyczar/enums/KeyType.java create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/entries create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/BadVersionException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/Base64DecodingException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/InvalidSignatureException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyNotFoundException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyczarException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/NoPrimaryKeyException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortBufferException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortCiphertextException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortSignatureException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/.svn/text-base/UnsupportedTypeException.java.svn-base create mode 100644 src/cz/cvut/keyczar/exceptions/BadVersionException.java create mode 100644 src/cz/cvut/keyczar/exceptions/Base64DecodingException.java create mode 100644 src/cz/cvut/keyczar/exceptions/InvalidSignatureException.java create mode 100644 src/cz/cvut/keyczar/exceptions/KeyNotFoundException.java create mode 100644 src/cz/cvut/keyczar/exceptions/KeyczarException.java create mode 100644 src/cz/cvut/keyczar/exceptions/NoPrimaryKeyException.java create mode 100644 src/cz/cvut/keyczar/exceptions/ShortBufferException.java create mode 100644 src/cz/cvut/keyczar/exceptions/ShortCiphertextException.java create mode 100644 src/cz/cvut/keyczar/exceptions/ShortSignatureException.java create mode 100644 src/cz/cvut/keyczar/exceptions/UnsupportedTypeException.java create mode 100644 src/cz/cvut/keyczar/experimental/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/experimental/.svn/entries create mode 100644 src/cz/cvut/keyczar/experimental/.svn/text-base/UriSigner.java.svn-base create mode 100644 src/cz/cvut/keyczar/experimental/UriSigner.java create mode 100644 src/cz/cvut/keyczar/homework/CreateSignedFile.java create mode 100644 src/cz/cvut/keyczar/homework/MessageVerifier.java create mode 100644 src/cz/cvut/keyczar/homework/VerificationServer.java create mode 100644 src/cz/cvut/keyczar/i18n/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/i18n/.svn/entries create mode 100644 src/cz/cvut/keyczar/i18n/.svn/text-base/Messages.java.svn-base create mode 100644 src/cz/cvut/keyczar/i18n/.svn/text-base/messages.properties.svn-base create mode 100644 src/cz/cvut/keyczar/i18n/.svn/text-base/messages_hi.properties.svn-base create mode 100644 src/cz/cvut/keyczar/i18n/.svn/text-base/messages_jp.properties.svn-base create mode 100644 src/cz/cvut/keyczar/i18n/.svn/text-base/messages_pt.properties.svn-base create mode 100644 src/cz/cvut/keyczar/i18n/Messages.java create mode 100644 src/cz/cvut/keyczar/i18n/messages.properties create mode 100644 src/cz/cvut/keyczar/i18n/messages_hi.properties create mode 100644 src/cz/cvut/keyczar/i18n/messages_jp.properties create mode 100644 src/cz/cvut/keyczar/i18n/messages_pt.properties create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/entries create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/DecryptingStream.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptedReader.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptingStream.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/KeyczarReader.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/SigningStream.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/Stream.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/.svn/text-base/VerifyingStream.java.svn-base create mode 100644 src/cz/cvut/keyczar/interfaces/DecryptingStream.java create mode 100644 src/cz/cvut/keyczar/interfaces/EncryptedReader.java create mode 100644 src/cz/cvut/keyczar/interfaces/EncryptingStream.java create mode 100644 src/cz/cvut/keyczar/interfaces/KeyczarReader.java create mode 100644 src/cz/cvut/keyczar/interfaces/SigningStream.java create mode 100644 src/cz/cvut/keyczar/interfaces/Stream.java create mode 100644 src/cz/cvut/keyczar/interfaces/VerifyingStream.java create mode 100644 src/cz/cvut/keyczar/jce/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/jce/.svn/entries create mode 100644 src/cz/cvut/keyczar/jce/.svn/text-base/EcCore.java.svn-base create mode 100644 src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyFactoryImpl.java.svn-base create mode 100644 src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyPairGeneratorImpl.java.svn-base create mode 100644 src/cz/cvut/keyczar/jce/.svn/text-base/EcPrivateKeyImpl.java.svn-base create mode 100644 src/cz/cvut/keyczar/jce/.svn/text-base/EcPublicKeyImpl.java.svn-base create mode 100644 src/cz/cvut/keyczar/jce/.svn/text-base/EcSignatureImpl.java.svn-base create mode 100644 src/cz/cvut/keyczar/jce/EcCore.java create mode 100644 src/cz/cvut/keyczar/jce/EcKeyFactoryImpl.java create mode 100644 src/cz/cvut/keyczar/jce/EcKeyPairGeneratorImpl.java create mode 100644 src/cz/cvut/keyczar/jce/EcPrivateKeyImpl.java create mode 100644 src/cz/cvut/keyczar/jce/EcPublicKeyImpl.java create mode 100644 src/cz/cvut/keyczar/jce/EcSignatureImpl.java create mode 100644 src/cz/cvut/keyczar/util/.svn/all-wcprops create mode 100644 src/cz/cvut/keyczar/util/.svn/entries create mode 100644 src/cz/cvut/keyczar/util/.svn/text-base/Base64Coder.java.svn-base create mode 100644 src/cz/cvut/keyczar/util/.svn/text-base/Util.java.svn-base create mode 100644 src/cz/cvut/keyczar/util/Base64Coder.java create mode 100644 src/cz/cvut/keyczar/util/Util.java create mode 100644 src/log4j.properties diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/bin/createKey.sh b/bin/createKey.sh new file mode 100755 index 0000000..6f58c15 --- /dev/null +++ b/bin/createKey.sh @@ -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 diff --git a/bin/libs.sh b/bin/libs.sh new file mode 100644 index 0000000..7d11177 --- /dev/null +++ b/bin/libs.sh @@ -0,0 +1 @@ +CP="keyczar-0.6b-jar-with-dependencies.jar" diff --git a/bin/signMessage.sh b/bin/signMessage.sh new file mode 100755 index 0000000..dc9c521 --- /dev/null +++ b/bin/signMessage.sh @@ -0,0 +1,4 @@ +#!/bin/bash +. libs.sh + +java -Dfile.encoding=UTF-8 -classpath $CP cz.cvut.keyczar.homework.CreateSignedFile $@ diff --git a/bin/startServer.sh b/bin/startServer.sh new file mode 100755 index 0000000..361821a --- /dev/null +++ b/bin/startServer.sh @@ -0,0 +1,31 @@ +#!/bin/bash +. libs.sh + +if [ $# -lt 4 ]; then + echo "Usage:" + echo "$0 " + echo " = " + echo " = " + + 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 " + echo " = " + echo " = " + exit 1 +fi + +java -Dmilis=$milis -Dnanos=$nanos -Dfile.encoding=UTF-8 -classpath $CP cz.cvut.keyczar.homework.VerificationServer $2 $3$1 $4$1 diff --git a/keyczar.iml b/keyczar.iml new file mode 100644 index 0000000..0d1eba6 --- /dev/null +++ b/keyczar.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/keyczar.ipr b/keyczar.ipr new file mode 100644 index 0000000..d62bf9b --- /dev/null +++ b/keyczar.ipr @@ -0,0 +1,258 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://www.w3.org/1999/xhtml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/keyczar.iws b/keyczar.iws new file mode 100644 index 0000000..9c7a62b --- /dev/null +++ b/keyczar.iws @@ -0,0 +1,777 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + localhost + 5050 + + + + + + + + + 1320143548148 + 1320143548148 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Android + + + + + + + + + + + + + + + 1.6 + + + + + + + + keyczar + + + + + + + + 1.6 + + + + + + + + Maven: com.google.code.gson:gson:1.4 + + + + + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4eb3961 --- /dev/null +++ b/pom.xml @@ -0,0 +1,124 @@ + + + + 4.0.0 + cz.cvut.keyczar + keyczar + Keyczar + 0.6b + jar + + true + + + ${project.artifactId}-${project.version} + src + scripts + tests + + + src + false + + **/*.properties + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.0.2 + + 1.6 + 1.6 + + + + + maven-assembly-plugin + 2.2.1 + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + + + testdata + + + + + + + true + always + warn + + + true + always + warn + + keyczar + Keyczar + http://keyczar.googlecode.com/svn/trunk/java/maven/ + default + + + + + com.google.code.gson + gson + 1.4 + + + log4j + log4j + 1.2.14 + + + org.mozilla + jss + 4 + + + junit + junit + 4.0 + + + org.testng + testng + 5.8 + jdk15 + + + diff --git a/src/cz/cvut/keyczar/.svn/all-wcprops b/src/cz/cvut/keyczar/.svn/all-wcprops new file mode 100644 index 0000000..b170263 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/all-wcprops @@ -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 diff --git a/src/cz/cvut/keyczar/.svn/entries b/src/cz/cvut/keyczar/.svn/entries new file mode 100644 index 0000000..3c0d23a --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/entries @@ -0,0 +1,1038 @@ +10 + +dir +412 +http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar +http://keyczar.googlecode.com/svn + + + +2009-01-29T23:35:25.884121Z +376 +steveweis + + + + + + + + + + + + + + +8f3b247a-914b-0410-8f51-05e301831c82 + +EcPublicKey.java +file + + + + +2010-03-15T07:45:43.963854Z +deb85cbe2c4eaa8ae3ecb368c4715c12 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +3759 + +interfaces +dir + +GenericKeyczar.java +file + + + + +2010-03-15T07:45:43.984980Z +c010097a8d01850039edcfc10d08290d +2008-08-07T17:21:16.096095Z +276 +steveweis + + + + + + + + + + + + + + + + + + + + + +10013 + +enums +dir + +KeyczarEncryptedReader.java +file + + + + +2010-03-15T07:45:43.984980Z +90ce86b16d6b2768ec95afada5398c8f +2008-10-20T19:04:00.707420Z +333 +steveweis + + + + + + + + + + + + + + + + + + + + + +1574 + +DsaPrivateKey.java +file + + + + +2010-03-15T07:45:43.985980Z +2656918e85f9c81cfadc921f23be69d8 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +5722 + +annotations +dir + +jce +dir + +HmacKey.java +file + + + + +2010-03-15T07:45:43.985980Z +153eb917d6f7ba64d918ba3e3d7bdf34 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +3764 + +TimeoutVerifier.java +file + + + + +2010-03-15T07:45:43.986985Z +25f733b3a66eea11c4847f5e7433c87e +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +5065 + +Signer.java +file + + + + +2010-03-15T07:45:43.987980Z +fb264b5fd14f9d1c95af4b683303877f +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +6551 + +COPYING +file + + + + +2010-03-15T07:45:43.987980Z +37f2420240cf848ec1a0bab042fd6b55 +2008-07-15T21:06:18.912209Z +167 +steveweis + + + + + + + + + + + + + + + + + + + + + +11358 + +RsaPrivateKey.java +file + + + + +2010-03-15T07:45:43.988980Z +a677ca462acb1fa64cdd447b4d988059 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +9025 + +KeyMetadata.java +file + + + + +2010-03-15T07:45:43.987980Z +44f119ca504a0e83cbb4a34c788a3c3b +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +4080 + +KeyczarFileReader.java +file + + + + +2010-03-15T07:45:43.989855Z +6dff85e1bd8b3cb0ce50fa9aa0518796 +2008-10-20T19:04:00.707420Z +333 +steveweis + + + + + + + + + + + + + + + + + + + + + +1921 + +EcPrivateKey.java +file + + + + +2010-03-15T07:45:43.989855Z +fd4c1b7f41ddb10c895afd9bca94f677 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +5247 + +KeyVersion.java +file + + + + +2010-03-15T07:45:43.989855Z +0c961401ae37bb70f9bf725269c811a3 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +2703 + +i18n +dir + +exceptions +dir + +MockKeyczarReader.java +file + + + + +2010-03-15T07:45:43.990855Z +111425fc1f03bb7173e9bcdf5bb297c3 +2008-08-15T01:14:57.635163Z +289 +steveweis + + + + + + + + + + + + + + + + + + + + + +3106 + +KeyczarTool.java +file + + + + +2010-03-15T07:45:43.990855Z +96c2ef1822920cb6d25815bf1fb556e9 +2008-09-01T08:06:30.031213Z +300 +martclau + + + + + + + + + + + + + + + + + + + + + +15737 + +Keyczar.java +file + + + + +2010-03-15T07:45:43.991856Z +45ff1108e7ca2459ff49cc68c598e2b5 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +4519 + +UnversionedSigner.java +file + + + + +2010-03-15T07:45:43.991856Z +b9c50b5ae8b19298933409e71ace24b4 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +5631 + +Verifier.java +file + + + + +2010-03-15T07:45:43.992855Z +0b342a6a75f420e0fdd6f908a242cf0e +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +5201 + +Encrypter.java +file + + + + +2010-03-15T07:45:43.992855Z +2020465c6c643f0eefd0f1cae6775185 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +6907 + +KeyczarPrivateKey.java +file + + + + +2010-03-15T07:45:43.993857Z +b81b292dc7f360f823d40c89867c140b +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +920 + +experimental +dir + +DsaPublicKey.java +file + + + + +2010-03-15T07:45:43.995857Z +b4e8caddb1d71fd45ceb1451b56075af +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +4446 + +StreamCache.java +file + + + + +2010-03-15T07:45:43.994857Z +6b0d96656cf0dcf2109c9d9149ea7214 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +1797 + +KeyczarPublicKey.java +file + + + + +2010-03-15T07:45:43.995857Z +81fb222ab4c11f8ab6e2730b8d924df9 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +870 + +KeyczarKey.java +file + + + + +2010-03-15T07:45:43.996856Z +78246a32fa0a4c7365e909b6d8ebe54a +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +4715 + +AesKey.java +file + + + + +2010-03-15T07:45:43.996856Z +62b06e52fc53611cc1d50d82b54516c8 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +7144 + +Crypter.java +file + + + + +2010-03-15T07:45:43.997855Z +aaeaaaea7614e92251bc5fcf6c34ad77 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +7039 + +util +dir + +RsaPublicKey.java +file + + + + +2010-03-15T07:45:43.997855Z +679861f67a52518e0a625cd5f8d3c455 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +5941 + +UnversionedVerifier.java +file + + + + +2010-03-15T07:45:43.997855Z +b15723f35627cd738dc588cb73c98765 +2008-11-19T19:08:29.376666Z +357 +steveweis + + + + + + + + + + + + + + + + + + + + + +5566 + +TimeoutSigner.java +file + + + + +2010-03-15T07:45:43.998854Z +4a8610717c26d6625b0de11baad1ec6b +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +4394 + diff --git a/src/cz/cvut/keyczar/.svn/text-base/AesKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/AesKey.java.svn-base new file mode 100644 index 0000000..349a3be --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/AesKey.java.svn-base @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/COPYING.svn-base b/src/cz/cvut/keyczar/.svn/text-base/COPYING.svn-base new file mode 100644 index 0000000..66c2d58 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/COPYING.svn-base @@ -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. diff --git a/src/cz/cvut/keyczar/.svn/text-base/Crypter.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/Crypter.java.svn-base new file mode 100644 index 0000000..7af5f1a --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/Crypter.java.svn-base @@ -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 CRYPT_CACHE + = new StreamCache(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/DsaPrivateKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/DsaPrivateKey.java.svn-base new file mode 100644 index 0000000..c96c374 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/DsaPrivateKey.java.svn-base @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/DsaPublicKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/DsaPublicKey.java.svn-base new file mode 100644 index 0000000..716a9be --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/DsaPublicKey.java.svn-base @@ -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); + } + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/EcPrivateKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/EcPrivateKey.java.svn-base new file mode 100644 index 0000000..a248ef0 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/EcPrivateKey.java.svn-base @@ -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); + } + } +} diff --git a/src/cz/cvut/keyczar/.svn/text-base/EcPublicKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/EcPublicKey.java.svn-base new file mode 100644 index 0000000..8aff3f2 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/EcPublicKey.java.svn-base @@ -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); + } + } + } +} diff --git a/src/cz/cvut/keyczar/.svn/text-base/Encrypter.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/Encrypter.java.svn-base new file mode 100644 index 0000000..79ea52b --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/Encrypter.java.svn-base @@ -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 ENCRYPT_QUEUE = + new StreamQueue(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/GenericKeyczar.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/GenericKeyczar.java.svn-base new file mode 100644 index 0000000..7c95938 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/GenericKeyczar.java.svn-base @@ -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 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); + } + } +} diff --git a/src/cz/cvut/keyczar/.svn/text-base/HmacKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/HmacKey.java.svn-base new file mode 100644 index 0000000..f4800e8 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/HmacKey.java.svn-base @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyMetadata.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyMetadata.java.svn-base new file mode 100644 index 0000000..c04ad14 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyMetadata.java.svn-base @@ -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: + *
    + *
  • a string-valued name, + *
  • a KeyPurpose, + *
  • a KeyType, and + *
  • a set of KeyVersion values. + *
+ * + *

JSON Representation consists of the following fields: + *

    + *
  • "name": a String name, + *
  • "purpose": JSON representation of KeyPurpose value, + *
  • "type": JSON representation of KeyType value, + *
  • "versions": JSON representation of an array of KeyVersion values. + *
+ * + * @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 versions = new ArrayList(); + @Expose boolean encrypted = false; + + protected Map versionMap = + new HashMap(); // 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 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; + } +} diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyVersion.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyVersion.java.svn-base new file mode 100644 index 0000000..2b2542f --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyVersion.java.svn-base @@ -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: + *
    + *
  • an integer value version number, counting from 1, + *
  • a KeyStatus, and + *
  • a boolean representing whether this key is exportable + * outside of Keyczar. + *
+ *

JSON Representation consists of the following fields: + *

    + *
  • "status": JSON representation of KeyStatus value, + *
  • "versionNumber": integer version number, + *
  • "exportable": boolean value. + *
+ * + * @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); + } +} diff --git a/src/cz/cvut/keyczar/.svn/text-base/Keyczar.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/Keyczar.java.svn-base new file mode 100644 index 0000000..ded2473 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/Keyczar.java.svn-base @@ -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 versionMap = + new HashMap(); + final HashMap hashMap = + new HashMap(); // 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); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyczarEncryptedReader.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyczarEncryptedReader.java.svn-base new file mode 100644 index 0000000..27352d1 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyczarEncryptedReader.java.svn-base @@ -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(); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyczarFileReader.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyczarFileReader.java.svn-base new file mode 100644 index 0000000..4fc0fde --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyczarFileReader.java.svn-base @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyczarKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyczarKey.java.svn-base new file mode 100644 index 0000000..310e023 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyczarKey.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyczarPrivateKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyczarPrivateKey.java.svn-base new file mode 100644 index 0000000..b61e2d8 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyczarPrivateKey.java.svn-base @@ -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(); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyczarPublicKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyczarPublicKey.java.svn-base new file mode 100644 index 0000000..7ceba6a --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyczarPublicKey.java.svn-base @@ -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 +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/KeyczarTool.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/KeyczarTool.java.svn-base new file mode 100644 index 0000000..8050b86 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/KeyczarTool.java.svn-base @@ -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: + *
    + *
  • create: create a new key store + *
  • addkey: add new key to existing store + *
  • pubkey: export a public key set from existing private key store + *
  • promote: promote status of a key version in existing store + *
  • demote: demote status of a key version in existing store + *
  • revoke: revoke key version in existing store (if scheduled to be) + *
+ * + * @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 flagMap = new HashMap(); + 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 usageParams = new ArrayList(); + 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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/MockKeyczarReader.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/MockKeyczarReader.java.svn-base new file mode 100644 index 0000000..43dfb07 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/MockKeyczarReader.java.svn-base @@ -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 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(); + publicKeys = new HashMap(); + } + + 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(); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/RsaPrivateKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/RsaPrivateKey.java.svn-base new file mode 100644 index 0000000..9606267 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/RsaPrivateKey.java.svn-base @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/RsaPublicKey.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/RsaPublicKey.java.svn-base new file mode 100644 index 0000000..982ec1e --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/RsaPublicKey.java.svn-base @@ -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); + } + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/Signer.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/Signer.java.svn-base new file mode 100644 index 0000000..7c5551b --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/Signer.java.svn-base @@ -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 SIGN_QUEUE = + new StreamQueue(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/StreamCache.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/StreamCache.java.svn-base new file mode 100644 index 0000000..e78f2d9 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/StreamCache.java.svn-base @@ -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 + */ +class StreamCache { + private final ConcurrentHashMap> cacheMap = + new ConcurrentHashMap>(); + + void put(KeyczarKey key, T s) { + getQueue(key).add(s); + } + + T get(KeyczarKey key) { + return getQueue(key).poll(); + } + + StreamQueue getQueue(KeyczarKey key) { + StreamQueue queue = cacheMap.get(key); + if (queue != null) { + return queue; + } + StreamQueue freshQueue = new StreamQueue(); + 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 + */ +class StreamQueue extends ConcurrentLinkedQueue { + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/TimeoutSigner.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/TimeoutSigner.java.svn-base new file mode 100644 index 0000000..1604c4a --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/TimeoutSigner.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/TimeoutVerifier.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/TimeoutVerifier.java.svn-base new file mode 100644 index 0000000..972bee0 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/TimeoutVerifier.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/UnversionedSigner.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/UnversionedSigner.java.svn-base new file mode 100644 index 0000000..3ed4f75 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/UnversionedSigner.java.svn-base @@ -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 SIGN_QUEUE = + new StreamQueue(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/UnversionedVerifier.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/UnversionedVerifier.java.svn-base new file mode 100644 index 0000000..8799fcc --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/UnversionedVerifier.java.svn-base @@ -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 VERIFY_CACHE + = new StreamCache(); + + /** + * 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> 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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/.svn/text-base/Verifier.java.svn-base b/src/cz/cvut/keyczar/.svn/text-base/Verifier.java.svn-base new file mode 100644 index 0000000..9d0e964 --- /dev/null +++ b/src/cz/cvut/keyczar/.svn/text-base/Verifier.java.svn-base @@ -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 VERIFY_CACHE + = new StreamCache(); + + /** + * 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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/AesKey.java b/src/cz/cvut/keyczar/AesKey.java new file mode 100644 index 0000000..58fd4fa --- /dev/null +++ b/src/cz/cvut/keyczar/AesKey.java @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/COPYING b/src/cz/cvut/keyczar/COPYING new file mode 100644 index 0000000..66c2d58 --- /dev/null +++ b/src/cz/cvut/keyczar/COPYING @@ -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. diff --git a/src/cz/cvut/keyczar/Crypter.java b/src/cz/cvut/keyczar/Crypter.java new file mode 100644 index 0000000..eb3ce06 --- /dev/null +++ b/src/cz/cvut/keyczar/Crypter.java @@ -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 CRYPT_CACHE + = new StreamCache(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/DsaPrivateKey.java b/src/cz/cvut/keyczar/DsaPrivateKey.java new file mode 100644 index 0000000..b884ec8 --- /dev/null +++ b/src/cz/cvut/keyczar/DsaPrivateKey.java @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/DsaPublicKey.java b/src/cz/cvut/keyczar/DsaPublicKey.java new file mode 100644 index 0000000..2ea5596 --- /dev/null +++ b/src/cz/cvut/keyczar/DsaPublicKey.java @@ -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); + } + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/EcPrivateKey.java b/src/cz/cvut/keyczar/EcPrivateKey.java new file mode 100644 index 0000000..2c8b2b5 --- /dev/null +++ b/src/cz/cvut/keyczar/EcPrivateKey.java @@ -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); + } + } +} diff --git a/src/cz/cvut/keyczar/EcPublicKey.java b/src/cz/cvut/keyczar/EcPublicKey.java new file mode 100644 index 0000000..68d89e3 --- /dev/null +++ b/src/cz/cvut/keyczar/EcPublicKey.java @@ -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); + } + } + } +} diff --git a/src/cz/cvut/keyczar/Encrypter.java b/src/cz/cvut/keyczar/Encrypter.java new file mode 100644 index 0000000..a51ae8e --- /dev/null +++ b/src/cz/cvut/keyczar/Encrypter.java @@ -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 ENCRYPT_QUEUE = + new StreamQueue(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/GenericKeyczar.java b/src/cz/cvut/keyczar/GenericKeyczar.java new file mode 100644 index 0000000..ebbdda2 --- /dev/null +++ b/src/cz/cvut/keyczar/GenericKeyczar.java @@ -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 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); + } + } +} diff --git a/src/cz/cvut/keyczar/HmacKey.java b/src/cz/cvut/keyczar/HmacKey.java new file mode 100644 index 0000000..978e271 --- /dev/null +++ b/src/cz/cvut/keyczar/HmacKey.java @@ -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; + } + } +} diff --git a/src/cz/cvut/keyczar/KeyMetadata.java b/src/cz/cvut/keyczar/KeyMetadata.java new file mode 100644 index 0000000..44ce303 --- /dev/null +++ b/src/cz/cvut/keyczar/KeyMetadata.java @@ -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: + *
    + *
  • a string-valued name, + *
  • a KeyPurpose, + *
  • a KeyType, and + *
  • a set of KeyVersion values. + *
+ * + *

JSON Representation consists of the following fields: + *

    + *
  • "name": a String name, + *
  • "purpose": JSON representation of KeyPurpose value, + *
  • "type": JSON representation of KeyType value, + *
  • "versions": JSON representation of an array of KeyVersion values. + *
+ * + * @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 versions = new ArrayList(); + @Expose boolean encrypted = false; + + protected Map versionMap = + new HashMap(); // 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 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; + } +} diff --git a/src/cz/cvut/keyczar/KeyVersion.java b/src/cz/cvut/keyczar/KeyVersion.java new file mode 100644 index 0000000..c360eb6 --- /dev/null +++ b/src/cz/cvut/keyczar/KeyVersion.java @@ -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: + *
    + *
  • an integer value version number, counting from 1, + *
  • a KeyStatus, and + *
  • a boolean representing whether this key is exportable + * outside of Keyczar. + *
+ *

JSON Representation consists of the following fields: + *

    + *
  • "status": JSON representation of KeyStatus value, + *
  • "versionNumber": integer version number, + *
  • "exportable": boolean value. + *
+ * + * @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); + } +} diff --git a/src/cz/cvut/keyczar/Keyczar.java b/src/cz/cvut/keyczar/Keyczar.java new file mode 100644 index 0000000..b574628 --- /dev/null +++ b/src/cz/cvut/keyczar/Keyczar.java @@ -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 versionMap = + new HashMap(); + final HashMap hashMap = + new HashMap(); // 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); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/KeyczarEncryptedReader.java b/src/cz/cvut/keyczar/KeyczarEncryptedReader.java new file mode 100644 index 0000000..870529a --- /dev/null +++ b/src/cz/cvut/keyczar/KeyczarEncryptedReader.java @@ -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(); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/KeyczarFileReader.java b/src/cz/cvut/keyczar/KeyczarFileReader.java new file mode 100644 index 0000000..67f1563 --- /dev/null +++ b/src/cz/cvut/keyczar/KeyczarFileReader.java @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/KeyczarKey.java b/src/cz/cvut/keyczar/KeyczarKey.java new file mode 100644 index 0000000..3111124 --- /dev/null +++ b/src/cz/cvut/keyczar/KeyczarKey.java @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/KeyczarPrivateKey.java b/src/cz/cvut/keyczar/KeyczarPrivateKey.java new file mode 100644 index 0000000..13bd3eb --- /dev/null +++ b/src/cz/cvut/keyczar/KeyczarPrivateKey.java @@ -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(); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/KeyczarPublicKey.java b/src/cz/cvut/keyczar/KeyczarPublicKey.java new file mode 100644 index 0000000..a0b334b --- /dev/null +++ b/src/cz/cvut/keyczar/KeyczarPublicKey.java @@ -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 +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/KeyczarTool.java b/src/cz/cvut/keyczar/KeyczarTool.java new file mode 100644 index 0000000..8e1f0ba --- /dev/null +++ b/src/cz/cvut/keyczar/KeyczarTool.java @@ -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: + *
    + *
  • create: create a new key store + *
  • addkey: add new key to existing store + *
  • pubkey: export a public key set from existing private key store + *
  • promote: promote status of a key version in existing store + *
  • demote: demote status of a key version in existing store + *
  • revoke: revoke key version in existing store (if scheduled to be) + *
+ * + * @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 flagMap = new HashMap(); + 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 usageParams = new ArrayList(); + 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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/MockKeyczarReader.java b/src/cz/cvut/keyczar/MockKeyczarReader.java new file mode 100644 index 0000000..26e87c7 --- /dev/null +++ b/src/cz/cvut/keyczar/MockKeyczarReader.java @@ -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 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(); + publicKeys = new HashMap(); + } + + 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(); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/RsaPrivateKey.java b/src/cz/cvut/keyczar/RsaPrivateKey.java new file mode 100644 index 0000000..9a3edd8 --- /dev/null +++ b/src/cz/cvut/keyczar/RsaPrivateKey.java @@ -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); + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/RsaPublicKey.java b/src/cz/cvut/keyczar/RsaPublicKey.java new file mode 100644 index 0000000..1fcac20 --- /dev/null +++ b/src/cz/cvut/keyczar/RsaPublicKey.java @@ -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); + } + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/Signer.java b/src/cz/cvut/keyczar/Signer.java new file mode 100644 index 0000000..9f8a8ba --- /dev/null +++ b/src/cz/cvut/keyczar/Signer.java @@ -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 SIGN_QUEUE = + new StreamQueue(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/StreamCache.java b/src/cz/cvut/keyczar/StreamCache.java new file mode 100644 index 0000000..8afa976 --- /dev/null +++ b/src/cz/cvut/keyczar/StreamCache.java @@ -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 + */ +class StreamCache { + private final ConcurrentHashMap> cacheMap = + new ConcurrentHashMap>(); + + void put(KeyczarKey key, T s) { + getQueue(key).add(s); + } + + T get(KeyczarKey key) { + return getQueue(key).poll(); + } + + StreamQueue getQueue(KeyczarKey key) { + StreamQueue queue = cacheMap.get(key); + if (queue != null) { + return queue; + } + StreamQueue freshQueue = new StreamQueue(); + 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 + */ +class StreamQueue extends ConcurrentLinkedQueue { + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/TimeoutSigner.java b/src/cz/cvut/keyczar/TimeoutSigner.java new file mode 100644 index 0000000..7772bc5 --- /dev/null +++ b/src/cz/cvut/keyczar/TimeoutSigner.java @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/TimeoutVerifier.java b/src/cz/cvut/keyczar/TimeoutVerifier.java new file mode 100644 index 0000000..9d8ccae --- /dev/null +++ b/src/cz/cvut/keyczar/TimeoutVerifier.java @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/UnversionedSigner.java b/src/cz/cvut/keyczar/UnversionedSigner.java new file mode 100644 index 0000000..3bd71be --- /dev/null +++ b/src/cz/cvut/keyczar/UnversionedSigner.java @@ -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 SIGN_QUEUE = + new StreamQueue(); + + /** + * 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/UnversionedVerifier.java b/src/cz/cvut/keyczar/UnversionedVerifier.java new file mode 100644 index 0000000..40db101 --- /dev/null +++ b/src/cz/cvut/keyczar/UnversionedVerifier.java @@ -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 VERIFY_CACHE + = new StreamCache(); + + /** + * 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> 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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/Verifier.java b/src/cz/cvut/keyczar/Verifier.java new file mode 100644 index 0000000..b683ac0 --- /dev/null +++ b/src/cz/cvut/keyczar/Verifier.java @@ -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 VERIFY_CACHE + = new StreamCache(); + + /** + * 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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/annotations/.svn/all-wcprops b/src/cz/cvut/keyczar/annotations/.svn/all-wcprops new file mode 100644 index 0000000..f46c35f --- /dev/null +++ b/src/cz/cvut/keyczar/annotations/.svn/all-wcprops @@ -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 diff --git a/src/cz/cvut/keyczar/annotations/.svn/entries b/src/cz/cvut/keyczar/annotations/.svn/entries new file mode 100644 index 0000000..58c7b1a --- /dev/null +++ b/src/cz/cvut/keyczar/annotations/.svn/entries @@ -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 + diff --git a/src/cz/cvut/keyczar/annotations/.svn/text-base/ForTesting.java.svn-base b/src/cz/cvut/keyczar/annotations/.svn/text-base/ForTesting.java.svn-base new file mode 100644 index 0000000..96a237c --- /dev/null +++ b/src/cz/cvut/keyczar/annotations/.svn/text-base/ForTesting.java.svn-base @@ -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 { + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/annotations/ForTesting.java b/src/cz/cvut/keyczar/annotations/ForTesting.java new file mode 100644 index 0000000..1201c8e --- /dev/null +++ b/src/cz/cvut/keyczar/annotations/ForTesting.java @@ -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 { + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/.svn/all-wcprops b/src/cz/cvut/keyczar/enums/.svn/all-wcprops new file mode 100644 index 0000000..70ae96c --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/all-wcprops @@ -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 diff --git a/src/cz/cvut/keyczar/enums/.svn/entries b/src/cz/cvut/keyczar/enums/.svn/entries new file mode 100644 index 0000000..a1f4f31 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/entries @@ -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 + diff --git a/src/cz/cvut/keyczar/enums/.svn/text-base/CipherMode.java.svn-base b/src/cz/cvut/keyczar/enums/.svn/text-base/CipherMode.java.svn-base new file mode 100644 index 0000000..ae04b24 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/text-base/CipherMode.java.svn-base @@ -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; + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/.svn/text-base/Command.java.svn-base b/src/cz/cvut/keyczar/enums/.svn/text-base/Command.java.svn-base new file mode 100644 index 0000000..cd136ac --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/text-base/Command.java.svn-base @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/.svn/text-base/Flag.java.svn-base b/src/cz/cvut/keyczar/enums/.svn/text-base/Flag.java.svn-base new file mode 100644 index 0000000..c901113 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/text-base/Flag.java.svn-base @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/.svn/text-base/KeyPurpose.java.svn-base b/src/cz/cvut/keyczar/enums/.svn/text-base/KeyPurpose.java.svn-base new file mode 100644 index 0000000..e796005 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/text-base/KeyPurpose.java.svn-base @@ -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: + *
    + *
  • Decrypt and Encrypt, + *
  • Encrypt Only, + *
  • Sign and Verify, + *
  • Verify Only, and + *
  • Test. + *
+ * + *

JSON Representation currently supports these strings: + *

    + *
  • "DECRYPT_AND_ENCRYPT" + *
  • "ENCRYPT" + *
  • "SIGN_AND_VERIFY" + *
  • "VERIFY" + *
+ * + * @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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/.svn/text-base/KeyStatus.java.svn-base b/src/cz/cvut/keyczar/enums/.svn/text-base/KeyStatus.java.svn-base new file mode 100644 index 0000000..e327361 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/text-base/KeyStatus.java.svn-base @@ -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: + *
    + *
  • Primary: This key can verify or decrypt existing data and can sign or + * encrypt new data. + *
  • Active: This key can only verify or decrypt existing data. + *
  • Inactive: This key can only verify or decrypt existing + * data and may be revoked at any time. + *
+ * + *

JSON Representation is one of the strings: + *

    + *
  • "PRIMARY" + *
  • "ACTIVE" + *
  • "INACTIVE" + *
+ * + * @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 + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/.svn/text-base/KeyType.java.svn-base b/src/cz/cvut/keyczar/enums/.svn/text-base/KeyType.java.svn-base new file mode 100644 index 0000000..73841e4 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/.svn/text-base/KeyType.java.svn-base @@ -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. + *
    + *
  • AES: ((128, 192, 256), 0) + *
  • HMAC-SHA1: (256, 20) + *
  • DSA Private: (1024, 48) + *
  • DSA Public: (1024, 48) + *
  • RSA Private: ((2048, 1024, 768, 512), 256) + *
  • RSA Public: ((2048, 1024, 768, 512), 256) + *
  • EC Private: ((256, 384, 521, 192), 70) + *
  • EC Public: ((256, 384, 521, 192), 70) + *
  • Test: (1, 0) + *
+ * + *

JSON Representation currently supports these strings: + *

    + *
  • "AES" + *
  • "HMAC_SHA1" + *
  • "DSA_PRIV" + *
  • "DSA_PUB" + *
+ * + * @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 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 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 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/CipherMode.java b/src/cz/cvut/keyczar/enums/CipherMode.java new file mode 100644 index 0000000..8ece6cd --- /dev/null +++ b/src/cz/cvut/keyczar/enums/CipherMode.java @@ -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; + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/Command.java b/src/cz/cvut/keyczar/enums/Command.java new file mode 100644 index 0000000..269c375 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/Command.java @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/Flag.java b/src/cz/cvut/keyczar/enums/Flag.java new file mode 100644 index 0000000..f566ce0 --- /dev/null +++ b/src/cz/cvut/keyczar/enums/Flag.java @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/KeyPurpose.java b/src/cz/cvut/keyczar/enums/KeyPurpose.java new file mode 100644 index 0000000..854035c --- /dev/null +++ b/src/cz/cvut/keyczar/enums/KeyPurpose.java @@ -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: + *
    + *
  • Decrypt and Encrypt, + *
  • Encrypt Only, + *
  • Sign and Verify, + *
  • Verify Only, and + *
  • Test. + *
+ * + *

JSON Representation currently supports these strings: + *

    + *
  • "DECRYPT_AND_ENCRYPT" + *
  • "ENCRYPT" + *
  • "SIGN_AND_VERIFY" + *
  • "VERIFY" + *
+ * + * @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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/KeyStatus.java b/src/cz/cvut/keyczar/enums/KeyStatus.java new file mode 100644 index 0000000..349474c --- /dev/null +++ b/src/cz/cvut/keyczar/enums/KeyStatus.java @@ -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: + *
    + *
  • Primary: This key can verify or decrypt existing data and can sign or + * encrypt new data. + *
  • Active: This key can only verify or decrypt existing data. + *
  • Inactive: This key can only verify or decrypt existing + * data and may be revoked at any time. + *
+ * + *

JSON Representation is one of the strings: + *

    + *
  • "PRIMARY" + *
  • "ACTIVE" + *
  • "INACTIVE" + *
+ * + * @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 + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/enums/KeyType.java b/src/cz/cvut/keyczar/enums/KeyType.java new file mode 100644 index 0000000..fbd3c0d --- /dev/null +++ b/src/cz/cvut/keyczar/enums/KeyType.java @@ -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. + *
    + *
  • AES: ((128, 192, 256), 0) + *
  • HMAC-SHA1: (256, 20) + *
  • DSA Private: (1024, 48) + *
  • DSA Public: (1024, 48) + *
  • RSA Private: ((2048, 1024, 768, 512), 256) + *
  • RSA Public: ((2048, 1024, 768, 512), 256) + *
  • EC Private: ((256, 384, 521, 192), 70) + *
  • EC Public: ((256, 384, 521, 192), 70) + *
  • Test: (1, 0) + *
+ * + *

JSON Representation currently supports these strings: + *

    + *
  • "AES" + *
  • "HMAC_SHA1" + *
  • "DSA_PRIV" + *
  • "DSA_PUB" + *
+ * + * @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 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 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 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; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/all-wcprops b/src/cz/cvut/keyczar/exceptions/.svn/all-wcprops new file mode 100644 index 0000000..3639ccd --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/all-wcprops @@ -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 diff --git a/src/cz/cvut/keyczar/exceptions/.svn/entries b/src/cz/cvut/keyczar/exceptions/.svn/entries new file mode 100644 index 0000000..0bc6fb5 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/entries @@ -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 + diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/BadVersionException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/BadVersionException.java.svn-base new file mode 100644 index 0000000..75efd05 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/BadVersionException.java.svn-base @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/Base64DecodingException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/Base64DecodingException.java.svn-base new file mode 100644 index 0000000..76c970c --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/Base64DecodingException.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/InvalidSignatureException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/InvalidSignatureException.java.svn-base new file mode 100644 index 0000000..132b2c3 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/InvalidSignatureException.java.svn-base @@ -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")); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyNotFoundException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyNotFoundException.java.svn-base new file mode 100644 index 0000000..02941c0 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyNotFoundException.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyczarException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyczarException.java.svn-base new file mode 100644 index 0000000..bc02617 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/KeyczarException.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/NoPrimaryKeyException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/NoPrimaryKeyException.java.svn-base new file mode 100644 index 0000000..48111f8 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/NoPrimaryKeyException.java.svn-base @@ -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")); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortBufferException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortBufferException.java.svn-base new file mode 100644 index 0000000..09786d9 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortBufferException.java.svn-base @@ -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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortCiphertextException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortCiphertextException.java.svn-base new file mode 100644 index 0000000..f720644 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortCiphertextException.java.svn-base @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortSignatureException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortSignatureException.java.svn-base new file mode 100644 index 0000000..c901191 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/ShortSignatureException.java.svn-base @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/.svn/text-base/UnsupportedTypeException.java.svn-base b/src/cz/cvut/keyczar/exceptions/.svn/text-base/UnsupportedTypeException.java.svn-base new file mode 100644 index 0000000..f2fb80a --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/.svn/text-base/UnsupportedTypeException.java.svn-base @@ -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)); + } + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/BadVersionException.java b/src/cz/cvut/keyczar/exceptions/BadVersionException.java new file mode 100644 index 0000000..38e4806 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/BadVersionException.java @@ -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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/Base64DecodingException.java b/src/cz/cvut/keyczar/exceptions/Base64DecodingException.java new file mode 100644 index 0000000..12d1b54 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/Base64DecodingException.java @@ -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; + +/** + * 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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/InvalidSignatureException.java b/src/cz/cvut/keyczar/exceptions/InvalidSignatureException.java new file mode 100644 index 0000000..12021a0 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/InvalidSignatureException.java @@ -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; + +/** + * 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")); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/KeyNotFoundException.java b/src/cz/cvut/keyczar/exceptions/KeyNotFoundException.java new file mode 100644 index 0000000..4ef95fb --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/KeyNotFoundException.java @@ -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 cz.cvut.keyczar.exceptions; + +import cz.cvut.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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/KeyczarException.java b/src/cz/cvut/keyczar/exceptions/KeyczarException.java new file mode 100644 index 0000000..48b4f78 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/KeyczarException.java @@ -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 cz.cvut.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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/NoPrimaryKeyException.java b/src/cz/cvut/keyczar/exceptions/NoPrimaryKeyException.java new file mode 100644 index 0000000..4e5de84 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/NoPrimaryKeyException.java @@ -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; + +/** + * 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")); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/ShortBufferException.java b/src/cz/cvut/keyczar/exceptions/ShortBufferException.java new file mode 100644 index 0000000..7ca8719 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/ShortBufferException.java @@ -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 cz.cvut.keyczar.exceptions; + +import cz.cvut.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); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/ShortCiphertextException.java b/src/cz/cvut/keyczar/exceptions/ShortCiphertextException.java new file mode 100644 index 0000000..7b2129b --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/ShortCiphertextException.java @@ -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 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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/ShortSignatureException.java b/src/cz/cvut/keyczar/exceptions/ShortSignatureException.java new file mode 100644 index 0000000..e12b0f4 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/ShortSignatureException.java @@ -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.exceptions; + +import cz.cvut.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)); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/exceptions/UnsupportedTypeException.java b/src/cz/cvut/keyczar/exceptions/UnsupportedTypeException.java new file mode 100644 index 0000000..b761ad8 --- /dev/null +++ b/src/cz/cvut/keyczar/exceptions/UnsupportedTypeException.java @@ -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.enums.KeyType; +import cz.cvut.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)); + } + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/experimental/.svn/all-wcprops b/src/cz/cvut/keyczar/experimental/.svn/all-wcprops new file mode 100644 index 0000000..4cac059 --- /dev/null +++ b/src/cz/cvut/keyczar/experimental/.svn/all-wcprops @@ -0,0 +1,11 @@ +K 25 +svn:wc:ra_dav:version-url +V 62 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/experimental +END +UriSigner.java +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/experimental/UriSigner.java +END diff --git a/src/cz/cvut/keyczar/experimental/.svn/entries b/src/cz/cvut/keyczar/experimental/.svn/entries new file mode 100644 index 0000000..b56c3cf --- /dev/null +++ b/src/cz/cvut/keyczar/experimental/.svn/entries @@ -0,0 +1,62 @@ +10 + +dir +412 +http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/experimental +http://keyczar.googlecode.com/svn + + + +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + +8f3b247a-914b-0410-8f51-05e301831c82 + +UriSigner.java +file + + + + +2010-03-15T07:45:43.807855Z +c27be68e63925d2d489b35fd13a02c52 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +6032 + diff --git a/src/cz/cvut/keyczar/experimental/.svn/text-base/UriSigner.java.svn-base b/src/cz/cvut/keyczar/experimental/.svn/text-base/UriSigner.java.svn-base new file mode 100644 index 0000000..3097fa1 --- /dev/null +++ b/src/cz/cvut/keyczar/experimental/.svn/text-base/UriSigner.java.svn-base @@ -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 org.keyczar.experimental; + + +import org.keyczar.Signer; +import org.keyczar.exceptions.KeyczarException; +import org.keyczar.interfaces.KeyczarReader; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.TreeSet; + +/** + * Adds a signature parameter, named sig by default, to a URI query which + * signs all the query parameters. Can use to check integrity of query + * parameters. Canonicalizes URI query parameters to be in lexicographic order. + * + * @author steveweis@gmail.com (Steve Weis) + * @author arkajit.dey@gmail.com (Arkajit Dey) + * + */ +public class UriSigner { + private static final String DEFAULT_SIG_PARAM = "sig"; + private Signer signer; + + public UriSigner(KeyczarReader reader) throws KeyczarException { + signer = new Signer(reader); + } + + public UriSigner(String fileLocation) throws KeyczarException { + signer = new Signer(fileLocation); + } + + /** + * Returns a signed URI with the signature in the default parameter 'sig'. + * Rest of the URI and query parameters are unchanged. Entire URI is signed. + * + * @param uri to be signed + * @return signed uri + * @throws KeyczarException + */ + public URI sign(URI uri) throws KeyczarException { + return sign(uri, DEFAULT_SIG_PARAM); + } + + /** + * Returns a signed URI with the signature in a parameter with the specified + * name. Rest of the URI and query parameters are unchanged. + * Entire URI is signed. + * + * @param uri to be signed + * @param sigParam String name of signature parameter + * @return signed uri with signature in given parameter + * @throws KeyczarException + */ + public URI sign(URI uri, String sigParam) throws KeyczarException { + try { + uri = canonicalUri(uri); + } catch (URISyntaxException e) { + throw new KeyczarException(e); + } + String uriString = uri.toASCIIString(); + String sig = signer.sign(uriString); + String signedQuery = sigParam + "=" + sig; + String query = uri.getQuery(); + if (query != null) { + signedQuery = query + "&" + signedQuery; + } + + try { + return new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), + signedQuery, uri.getFragment()); + } catch (URISyntaxException e) { + throw new KeyczarException(e); + } + } + + /** + * Verifies that the given URI is properly signed. Assumes signature is + * in query parameter named 'sig'. + * + * @param signedUri + * @return true if signature is valid, false otherwise + * @throws KeyczarException + */ + public boolean verify(URI signedUri) throws KeyczarException { + return verify(signedUri, DEFAULT_SIG_PARAM); + } + + /** + * Verifies that the given URI is properly signed. Takes signature from + * from the parameter name given. + * + * @param signedUri + * @param sigParam + * @return true if signature is valid, false otherwise + * @throws KeyczarException + */ + public boolean verify(URI signedUri, String sigParam) + throws KeyczarException { + if (signedUri == null) { + return false; + } + String query = signedUri.getQuery(); + if (query == null) { + return false; + } + String sig = null; + StringBuffer unsignedQuery = new StringBuffer(); + + for (String param : query.split("&")) { + if (param.startsWith(sigParam)) { + String[] nameValue = param.split("="); + if (nameValue.length == 2) { + sig = nameValue[1]; + } + } else { + unsignedQuery.append(param).append('&'); + } + } + if (sig == null) { + return false; + } + + try { + URI unsignedUri; + if (unsignedQuery.length() > 0) { + unsignedQuery.deleteCharAt(unsignedQuery.length() - 1); // extra & + unsignedUri = new URI(signedUri.getScheme(), signedUri.getAuthority(), + signedUri.getPath(), unsignedQuery.toString(), + signedUri.getFragment()); + } else { + unsignedUri = new URI(signedUri.getScheme(), signedUri.getAuthority(), + signedUri.getPath(), null, signedUri.getFragment()); + } + unsignedUri = canonicalUri(unsignedUri); // CHECK: use canonical version + return signer.verify(unsignedUri.toASCIIString(), sig); + } catch (URISyntaxException e) { + // Throw an exception? + return false; + } + } + + /** + * Return canonical version of query string with all query parameters sorted + * in lexicographic order. + * + * @param query to canonicalize + * @return canonicalized query String + */ + private String canonicalQuery(String query) { + StringBuffer canonicalQuery = new StringBuffer(); + + TreeSet params = new TreeSet(); + if (query != null) { + String[] nameValues = query.split("&"); + for (String nameValue : nameValues) { + params.add(nameValue); + } + for (String nameValue : params) { + canonicalQuery.append(nameValue).append('&'); + } + // Trim the trailing '&' + canonicalQuery.deleteCharAt(canonicalQuery.length() - 1); + } + return canonicalQuery.toString(); + } + + /** + * Canonicalizes URI by replacing query component with canonicalized query. + * + * @param uri to be canonicalized + * @return canonicalized uri + * @throws URISyntaxException if uri is invalid + */ + private URI canonicalUri(URI uri) throws URISyntaxException { + return (uri == null) ? null : new URI(uri.getScheme(), uri.getAuthority(), + uri.getPath(), canonicalQuery(uri.getQuery()), uri.getFragment()); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/experimental/UriSigner.java b/src/cz/cvut/keyczar/experimental/UriSigner.java new file mode 100644 index 0000000..2cc9a95 --- /dev/null +++ b/src/cz/cvut/keyczar/experimental/UriSigner.java @@ -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.experimental; + + +import cz.cvut.keyczar.Signer; +import cz.cvut.keyczar.exceptions.KeyczarException; +import cz.cvut.keyczar.interfaces.KeyczarReader; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.TreeSet; + +/** + * Adds a signature parameter, named sig by default, to a URI query which + * signs all the query parameters. Can use to check integrity of query + * parameters. Canonicalizes URI query parameters to be in lexicographic order. + * + * @author steveweis@gmail.com (Steve Weis) + * @author arkajit.dey@gmail.com (Arkajit Dey) + * + */ +public class UriSigner { + private static final String DEFAULT_SIG_PARAM = "sig"; + private Signer signer; + + public UriSigner(KeyczarReader reader) throws KeyczarException { + signer = new Signer(reader); + } + + public UriSigner(String fileLocation) throws KeyczarException { + signer = new Signer(fileLocation); + } + + /** + * Returns a signed URI with the signature in the default parameter 'sig'. + * Rest of the URI and query parameters are unchanged. Entire URI is signed. + * + * @param uri to be signed + * @return signed uri + * @throws KeyczarException + */ + public URI sign(URI uri) throws KeyczarException { + return sign(uri, DEFAULT_SIG_PARAM); + } + + /** + * Returns a signed URI with the signature in a parameter with the specified + * name. Rest of the URI and query parameters are unchanged. + * Entire URI is signed. + * + * @param uri to be signed + * @param sigParam String name of signature parameter + * @return signed uri with signature in given parameter + * @throws KeyczarException + */ + public URI sign(URI uri, String sigParam) throws KeyczarException { + try { + uri = canonicalUri(uri); + } catch (URISyntaxException e) { + throw new KeyczarException(e); + } + String uriString = uri.toASCIIString(); + String sig = signer.sign(uriString); + String signedQuery = sigParam + "=" + sig; + String query = uri.getQuery(); + if (query != null) { + signedQuery = query + "&" + signedQuery; + } + + try { + return new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), + signedQuery, uri.getFragment()); + } catch (URISyntaxException e) { + throw new KeyczarException(e); + } + } + + /** + * Verifies that the given URI is properly signed. Assumes signature is + * in query parameter named 'sig'. + * + * @param signedUri + * @return true if signature is valid, false otherwise + * @throws KeyczarException + */ + public boolean verify(URI signedUri) throws KeyczarException { + return verify(signedUri, DEFAULT_SIG_PARAM); + } + + /** + * Verifies that the given URI is properly signed. Takes signature from + * from the parameter name given. + * + * @param signedUri + * @param sigParam + * @return true if signature is valid, false otherwise + * @throws KeyczarException + */ + public boolean verify(URI signedUri, String sigParam) + throws KeyczarException { + if (signedUri == null) { + return false; + } + String query = signedUri.getQuery(); + if (query == null) { + return false; + } + String sig = null; + StringBuffer unsignedQuery = new StringBuffer(); + + for (String param : query.split("&")) { + if (param.startsWith(sigParam)) { + String[] nameValue = param.split("="); + if (nameValue.length == 2) { + sig = nameValue[1]; + } + } else { + unsignedQuery.append(param).append('&'); + } + } + if (sig == null) { + return false; + } + + try { + URI unsignedUri; + if (unsignedQuery.length() > 0) { + unsignedQuery.deleteCharAt(unsignedQuery.length() - 1); // extra & + unsignedUri = new URI(signedUri.getScheme(), signedUri.getAuthority(), + signedUri.getPath(), unsignedQuery.toString(), + signedUri.getFragment()); + } else { + unsignedUri = new URI(signedUri.getScheme(), signedUri.getAuthority(), + signedUri.getPath(), null, signedUri.getFragment()); + } + unsignedUri = canonicalUri(unsignedUri); // CHECK: use canonical version + return signer.verify(unsignedUri.toASCIIString(), sig); + } catch (URISyntaxException e) { + // Throw an exception? + return false; + } + } + + /** + * Return canonical version of query string with all query parameters sorted + * in lexicographic order. + * + * @param query to canonicalize + * @return canonicalized query String + */ + private String canonicalQuery(String query) { + StringBuffer canonicalQuery = new StringBuffer(); + + TreeSet params = new TreeSet(); + if (query != null) { + String[] nameValues = query.split("&"); + for (String nameValue : nameValues) { + params.add(nameValue); + } + for (String nameValue : params) { + canonicalQuery.append(nameValue).append('&'); + } + // Trim the trailing '&' + canonicalQuery.deleteCharAt(canonicalQuery.length() - 1); + } + return canonicalQuery.toString(); + } + + /** + * Canonicalizes URI by replacing query component with canonicalized query. + * + * @param uri to be canonicalized + * @return canonicalized uri + * @throws URISyntaxException if uri is invalid + */ + private URI canonicalUri(URI uri) throws URISyntaxException { + return (uri == null) ? null : new URI(uri.getScheme(), uri.getAuthority(), + uri.getPath(), canonicalQuery(uri.getQuery()), uri.getFragment()); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/homework/CreateSignedFile.java b/src/cz/cvut/keyczar/homework/CreateSignedFile.java new file mode 100644 index 0000000..8709267 --- /dev/null +++ b/src/cz/cvut/keyczar/homework/CreateSignedFile.java @@ -0,0 +1,32 @@ +package cz.cvut.keyczar.homework; + +import cz.cvut.keyczar.Signer; + +import java.io.FileOutputStream; + +public class CreateSignedFile { + + public static void main(String[] arguments) throws Throwable { + if (arguments.length<2) { + System.out.println("Usage:"); + System.out.println("caller "); + System.exit(-1); + } + String message = arguments[0]; + String keyDir = arguments[1]; + String outFile = arguments[2]; + Signer signer = new Signer(keyDir); + byte[] sig = signer.sign(message.getBytes()); + FileOutputStream fos = new FileOutputStream(outFile); + for (byte b: sig) { + System.out.print(Integer.toHexString(b&0xff)); + System.out.print(' '); + } + System.out.println(); + + fos.write(message.getBytes()); + fos.write(0); + fos.write(sig); + } + +} diff --git a/src/cz/cvut/keyczar/homework/MessageVerifier.java b/src/cz/cvut/keyczar/homework/MessageVerifier.java new file mode 100644 index 0000000..be50ec6 --- /dev/null +++ b/src/cz/cvut/keyczar/homework/MessageVerifier.java @@ -0,0 +1,140 @@ +package cz.cvut.keyczar.homework; + +import cz.cvut.keyczar.Verifier; +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.io.*; +import java.net.Socket; +import java.util.List; +import java.util.Vector; + +/** Verify incoming messages and HMACs in a loop. + * The communications protocol is as follows: + *
+ * Verifier upon start: "READY"
+ * loop:
+ *   Client to Verifier: [message bytes][null byte][25 bytes of H-MAC]
+ *   Verifier to Client: OK (when verification passes)
+ *   Verifier to Client: NOT OK (when verification fails)
+ *   Verifier to Client: ERROR: [error text] (when input is invalid)
+ * end loop
+ * Client to Verifier: (closes channel)
+ * Verifier to Client: BYE (closes channel)
+ * 
+ */ +public class MessageVerifier implements Runnable { + + private Verifier keyCzarVerifier = null; + private PrintStream outputStream; + private InputStream inputStream; + private String kudoFile; + private Socket socket; + + public MessageVerifier(Socket sock, String kudoFile, String keydir) throws KeyczarException, IOException { + this.keyCzarVerifier = new Verifier(keydir); + this.outputStream = new PrintStream(sock.getOutputStream()); + this.inputStream = sock.getInputStream(); + this.outputStream.println("READY"); + this.outputStream.flush(); + this.kudoFile = kudoFile; + this.socket = sock; + } + + /** Runs the instance + * + */ + public void run() { + verifyMessages(); + try { + socket.shutdownOutput(); + socket.shutdownInput(); + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void verifyMessages() { + while (true) { + try { + verifyOne(); + } + catch (EOF e) { + System.out.println("Disconnected."); + return; + } + catch (Throwable t) { + System.err.println("ERROR: " + t.getMessage()); + } + } + } + + private void verifyOne() throws Throwable { + byte[] message = readNullTerminatedMessage(); + byte[] hMAC = readHMAC(); + if (message.length > 100) return; + boolean result = keyCzarVerifier.verify(message, hMAC); + outputStream.println(result ? "OK" : "NOT OK"); + outputStream.flush(); + if (result) { + System.out.print("Message received: "); + System.out.write(message); + System.out.println(); + String msg = new String(message); + /*if ("halt".equalsIgnoreCase(msg) || "shutdown".equals(msg)) { + System.exit(0); + } */ + if (msg.startsWith("echo_")) { + FileOutputStream fstream = new FileOutputStream(this.kudoFile, true); + try { + PrintStream out = new PrintStream(fstream); + out.println(msg.substring(5)); + out.flush(); + } finally { + fstream.close(); + } + } + } + } + + private byte[] readNullTerminatedMessage() throws Throwable { + List message = new Vector(); + while (true) { + byte b = byteFromInput(); + if (b == 0) { + break; // don't append the null byte + } + message.add(b); + } + return listToByteArray(message); + } + + private byte[] readHMAC() throws Throwable { + byte[] hMAC = new byte[25]; + for (int i = 0; i < 25; i++) { + byte b = byteFromInput(); + hMAC[i] = b; + } + return hMAC; + } + + private static byte[] listToByteArray(List list) { + byte[] array = new byte[list.size()]; + for (int i = 0; i < array.length; i++) { + array[i] = list.get(i); + } + return array; + } + + private byte byteFromInput() throws Throwable { + int i = inputStream.read(); + if (i < 0) { + throw new EOF(); + } + return (byte) i; + } + + public class EOF extends RuntimeException { + } + +} diff --git a/src/cz/cvut/keyczar/homework/VerificationServer.java b/src/cz/cvut/keyczar/homework/VerificationServer.java new file mode 100644 index 0000000..11cf409 --- /dev/null +++ b/src/cz/cvut/keyczar/homework/VerificationServer.java @@ -0,0 +1,66 @@ +package cz.cvut.keyczar.homework; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +public class VerificationServer { + + public static void main(String[] arguments) throws IOException, KeyczarException { + + if (arguments.length<2) { + System.err.println("Usage:"); + System.err.println("\tVerificationServer "); + System.exit(-1); + } + + int socketPort = Integer.parseInt(arguments[0]); + String kudoFile = arguments[1]; + String keyDir = arguments[2]; + + ServerSocket serverSocket; + try { + serverSocket = new ServerSocket(socketPort); + System.out.println("Listen on: "+String.valueOf(socketPort)); + Thread t = new Thread(new ConnectionAcceptor(serverSocket, kudoFile, keyDir)); + t.setDaemon(true); + t.start(); + t.join(); + } catch (IOException e) { + System.err.println("Could not listen on ports: " + String.valueOf(socketPort) ); + System.exit(-1); + } catch (InterruptedException e) { } + } + static class ConnectionAcceptor implements Runnable { + private ServerSocket socket; + private String kudoFile; + private String keyDir; + + public ConnectionAcceptor(ServerSocket socket, String kudoFile, String keyDir) { + this.socket = socket; + this.kudoFile = kudoFile; + this.keyDir = keyDir; + } + @Override + public void run() { + while (true) { + try { + Socket clientSocket = this.socket.accept(); + System.out.println("Connect from: "+clientSocket.toString()); + Thread t = new Thread(new MessageVerifier(clientSocket, kudoFile, keyDir)); + t.setDaemon(true); + t.start(); + } catch (IOException e) { + System.err.println("Accept failed: "+String.valueOf(this.socket.getLocalPort())); + System.exit(-1); + } catch (KeyczarException e) { + System.err.println("Accept failed: "+String.valueOf(this.socket.getLocalPort())); + System.exit(-1); + } + } + } + } + +} diff --git a/src/cz/cvut/keyczar/i18n/.svn/all-wcprops b/src/cz/cvut/keyczar/i18n/.svn/all-wcprops new file mode 100644 index 0000000..ae889b5 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/all-wcprops @@ -0,0 +1,35 @@ +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/i18n +END +messages_hi.properties +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/i18n/messages_hi.properties +END +messages.properties +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/i18n/messages.properties +END +messages_pt.properties +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/i18n/messages_pt.properties +END +Messages.java +K 25 +svn:wc:ra_dav:version-url +V 68 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/i18n/Messages.java +END +messages_jp.properties +K 25 +svn:wc:ra_dav:version-url +V 77 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/i18n/messages_jp.properties +END diff --git a/src/cz/cvut/keyczar/i18n/.svn/entries b/src/cz/cvut/keyczar/i18n/.svn/entries new file mode 100644 index 0000000..3339cd2 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/entries @@ -0,0 +1,198 @@ +10 + +dir +412 +http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/i18n +http://keyczar.googlecode.com/svn + + + +2008-09-01T08:09:03.007010Z +303 +martclau + + + + + + + + + + + + + + +8f3b247a-914b-0410-8f51-05e301831c82 + +messages_hi.properties +file + + + + +2010-03-15T07:45:43.540981Z +9ed94da406efd0e550764a2b79d8c288 +2008-08-04T22:26:54.317104Z +246 +steveweis + + + + + + + + + + + + + + + + + + + + + +23774 + +messages.properties +file + + + + +2010-03-15T07:45:43.541982Z +cc2cffd4f9ddeac177230e2afac18d62 +2008-09-01T08:09:03.007010Z +303 +martclau + + + + + + + + + + + + + + + + + + + + + +4367 + +messages_pt.properties +file + + + + +2010-03-15T07:45:43.541982Z +2fae4726fcdedb2aa255099c34ee54b7 +2008-08-07T16:52:30.801678Z +273 +steveweis + + + + + + + + + + + + + + + + + + + + + +9873 + +Messages.java +file + + + + +2010-03-15T07:45:43.542981Z +8e037e674cad5fbef1e5b38cccc7e3f3 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +892 + +messages_jp.properties +file + + + + +2010-03-15T07:45:43.542981Z +ae9acabe757ecea54ad7b188c4a2d789 +2008-08-07T17:52:03.265521Z +279 +steveweis + + + + + + + + + + + + + + + + + + + + + +24799 + diff --git a/src/cz/cvut/keyczar/i18n/.svn/text-base/Messages.java.svn-base b/src/cz/cvut/keyczar/i18n/.svn/text-base/Messages.java.svn-base new file mode 100644 index 0000000..ee6d857 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/text-base/Messages.java.svn-base @@ -0,0 +1,37 @@ +package org.keyczar.i18n; + +import org.keyczar.annotations.ForTesting; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * TODO(steveweis): javadoc this + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public class Messages { + private static final String BUNDLE_NAME = "org.keyczar.i18n.messages"; + + private static ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + @ForTesting + public static void changeLocale(Locale locale) { + RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME, locale); + } + + public static String getString(String key, Object... params) { + try { + return MessageFormat.format(RESOURCE_BUNDLE.getString(key), params); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/i18n/.svn/text-base/messages.properties.svn-base b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages.properties.svn-base new file mode 100644 index 0000000..4d4a9f9 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages.properties.svn-base @@ -0,0 +1,89 @@ +CiphertextTooShort=Input of length {0} is too short to be valid ciphertext +InputBufferTooShort=Input buffer is too short. Given: {0} bytes. Need: {1} +BadVersionNumber=Received a bad version number: {0} +SignatureTooShort=Input of length {0} is too short to be valid signature +NoPrimaryKeyFound=No primary key found +InvalidSignatureException=Invalid ciphertext signature. +KeyWithHashIdentifier=Key with hash identifier {0} not found +Signer.Signing=Signing {0} bytes +InvalidTypeInInput=Invalid type in input: {0} +Verifier.Verifying=Verifying {0} bytes +Base64Coder.IllegalLength=Input source is of illegal length: {0} +Base64Coder.IllegalCharacter=Illegal character in Base64 string: {0} +Encrypter.Encrypting=Encrypting {0} bytes. +Crypter.Decrypting=Decrypting {0} bytes. +KeyczarFileReader.FileError=Error reading file: {0} +KeyczarKey.PublicKeyExport=Public keys of type {0} must be exported from \ +private keys. +Keyczar.UnacceptablePurpose=Unacceptable purpose: {0} +Keyczar.NeedEncryptedReader=Must use an EncryptedReader to read encrypted \ +key sets. +Keyczar.SinglePrimary=Key sets may only have a single primary version +Keyczar.ReadVersion=Read version: {0} +Keyczar.SizeWarning=WARNING: {0}-bit key size is less than the recommended \ +default key size of {1} bits for {2} keys. +Keyczar.NewVersion=Created new version: {0} +Keyczar.PromotedVersion=Promoting version: {0} +Keyczar.CantPromotePrimary=Can't promote a primary key. +Keyczar.DemotingVersion=Demoting version: {0} +Keyczar.CantDemoteScheduled=Can't demote an inactive key. +Keyczar.CantRevoke=Can't revoke key unless inactive. +Keyczar.NoSuchVersion=No such version number: {0} + +KeyczarTool.NeedLocation=Must define a key set location with the --{0} flag +KeyczarTool.MustDefinePublic=Must define a public key location +KeyczarTool.UnsupportedPurpose=Unsupported purpose: {0} +KeyczarTool.MustDefinePurpose=Must specify a purpose +KeyczarTool.MustDefineLocation=Must specify a key set location +KeyczarTool.CannotExportPubKey=Cannot export public keys for {0} key type and \ +{1} purpose. +KeyczarTool.FileExists=File {0} already exists +KeyczarTool.MissingVersion=Must specify a key version +KeyczarTool.UnableToDelete=Unable to delete revoked key file +KeyczarTool.UnableToWrite=Unable to write to: {0} +KeyczarTool.MustDefineDestination=Must define a key set destination + +Flag.UnknownFlag=Unknown flag: {0} +Command.UnknownCommand=Unknown command: {0} + + +KeyczarTool.Usage=Usage: \"KeyczarTool command flags\"\n\ +Commands: {0} {1} {2} {3} {4} {5}\n\ +Flags: {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +Command Usage:\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"A name\"] [--{14}=(dsa|rsa|ec)]\n\ +\tCreates a new, empty key set in the given location.\n\ +\tThis key set must have a purpose of either "crypt" or "sign"\n\ +\tand may optionally be given a name. The optional {14} \n\ +\tflag will generate a public key set of the given algorithm.\n\ +\tThe "dsa" and "ec" asymmetric values are valid only for sets\n\ +\twith "sign" purpose.\n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\tAdds a new key to an existing key set. Optionally\n\ +\tspecify a status, which is active by default. Optionally\n\ +\tspecify a key size in bits. Also optionally specify the\n\ +\tlocation of a set of crypting keys, which will be used to\n\ +\tencrypt this key set.\n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\tExtracts public keys from a given key set and writes them\n\ +\tto the destination. The "{2}" command Only works for\n\ +\tkey sets that were created with the "--asymmetric" flag.\n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tPromotes the status of the given key version in the given \n\ +\tlocation. Active keys are promoted to primary (which demotes \n\ +\tany existing primary key to active). Inactive keys are \n\ +\tpromoted to be active.\n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tDemotes the status of the given key version in the given\n\ +\tlocation. Primary keys are demoted to active. Active keys\n\ +\tare made inactive.\n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tRevokes the key of the given version number.\n\ +\tThis key must have been demoted to inactive to be revoked.\n\ +\tWARNING: The key will be destroyed.\n\n\ +Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c"\n\ +are the valid choices + + diff --git a/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_hi.properties.svn-base b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_hi.properties.svn-base new file mode 100644 index 0000000..5214b70 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_hi.properties.svn-base @@ -0,0 +1,121 @@ +CiphertextTooShort={0} \u0932\u0902\u092c\u093e\u0908 \u0915\u0940 \u2018\u0907\u0928\u092a\u0941\u091f\u2019 \u092c\u0939\u0941\u0924 \u091b\u094b\u091f\u0940 \u0939\u0948, \u090f\u0915 \u0938\u0939\u0940 \u2018\u0938\u093e\u092f\u092b\u0930 \u091f\u0947\u0915\u094d\u0938\u091f\u2019 \u0939\u094b\u0928\u0947 \u0915\u0947 \u0932\u093f\u092f\u0947 +InputBufferTooShort= \u2018\u0907\u0928\u092a\u0941\u091f \u092c\u092b\u094d\u092b\u0930\u2019 \u092c\u0939\u0941\u0924 \u091b\u094b\u091f\u0940 \u0939\u0948, \u0926\u093f\u092f\u093e \u0917\u092f\u093e \u0939\u0948: {0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019\u0964 \u091c\u0930\u0942\u0930\u0924 \u0939\u0948: {1} +BadVersionNumber=\u0939\u092e\u093e\u0930\u0947 \u092a\u093e\u0938 \u0906\u092f\u093e \u090f\u0915 \u092c\u0941\u0930\u093e \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u093e \u0928\u0902\u092c\u0930: {0} +SignatureTooShort= {0} \u0932\u0902\u092c\u093e\u0908 \u0915\u0940 \u2018\u0907\u0928\u092a\u0941\u091f\u2019 \u092c\u0939\u0941\u0924 \u091b\u094b\u091f\u0940 \u0939\u0948, \u090f\u0915 \u0938\u0939\u0940 \u2018\u0938\u093f\u0917\u0928\u0947\u091a\u0930\u2019 \u0939\u094b\u0928\u0947 \u0915\u0947 \u0932\u093f\u092f\u0947 NoPrimaryKeyFound=\u0915\u094b\u0908 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0928\u0939\u0940 \u092e\u093f\u0932\u0940 +InvalidSignatureException=\u092f\u0947 \u2018\u0938\u093e\u092f\u092b\u0930 \u091f\u0947\u0915\u094d\u0938\u091f \u0938\u093f\u0917\u0928\u0947\u091a\u0930\u2019 \u0938\u0939\u0940 \u0928\u0939\u0940 \u0939\u0948 +KeyWithHashIdentifier= \u2018\u0915\u0940\u2019 \u092e\u093f\u0932\u0940 \u0928\u0939\u0940 \u091c\u093f\u0938 \u0915\u093e \u2018\u0939\u093e\u0937 \u0906\u0907\u0919\u0947\u0902\u091f\u093f\u092b\u093e\u092f\u0930\u2019 {0} \u0939\u0948 +Signer.Signing= \u2018\u0938\u093e\u0908\u0928\u093f\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 {0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 +InvalidTypeInInput= \u2018\u0907\u0928\u092a\u0941\u091f\u2019 \u0915\u093e \u2018\u091f\u093e\u0908\u092a\u2019 \u0917\u0932\u0924 \u0939\u0948: {0} +Verifier.Verifying= {0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 \u2018\u0935\u0947\u0930\u093f\u092b\u093e\u0908\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 +Base64Coder.IllegalLength= \u2018\u0907\u0928\u092a\u0941\u091f \u0938\u094b\u0930\u0938\u2019 \u0915\u0940 \u0932\u0902\u092c\u093e\u0908 \u0917\u0932\u0924 \u0939\u0948: {0} +Base64Coder.IllegalCharacter= \u0917\u0932\u0924 \u2018\u0915\u093e\u0930\u0948\u0915\u091f\u0930\u2019 \u0939\u0948 \u2018\u092c\u0947\u0938\u096c\u096a \u0938\u094d\u091f\u094d\u0930\u093f\u0902\u0917\u2019 \u092e\u0947\u0902: {0} +Encrypter.Encrypting={0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 +Crypter.Decrypting={0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 \u2018\u0921\u0940\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 +KeyczarFileReader.FileError= \u2018\u092b\u093e\u0908\u0932\u2019 \u092a\u0922\u0928\u0947 \u092e\u0947 \u0917\u0932\u0924\u0940 \u0939\u0941\u0908: {0} +KeyczarKey.PublicKeyExport= \u2018\u091f\u093e\u0908\u092a\u2019 {0} \u0915\u0940 \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c\u2019 \u0915\u094b \u2018\u092a\u0930\u093e\u0908\u0935\u0947\u091f \u0915\u0940\u091c\u093c\u2019 \u0938\u0947 \u2018\u090f\u0915\u094d\u0938\u092a\u094b\u0930\u091f\u2019 \u0915\u0930\u0928\u093e \u092a\u0921\u0947\u0917\u093e +Keyczar.UnacceptablePurpose=\u092f\u0947 \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u0928\u093e\u091c\u093e\u0907\u091c\u093c \u0939\u0948: {0} +Keyczar.NeedEncryptedReader= \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0921\u093c \u0930\u0940\u0921\u093c\u0930\u2019 \u0907\u0938\u0924\u093f\u092e\u093e\u0932 \u0915\u0930\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0921\u093c \u0915\u0940 \u0938\u0947\u091f\u094d\u0938\u2019 \u092a\u0922\u0928\u0947 \u0915\u0947 \u0932\u093f\u092f\u0947 +Keyczar.SinglePrimary= \u2018\u0915\u0940 \u0938\u0947\u091f\u094d\u0938\u2019 \u092e\u0947\u0902 \u0938\u093f\u0930\u092b \u0910\u0915 \u2018\u092a\u0930\u093e\u0908\u0902\u092e\u0930\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0939\u094b \u0938\u0915\u0924\u093e \u0939\u0948 +Keyczar.ReadVersion=\u2018\u0930\u0940\u0921 \u0935\u0930\u0937\u093f\u0928\u2019: {0} +Keyczar.SizeWarning=\u0938\u093e\u0935\u0927\u093e\u0928: {0}- \u2018\u092c\u093f\u091f \u0915\u0940\u2019 \u0915\u0940 \u0932\u0902\u092c\u093e\u0908 \u0915\u092e \u0939\u0948 \u0935\u094b \u092e\u0941\u0928\u093e\u0938\u093f\u092c \u0932\u0902\u092c\u093e\u0908 \u0938\u0947 \u091c\u094b \u0939\u0948 \u2018\u0921\u0940\u092b\u093e\u0932\u094d\u091f\u2019 {1} \u2018\u092c\u093f\u091f\u094d\u0938\u2019 {2} \u2018\u0915\u0940\u091c\u093c\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 +Keyczar.Version= \u0928\u092f\u093e \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u092c\u0928\u093e\u092f\u093e \u0917\u092f\u093e: {0} +Keyczar.PromotedVersion={0}: \u2018\u0935\u0930\u0937\u093f\u0928 \u092a\u094d\u0930\u094b\u092e\u094b\u091f\u2019 +Keyczar.CantPromotePrimary= \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0915\u094b \u2018\u092a\u094d\u0930\u094b\u092e\u094b\u091f\u2019 \u0915\u0930 \u0928\u0939\u0940 \u0938\u0915\u0924\u093e +Keyczar.DemotingVersion={0}: \u2018\u0935\u0930\u0937\u093f\u0928 \u0921\u0940\u092e\u094b\u091f\u2019 \u0939\u094b \u0930\u0939\u093e \u0939\u0948 +Keyczar.CantDemoteScheduled= \u0935\u094b \u2018\u0915\u0940 \u0921\u0940\u092e\u094b\u091f\u2019 \u0915\u0930 \u0928\u0939\u0940 \u0938\u0915\u0924\u0947 \u091c\u093f\u0938\u0915\u0940 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0939\u094b\u0928\u0947 \u0935\u093e\u0932\u0940 \u0939\u0948 +Keyczar.CantRevoke=\u092f\u0947 \u2018\u0915\u0940 \u0930\u093f\u0935\u094b\u0915\u2019 \u0928\u0939\u0940 \u0915\u0930 \u0938\u0915\u0924\u0947 \u091c\u094b \u092a\u0939\u0932\u0947 \u0938\u0947 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0928\u0939\u0940 \u0915\u0940 \u0917\u092f\u0940 +Keyczar.NoSuchVersion=\u0910\u0938\u093e \u0915\u094b\u0908 \u2018\u0935\u0930\u0937\u093f\u0928 \u0928\u0902\u092c\u0930\u2019 \u0928\u0939\u0940 \u0939\u0948: {0} + +KeyczarTool.NeedLocation= \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0930\u0916\u0928\u0947 \u0915\u0940 \u091c\u0917\u0939 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 --{0} \u2018\u092b\u094d\u0932\u093e\u0917\u2019 +KeyczarTool.MustDefinePublic= \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u2019 \u0930\u0916\u0928\u0947 \u0915\u0940 \u091c\u0917\u0939 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.UnsupportedPurpose=\u092f\u0947 \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u091a\u0932 \u0928\u0939\u0940 \u0938\u0915\u0924\u093e: {0} +KeyczarTool.MustDefinePurpose=\u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.MustDefineLocation=\u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u0940 \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.CannotExportPubKey=\u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c \u090f\u0915\u094d\u0938\u092a\u094b\u0930\u091f\u2019 \u0915\u0930 \u0928\u0939\u0940 \u0938\u0915\u0924\u0947,{0} \u2018\u0915\u0940 \u091f\u093e\u0908\u092a\u2019 \u0914\u0930 {1} \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 +KeyczarTool.FileExists= \u2018\u092b\u093e\u0908\u0932\u2019 {0} \u092a\u0939\u0932\u0947 \u0938\u0947 \u092e\u094c\u091c\u0942\u0926 \u0939\u0948 +KeyczarTool.MissingVersion=\u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.UnableToDelete= \u2018\u0930\u093f\u0935\u094b\u0915\u0921\u093c \u0915\u0940 \u092b\u093e\u0908\u0932\u2019 \u092e\u093f\u091f \u0928\u0939\u0940 \u0938\u0915\u0940 +KeyczarTool.UnableToWrite=\u0932\u093f\u0916 \u0928\u0939\u0940 \u0938\u0915\u093e: {0} +KeyczarTool.MustDefineDestination= \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u0921\u0947\u0938\u091f\u093f\u0928\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 + +Flag.UnknownFlag=\u092f\u0947 \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u0915\u0940 \u092a\u0939\u091a\u093e\u0928 \u0928\u0939\u0940 \u0939\u0948: {0} +Command.UnknownCommand= \u2018\u0915\u092e\u093e\u0902\u0921\u2019 \u0915\u0940 \u092a\u0939\u091a\u093e\u0928 \u0928\u0939\u0940 \u0939\u0948: {0} + +# \u092f\u0947 \u0905\u0928\u0947\u0915 \u2018\u0932\u093e\u0908\u0928\u2019 \u0915\u093e \u2018\u092f\u0942\u0938\u0947\u091c \u092e\u0948\u0938\u0947\u091c\u093c\u2019 \u0939\u0948 +# \u091c\u092c \u2018\u0906\u0930\u0917\u094d\u092f\u0941\u092e\u0948\u0902\u091f\u0938\u2019 \u0926\u093f\u092f\u0947 \u091c\u093e\u0924\u0947 \u0939\u0948 \u0924\u092c \u2018\u0906\u090a\u091f\u092a\u0941\u091f\u2019 \u0910\u0938\u0947 \u0928\u091c\u0930 \u0906\u0924\u0947 \u0939\u0948 +# Usage: "KeyczarTool command flags" +#Commands: create addkey pubkey promote demote revoke +#Flags: location name size status purpose destination version asymmetric crypter +#Command Usage: +#create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)] +# \u0910\u0915 \u0928\u092f\u0940 \u0916\u093e\u0932\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u0913 \u0907\u0938 \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092a\u0930\u0964 +# \u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u092a\u0930\u092a\u091c\u093c\u2019 "crypt" \u092f\u093e \u0924\u094b "sign" \u0939\u094b\u0928\u093e \u091a\u093e\u0939\u093f\u090f \u0914\u0930 \u090f\u0915 \u0928\u093e\u092e \u092d\u0940 +# \u0926\u093f\u092f\u093e \u091c\u093e \u0938\u0915\u0924\u093e \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u0905\u0938\u093f\u092e\u094d\u092e\u0948\u091f\u0930\u093f\u0915 \u092b\u094d\u0932\u093e\u0917\u2019 \u092d\u0940 \u0926\u0947 \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b \u0910\u0915 \u2018\u092a\u092c\u0932\u093f\u0915 +# \u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u090f\u0917\u093e \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0905\u0932\u0917\u094b\u0930\u093f\u0924\u094d\u092e\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 +# "dsa" \u2018\u0905\u0938\u093f\u092e\u094d\u092e\u0948\u091f\u0930\u093f\u0915 \u0935\u093e\u0932\u092f\u0941\u2019 \u0938\u0939\u0940 \u0939\u0948 \u092c\u0938 \u0935\u094b \u2018\u0938\u0947\u091f\u094d\u0938\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 \u091c\u093f\u0928\u0915\u093e +# \u2018\u092a\u0930\u092a\u091c\u093c\u2019 "sign" \u0939\u094b\u0964 +#addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation] +# \u092a\u0941\u0930\u093e\u0928\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092e\u0947 \u090f\u0915 \u0928\u092f\u0940 \u2018\u0915\u0940\u2019 \u0926\u093e\u0932\u0940 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b +# \u091c\u093f\u0938\u0915\u093e \u2018\u0921\u0940\u092b\u093e\u0932\u094d\u091f \u0906\u0915\u091f\u093f\u0935\u2019 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092c\u093f\u091f\u094d\u0938\u2019 \u092e\u0947 \u2018\u0915\u0940\u2019 \u0915\u0940 \u0932\u0902\u092c\u0964\u0908 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b\u0964 +# \u0914\u0930 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917 \u0915\u0940\u091c\u093c\u2019 \u0915\u093e \u2018\u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b +# \u0907\u0938\u0924\u0947\u092e\u093e\u0932 \u0939\u094b\u0917\u093e \u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u094b \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u094d\u091f\u2019 \u0915\u0930\u0928\u0947\u0964 +#pubkey --location=/path/to/keys --destination=/destination +# \u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0938\u0947 \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c\u2019 \u0928\u093f\u0915\u093e\u0932\u094b \u0914\u0930 \u0909\u0928\u0915\u094b \u0928\u092f\u0947 \u0920\u093f\u0915\u093e\u0928\u0947 \u0932\u093f\u0916 \u0926\u094b\u0964 +# "pubkey" \u2018\u0915\u092e\u093e\u0902\u0921\u2019 \u0935\u094b\u0939\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u0947 \u0938\u093e\u0925 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u091c\u094b \u092c\u0928\u093e\u092f\u0947 \u0917\u092f\u0947 \u0925\u0947 +# "--asymmetric" \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 +#promote --location=/path/to/keys --version=versionNumber +# \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u092c\u0922\u093e\u0913\u0964 +# \u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940\u2019 \u0914\u0930 (\u092a\u0939\u0932\u0940 \u0935\u093e\u0932\u0940 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 +# \u0939\u0948 \u2018\u0906\u0915\u091f\u093f\u0935 \u2019)\u0964 \u0905\u0917\u0930 \u2018\u0915\u0940\u2019 \u0915\u093e \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0939\u094b\u0928\u0947 \u0935\u093e\u0932\u093e \u0925\u093e \u0924\u094b \u0935\u094b \u2018\u0915\u0940\u2019 \u092c\u0922 \u0915\u0947 +# \u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 +#demote --location=/path/to/keys --version=versionNumber +# \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u0917\u093f\u0930\u093e\u0913\u0964 +# \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0915\u094b \u0917\u093f\u0930\u093e \u0915\u0947 \u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928\u093e\u0913\u0964 \u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u091c\u093c\u2019 \u0915\u094b \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 +# \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u0930\u094b\u0964 +#revoke --location=/path/to/keys --version=versionNumber +# \u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u2018\u0915\u0940\u2019 \u0915\u094b \u0939\u092e\u0947\u0936\u093e \u0915\u0947 \u0932\u093f\u090f \u0928\u093f\u0915\u093e\u0932 \u0926\u094b\u0964 \u092f\u0947 \u2018\u0915\u0940\u2019 \u0915\u094b +# \u2018\u092a\u094d\u0930\u094b\u092e\u094b\u091f \u0915\u092e\u093e\u0902\u0921\u2019 \u0928\u0947 \u092a\u0939\u0932\u0947 \u0938\u0947 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u093f\u092f\u093e \u0939\u094b\u0917\u093e\u0964 +# \u0938\u093e\u0935\u0927\u093e\u0928: \u092f\u0947 \u2018\u0915\u0940\u2019 \u0939\u092e\u0947\u0936\u093e \u0915\u0947 \u0932\u093f\u090f \u0928\u093f\u0915\u093e\u0932 \u0926\u0940 \u091c\u093e\u090f\u0917\u0940\u0964 +# +# \u2018\u092b\u094d\u0932\u093e\u0917\u091c\u093c\u2019 \u091c\u094b \u0939\u094b \u092d\u0940 \u0938\u0915\u0924\u0947 \u0939\u0948 \u0914\u0930 \u0928\u0939\u0940 \u092d\u0940 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948 \u0935\u094b [\u2018\u092c\u0930\u093e\u0915\u0947\u091f\u094d\u0938\u2019] \u092e\u0947 \u0939\u0948\u0964 \u092f\u0947 +# \u0928\u093f\u0936\u093e\u0928\u0940 (a|b|c) \u0915\u093e \u092e\u0924\u0932\u092c \u0939\u0948 "a", "b", \u0914\u0930 "c" \u0938\u092d\u0940 \u0907\u0938\u0924\u093f\u092e\u093e\u0932 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948\u0964 + +KeyczarTool.Usage=Usage: \"KeyczarTool command flags\"\n\ +Commands: {0} {1} {2} {3} {4} {5}\n\ +Flags: {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +Command Usage:\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"A name\"] [--{14}=(dsa|rsa)]\n\ +\t\u0910\u0915 \u0928\u092f\u0940 \u0916\u093e\u0932\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u0913 \u0907\u0938 \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092a\u0930\u0964 \n\ +\t\u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u092a\u0930\u092a\u091c\u093c\u2019 "crypt" \u092f\u093e \u0924\u094b "sign" \u0939\u094b\u0928\u093e \u091a\u093e\u0939\u093f\u090f \u0914\u0930 \u090f\u0915 \u0928\u093e\u092e \u092d\u0940 \n\ +\t\u0926\u093f\u092f\u093e \u091c\u093e \u0938\u0915\u0924\u093e \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b {14} \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u092d\u0940 \u0926\u0947 \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b \u0910\u0915 \u2018\u092a\u092c\u0932\u093f\u0915 \n\ +\t\u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u090f\u0917\u093e \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0905\u0932\u0917\u094b\u0930\u093f\u0924\u094d\u092e\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 \n\ +\t"dsa" \u2018\u0905\u0938\u093f\u092e\u094d\u092e\u0948\u091f\u0930\u093f\u0915 \u0935\u093e\u0932\u092f\u0941\u2019 \u0938\u0939\u0940 \u0939\u0948 \u092c\u0938 \u0935\u094b \u2018\u0938\u0947\u091f\u094d\u0938\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 \u091c\u093f\u0928\u0915\u093e \n\ +\t\u2018\u092a\u0930\u092a\u091c\u093c\u2019 "sign" \u0939\u094b\u0964 \n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\t\u092a\u0941\u0930\u093e\u0928\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092e\u0947 \u090f\u0915 \u0928\u092f\u0940 \u2018\u0915\u0940\u2019 \u0926\u093e\u0932\u0940 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b \n\ +\t\u091c\u093f\u0938\u0915\u093e \u2018\u0921\u0940\u092b\u093e\u0932\u091f \u0906\u0915\u091f\u093f\u0935\u2019 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092c\u093f\u091f\u094d\u0938\u2019 \u092e\u0947 \u2018\u0915\u0940\u2019 \u0915\u0940 \u0932\u0902\u092c\u0964\u0908 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b\u0964 \n\ +\t\u0914\u0930 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917 \u0915\u0940\u091c\u093c\u2019 \u0915\u093e \u2018\u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b \n\ +\t\u0907\u0938\u0924\u0947\u092e\u093e\u0932 \u0939\u094b\u0917\u093e \u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u094b \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u094d\u091f\u2019 \u0915\u0930\u0928\u0947\u0964 \n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\t\u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0938\u0947 \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c\u2019 \u0928\u093f\u0915\u093e\u0932\u094b \u0914\u0930 \u0909\u0928\u0915\u094b \u0928\u092f\u0947 \u0920\u093f\u0915\u093e\u0928\u0947 \u0932\u093f\u0916 \u0926\u094b\u0964 \n\ +\t"pubkey" \u2018\u0915\u092e\u093e\u0902\u0921\u2019 \u0935\u094b\u0939\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u0947 \u0938\u093e\u0925 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u091c\u094b \u092c\u0928\u093e\u092f\u0947 \u0917\u092f\u0947 \u0925\u0947 \n\ +\t"--asymmetric" \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 \n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u092c\u0922\u093e\u0913\u0964 \n\ +\t\u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940\u2019 \u0914\u0930 (\u092a\u0939\u0932\u0940 \u0935\u093e\u0932\u0940 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \n\ +\t\u0939\u0948 \u2018\u0906\u0915\u091f\u093f\u0935 \u2019)\u0964 \u0905\u0917\u0930 \u2018\u0915\u0940\u2019 \u0915\u093e \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0939\u094b\u0928\u0947 \u0935\u093e\u0932\u093e \u0925\u093e \u0924\u094b \u0935\u094b \u2018\u0915\u0940\u2019 \u092c\u0922 \u0915\u0947 \n\ +\t\u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 \n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u0917\u093f\u0930\u093e\u0913\u0964 \n\ +\t\u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0915\u094b \u0917\u093f\u0930\u093e \u0915\u0947 \u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928\u093e\u0913\u0964 \u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u091c\u093c\u2019 \u0915\u094b \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \n\ +\t\u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u0930\u094b\u0964 \n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u2018\u0915\u0940\u2019 \u0915\u094b \u0939\u092e\u0947\u0936\u093e \u0915\u0947 \u0932\u093f\u090f \u0928\u093f\u0915\u093e\u0932 \u0926\u094b\u0964 \u092f\u0947 \u2018\u0915\u0940\u2019 \u0915\u094b \n\ +\t\u2018\u092a\u094d\u0930\u094b\u092e\u094b\u091f \u0915\u092e\u093e\u0902\u0921\u2019 \u0928\u0947 \u092a\u0939\u0932\u0947 \u0938\u0947 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u093f\u092f\u093e \u0939\u094b\u0917\u093e\u0964 \n\ +\u2018\u092b\u094d\u0932\u093e\u0917\u091c\u093c\u2019 \u091c\u094b \u0939\u094b \u092d\u0940 \u0938\u0915\u0924\u0947 \u0939\u0948 \u0914\u0930 \u0928\u0939\u0940 \u092d\u0940 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948 \u0935\u094b [brackets] \u092e\u0947 \u0939\u0948\u0964 \u092f\u0947\n\ +\u0928\u093f\u0936\u093e\u0928\u0940 (a|b|c) \u0915\u093e \u092e\u0924\u0932\u092c \u0939\u0948 "a", "b", \u0914\u0930 "c" \u0938\u092d\u0940 \u0907\u0938\u0924\u093f\u092e\u093e\u0932 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948\u0964 + + + diff --git a/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_jp.properties.svn-base b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_jp.properties.svn-base new file mode 100644 index 0000000..2139adb --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_jp.properties.svn-base @@ -0,0 +1,130 @@ +CiphertextTooShort=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ae\u00e9\u0095\u00b7\u00e3\u0081\u0095\u00ef\u00bc\u0088{0}\u00ef\u00bc\u0089\u00e7\u009f\u00ad\u00e3\u0081\u0099\u00e3\u0081\u008e\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0080\u0081\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e6\u0096\u0087\u00e3\u0081\u00a7\u00e3\u0081\u00af\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +InputBufferTooShort=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0083\u0090\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0083\u00bc\u00e3\u0081\u00af\u00e7\u009f\u00ad\u00e3\u0081\u0099\u00e3\u0081\u008e\u00e3\u0082\u008b\u00e3\u0080\u0082\u00e3\u0083\u0090\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0083\u00bc\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0081\u00af{0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0080\u0081{1}\u00e3\u0081\u008c\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0080\u0082 +BadVersionNumber=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e7\u0095\u00aa\u00e5\u008f\u00b7\u00ef\u00bc\u009a{0} +SignatureTooShort=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ae\u00e9\u0095\u00b7\u00e3\u0081\u0095\u00ef\u00bc\u0088{0}\u00ef\u00bc\u0089\u00e7\u009f\u00ad\u00e3\u0081\u0099\u00e3\u0081\u008e\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0080\u0081\u00e7\u00bd\u00b2\u00e5\u0090\u008d\u00e3\u0081\u00a7\u00e3\u0081\u00af\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +NoPrimaryKeyFound=\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0081\u00af\u00e8\u00a6\u008b\u00e3\u0081\u00a4\u00e3\u0081\u008b\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +InvalidSignatureException=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e6\u0096\u0087\u00e3\u0081\u00ae\u00e8\u00a8\u00bc\u00e6\u0098\u008e\u00e3\u0080\u0082 +KeyWithHashIdentifier=\u00e3\u0083\u008f\u00e3\u0083\u0083\u00e3\u0082\u00b7\u00e3\u0083\u00a5{0}\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0081\u00af\u00e8\u00a6\u008b\u00e3\u0081\u00a4\u00e3\u0081\u008b\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Signer.Signing={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u00bd\u00b2\u00e5\u0090\u008d\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +InvalidTypeInInput=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ab\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0082\u00bf\u00e3\u0082\u00a4\u00e3\u0083\u0097\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Verifier.Verifying={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u00a2\u00ba\u00e8\u00aa\u008d\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Base64Coder.IllegalLength=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00af\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e9\u0095\u00b7\u00e3\u0081\u0095\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Base64Coder.IllegalCharacter=Base64\u00e3\u0081\u00ab\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e6\u0096\u0087\u00e5\u00ad\u0097\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Encrypter.Encrypting={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Crypter.Decrypting={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e8\u00a4\u0087\u00e5\u0090\u0088\u00e5\u008c\u0096\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarFileReader.FileError=\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0082\u00a4\u00e3\u0083\u00ab\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ae\u00e3\u0082\u00a8\u00e3\u0083\u00a9\u00e3\u0083\u00bc\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +KeyczarKey.PublicKeyExport=\u00e3\u0082\u00bf\u00e3\u0082\u00a4\u00e3\u0083\u0097{0}\u00e3\u0081\u00ae\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0081\u00af\u00e7\u00a7\u0098\u00e5\u00af\u0086\u00e9\u008d\u00b5\u00e3\u0081\u008b\u00e3\u0082\u0089\u00e3\u0082\u00a8\u00e3\u0082\u00af\u00e3\u0082\u00b9\u00e3\u0083\u009d\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.UnacceptablePurpose=\u00e5\u00af\u00be\u00e5\u00bf\u009c\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00aa\u00e3\u0081\u0084\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Keyczar.NeedEncryptedReader=\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u009f\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u0092EncryptedReader\u00e3\u0081\u00a7\u00e8\u00aa\u00ad\u00e3\u0082\u0080\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.SinglePrimary=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00af\u00e4\u00b8\u0080\u00e3\u0081\u00a4\u00e3\u0081\u00ae\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e6\u008c\u0081\u00e3\u0081\u009f\u00e3\u0081\u00aa\u00e3\u0081\u0091\u00e3\u0082\u008c\u00e3\u0081\u00b0\u00e3\u0081\u0084\u00e3\u0081\u0091\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.ReadVersion=\u00e8\u00aa\u00ad\u00e3\u0082\u0080\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Keyczar.SizeWarning=\u00e8\u00ad\u00a6\u00e5\u0091\u008a\u00ef\u00bc\u009a{0}\u00e3\u0083\u0093\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0081\u00af\u00e3\u0080\u0081{2}\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0081\u00ae\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ae\u00e6\u008e\u00a8\u00e8\u0096\u00a6\u00e3\u0081\u00ae{1}\u00e3\u0083\u0093\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0081\u00af\u00e5\u00b0\u0091\u00e3\u0081\u00aa\u00e3\u0081\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.NewVersion=\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e4\u00bd\u009c\u00e3\u0081\u00a3\u00e3\u0081\u009f\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Keyczar.PromotedVersion=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3{0}\u00e3\u0082\u0092\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0080\u0082 +Keyczar.CantPromotePrimary=\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.DemotingVersion=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3{0}\u00e3\u0082\u0092\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.CantDemoteScheduled=inactive\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.CantRevoke=\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u00a4\u00b1\u00e5\u008a\u00b9\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.NoSuchVersion=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3{0}\u00e3\u0081\u00af\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 + +# KeyczarTool commands +KeyczarTool.Create=\u00e4\u00bd\u009c\u00e6\u0088\u0090 +KeyczarTool.Addkey=\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u008a\u00a0\u00e3\u0081\u0088\u00e3\u0082\u008b +KeyczarTool.Pubkey=\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5 +KeyczarTool.Promote= \u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088 +KeyczarTool.Demote= \u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088 +KeyczarTool.Revoke=\u00e5\u00a4\u00b1\u00e5\u008a\u00b9 +KeyczarTool.Usekey=\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e4\u00bd\u00bf\u00e3\u0081\u0086 + +# KeyczarTool flags +KeyczarTool.Location=\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3 +KeyczarTool.Name=\u00e5\u0090\u008d\u00e5\u0089\u008d +KeyczarTool.Status=\u00e3\u0082\u00b9\u00e3\u0083\u0086\u00e3\u0083\u00bc\u00e3\u0082\u00bf\u00e3\u0082\u00b9 +KeyczarTool.Purpose=\u00e7\u009b\u00ae\u00e7\u009a\u0084 +KeyczarTool.Destination=\u00e8\u00a1\u008c\u00e3\u0081\u008d\u00e5\u0085\u0088\u00e3\u0081\u008d +KeyczarTool.Version=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3 +KeyczarTool.Size=\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba +KeyczarTool.Asymmetric=\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5 +KeyczarTool.Crypter=\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00bf\u00e3\u0083\u00bc + +KeyczarTool.NeedLocation=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092--{0}\u00e3\u0081\u00a7\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.MustDefinePublic=\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.UnsupportedPurpose=\u00e7\u0084\u00a1\u00e5\u008a\u00b9\u00e3\u0081\u00aa\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +KeyczarTool.MustDefinePurpose=\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.MustDefineLocation=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.CannotExportPubKey=\u00e9\u008d\u00b5\u00e3\u0082\u00bf\u00e3\u0082\u00a4\u00e3\u0083\u0097{0}\u00e3\u0081\u00a8\u00e7\u009b\u00ae\u00e7\u009a\u0084{1}\u00e3\u0081\u00af\u00e3\u0080\u0081\u00e3\u0082\u00a8\u00e3\u0082\u00af\u00e3\u0082\u00b9\u00e3\u0083\u009d\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +KeyczarTool.FileExists=\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0082\u00a4\u00e3\u0083\u00ab{0}\u00e3\u0081\u00af\u00e6\u0097\u00a2\u00e3\u0081\u00ab\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.MissingVersion=\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.UnableToDelete=\u00e5\u00a4\u00b1\u00e5\u008a\u00b9\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u009f\u00e9\u008d\u00b5\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0082\u00a4\u00e3\u0083\u00ab\u00e3\u0082\u0092\u00e5\u0089\u008a\u00e9\u0099\u00a4\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +KeyczarTool.UnableToWrite={0}\u00e3\u0082\u0092\u00e6\u009b\u00b8\u00e3\u0081\u008d\u00e8\u00be\u00bc\u00e3\u0081\u00bf\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +KeyczarTool.MustDefineDestination=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e8\u00a1\u008c\u00e3\u0081\u008d\u00e5\u0085\u0088\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Flag.UnknownFlag=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Command.UnknownCommand=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0082\u00b3\u00e3\u0083\u009e\u00e3\u0083\u00b3\u00e3\u0083\u0089\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 + +# This is a multi-line usage message +# The output looks like the following when arguments are passed in +#Usage: "KeyczarTool command flags" +#Commands: create addkey pubkey promote demote revoke +#Flags: location name size status purpose destination version asymmetric crypter +#Command Usage: +#create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)] +# Creates a new, empty key set in the given location. +# This key set must have a purpose of either "crypt" or "sign" +# and may optionally be given a name. The optional asymmetric +# flag will generate a public key set of the given algorithm. +# The "dsa" asymmetric value is valid only for sets with "sign" purpose. +# with the given purpose. +#addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation] +# Adds a new key to an existing key set. Optionally +# specify a purpose, which is active by default. Optionally +# specify a key size in bits. Also optionally specify the +# location of a set of crypting keys, which will be used to +# encrypt this key set. +#pubkey --location=/path/to/keys --destination=/destination +# Extracts public keys from a given key set and writes them +# to the destination. The "pubkey" command Only works for +# key sets that were created with the "--asymmetric" flag. +#promote --location=/path/to/keys --version=versionNumber +# Promotes the status of the given key version in the given +# location. Active keys are promoted to primary (which demotes +# any existing primary key to active). Keys scheduled for +# revocation are promoted to be active. +#demote --location=/path/to/keys --version=versionNumber +# Demotes the status of the given key version in the given +# location. Primary keys are demoted to active. Active keys +# are scheduled for revocation. +#revoke --location=/path/to/keys --version=versionNumber +# Revokes the key of the given version number. +# This key must have been scheduled for revocation by the +# promote command. WARNING: The key will be destroyed. +# +#Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c" +#are the valid choices + +KeyczarTool.Usage=\u00e6\u00a7\u008b\u00e6\u0096\u0087: \"KeyczarTool\u00e3\u0082\u00b3\u00e3\u0083\u009e\u00e3\u0083\u00b3\u00e3\u0083\u0089\u00e3\u0081\u00ae\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\"\n\ +\u00e3\u0082\u00b3\u00e3\u0083\u009e\u00e3\u0083\u00b3\u00e3\u0083\u0089\u00ef\u00bc\u009a {0} {1} {2} {3} {4} {5}\n\ +\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00ef\u00bc\u009a {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +\u00e8\u00aa\u00ac\u00e6\u0098\u008e\u00ef\u00bc\u009a\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"\u00e5\u0090\u008d\u00e5\u0089\u008d\"] [--{14}=(dsa|rsa)]\n\ +\t\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00a7\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0081\u008b\u00e3\u0082\u0089\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e4\u00bd\u009c\u00e6\u0088\u0090\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0081\u00af"crypt"\u00ef\u00bc\u0088\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00ef\u00bc\u0089\u00e3\u0081\u00be\u00e3\u0081\u009f\u00e3\u0081\u00af"sign"\u00ef\u00bc\u0088\u00e7\u00bd\u00b2\u00e5\u0090\u008d\u00e3\u0081\u0099\u00e3\u0082\u008b\u00ef\u00bc\u0089\u00e3\u0081\u00ab\u00e3\u0081\u0097\u00e3\u0080\u0081\n\ +\t\u00e5\u0090\u008d\u00e5\u0089\u008d\u00e3\u0082\u0092\u00e4\u00bb\u0098\u00e3\u0081\u0091\u00e3\u0082\u008b\u00e3\u0081\u0093\u00e3\u0081\u00a8\u00e3\u0081\u008c\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0082\u00a2\u00e3\u0083\u00ab\u00e3\u0082\u00b4\u00e3\u0083\u00aa\u00e3\u0082\u00ba\u00e3\u0083\u00a0\u00e3\u0082\u0092{14} \n\ +\t\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00a7\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00a7\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t"dsa"\u00e3\u0081\u00ae\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00af"sign"\u00e3\u0081\u00a8\u00e3\u0081\u0084\u00e3\u0081\u0086\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0097\u00e3\u0081\u008b\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082\n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ab\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u008a\u00a0\u00e3\u0081\u0088\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00a7\u00e3\u0080\u0081\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0080\u0081\u00e9\u008d\u00b5\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0080\u0081\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00bf\u00e3\u0083\u00bc\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u008c\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u008b\u00e3\u0082\u0089\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u008f\u0096\u00e3\u0082\u008a\u00e5\u0087\u00ba\u00e3\u0081\u0097\u00e3\u0080\u0081\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00ae\u00e8\u00a1\u008c\u00e3\u0081\u008d\u00e5\u0085\u0088\u00e3\u0081\u00ab\u00e6\u009b\u00b8\u00e3\u0081\u008d\u00e8\u00be\u00bc\u00e3\u0081\u00bf\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t"{2}"\u00e3\u0081\u00af"--asymmetric"\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00ae\u00e5\u00a0\u00b4\u00e5\u0090\u0088\u00e3\u0081\u00ab\u00e3\u0081\u0097\u00e3\u0081\u008b\u00e4\u00bd\u00bf\u00e3\u0081\u0088\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082\n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e3\u0081\u0093\u00e3\u0082\u008c\u00e3\u0081\u00a7\u00e3\u0080\u0081active\u00e9\u008d\u00b5\u00e3\u0082\u0092primary\u00e3\u0081\u00ab\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0080\u0081\n\ +\t\u00e6\u0097\u00a2\u00e3\u0081\u00abprimary\u00e9\u008d\u00b5\u00e3\u0082\u0092active\u00e3\u0081\u00ab\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082inactive\u00e9\u008d\u00b5\u00e3\u0081\u00afactive\u00e3\u0081\u00ab\u00e3\u0081\u00aa\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0081\u00afactive\u00e3\u0081\u00ab\u00e3\u0080\u0081active\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0081\u00afinactive\u00e3\u0081\u00ab\u00e3\u0081\u00aa\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e5\u00a4\u00b1\u00e5\u008a\u00b9\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00af\u00e6\u0097\u00a2\u00e3\u0081\u00abinactive\u00e3\u0081\u00ab\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e8\u00ad\u00a6\u00e5\u0091\u008a\u00ef\u00bc\u009a\u00e3\u0081\u0093\u00e3\u0082\u008c\u00e3\u0081\u00a7\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u0089\u008a\u00e9\u0099\u00a4\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\n\ +\u00e9\u008d\u00b5\u00e6\u008b\u00ac\u00e5\u00bc\u00a7\u00e3\u0081\u00a7\u00e5\u009b\u00b2\u00e3\u0081\u00be\u00e3\u0082\u008c\u00e3\u0081\u009f\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00af\u00e7\u009c\u0081\u00e3\u0081\u0091\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e9\u0081\u00b8\u00e6\u008a\u009e(a|b|c)\u00e3\u0081\u00af"a"\u00e3\u0080\u0081"b"\u00e3\u0080\u0081\u00e3\u0081\u00be\u00e3\u0081\u009f\u00e3\u0081\u00af"c"\u00e3\u0081\u00ae\u00e3\u0081\u00a9\u00e3\u0082\u008c\u00e3\u0081\u008b\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e6\u0084\u008f\u00e5\u0091\u00b3\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0080\u0082 diff --git a/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_pt.properties.svn-base b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_pt.properties.svn-base new file mode 100644 index 0000000..a413d82 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/.svn/text-base/messages_pt.properties.svn-base @@ -0,0 +1,179 @@ +#CiphertextTooShort=Input of length {0} is too short to be valid ciphertext +CiphertextTooShort=Entrada de tamanho {0} \u00e9 muito pequena para ser um texto \ +cifrado v\u00e1lido +#InputBufferTooShort=Input buffer is too short. Given: {0} bytes. Need: {1} +InputBufferTooShort=Buffer de entrada \u00e9 muito pequeno. Dispon\u00edvel: {0} bytes. \ +Necess\u00e1rio: {1} +#BadVersionNumber=Received a bad version number: {0} +BadVersionNumber=N\u00famero de vers\u00e3o inv\u00e1lido: {0} +#SignatureTooShort=Input of length {0} is too short to be valid signature +SignatureTooShort=Entrada de tamanho {0} \u00e9 muito pequena para ser uma \ +assinatura v\u00e1lida +#NoPrimaryKeyFound=No primary key found +NoPrimaryKeyFound=Chave prim\u00e1ria n\u00e3o encontrada +#InvalidSignatureException=Invalid ciphertext signature. +InvalidSignatureException=Assinatura de texto cifrado inv\u00e1lida. +#KeyWithHashIdentifier=Key with hash identifier {0} not found +KeyWithHashIdentifier=Chave com identificador de hash {0} n\u00e3o encontrada +#Signer.Signing=Signing {0} bytes +Signer.Signing=Assinando {0} bytes +#InvalidTypeInInput=Invalid type in input: {0} +InvalidTypeInInput=Tipo inv\u00e1lido na entrada: {0} +#Verifier.Verifying=Verifying {0} bytes +Verifier.Verifying=Verificando {0} bytes +#Base64Coder.IllegalLength=Input source is of illegal length: {0} +Base64Coder.IllegalLength=Entrada de tamanho inv\u00e1lido: {0} +#Base64Coder.IllegalCharacter=Illegal character in Base64 string: {0} +Base64Coder.IllegalCharacter=Caracter inv\u00e1lido em string Base64: {0} +#Encrypter.Encrypting=Encrypting {0} bytes. +Encrypter.Encrypting=Cifrando {0} bytes. +#Crypter.Decrypting=Decrypting {0} bytes. +Crypter.Decrypting=Decifrando {0} bytes. +#KeyczarFileReader.FileError=Error reading file: {0} +KeyczarFileReader.FileError=Erro lendo arquivo: {0} +#KeyczarKey.PublicKeyExport=Public keys of type {0} must be exported from \ +#private keys. +KeyczarKey.PublicKeyExport=Chaves p\u00fablicas de tipo {0} tem que ser exportadas \ +de chaves privadas. +#Keyczar.UnacceptablePurpose=Unacceptable purpose: {0} +Keyczar.UnacceptablePurpose=Objetivo inaceit\u00e1vel: {0} +#Keyczar.NeedEncryptedReader=Must use an EncryptedReader to read encrypted \ +#key sets. +Keyczar.NeedEncryptedReader=\u00c9 necess\u00e1rio usar um EncryptedReader para ler +conjuntos de chaves cifradas. +#Keyczar.SinglePrimary=Key sets may only have a single primary version +Keyczar.SinglePrimary=Conjuntos de chaves podem ter apenas uma vers\u00e3o prim\u00e1ria +#Keyczar.ReadVersion=Read version: {0} +Keyczar.ReadVersion=Vers\u00e3o lida: {0} +#Keyczar.SizeWarning=WARNING: {0}-bit key size is less than the recommended \ +#default key size of {1} bits for {2} keys. +Keyczar.SizeWarning=ATEN\u00e7\u00c3O: chaves de {0} bits s\u00e3o menores do que o padr\u00e3o \ +recomendado de {1} bits para {2} chaves +#Keyczar.NewVersion=Created new version: {0} +Keyczar.NewVersion=Criada uma nova vers\u00e3o: {0} +#Keyczar.PromotedVersion=Promoting version: {0} +Keyczar.PromotedVersion=Promovendo vers\u00e3o: {0} +#Keyczar.CantPromotePrimary=Can't promote a primary key. +Keyczar.CantPromotePrimary=Imposs\u00edvel promover chave prim\u00e1ria. +#Keyczar.DemotingVersion=Demoting version: {0} +Keyczar.DemotingVersion=Demovendo vers\u00e3o: {0} +#Keyczar.CantDemoteScheduled=Can't demote a key scheduled for revocation. +Keyczar.CantDemoteScheduled=Imposs\u00edvel demover chave agendada para revoga\u00e7\u00e3o. +#Keyczar.CantRevoke=Can't revoke key if not scheduled to be revoked. +Keyczar.CantRevoke=Imposs\u00edvel revogar chave n\u00e3o agendada para revoga\u00e7\u00e3o. +#Keyczar.NoSuchVersion=No such version number: {0} +Keyczar.NoSuchVersion=N\u00famero de vers\u00e3o inexistente: {0} + +#KeyczarTool.NeedLocation=Must define a key set location with the --{0} flag +KeyczarTool.NeedLocation=\u00c9 necess\u00e1rio definir a localiza\u00e7\u00e3o do conjunto de \ +chaves com a flag --{0} +#KeyczarTool.MustDefinePublic=Must define a public key location +KeyczarTool.MustDefinePublic=\u00c9 necess\u00e1rio definir a localiza\u00e7\u00e3o da chave \ +p\u00fablica +#KeyczarTool.UnsupportedPurpose=Unsupported purpose: {0} +KeyczarTool.UnsupportedPurpose=Objetivo n\u00e3o suportado: {0} +#KeyczarTool.MustDefinePurpose=Must specify a purpose +KeyczarTool.MustDefinePurpose=\u00c9 preciso especificar um objetivo +#KeyczarTool.MustDefineLocation=Must specify a key set location +KeyczarTool.MustDefineLocation=\u00c9 necess\u00e1rio definir a localiza\u00e7\u00e3o do conjunto \ +de chaves +#KeyczarTool.CannotExportPubKey=Cannot export public keys for {0} key type and \ +#{1} purpose. +KeyczarTool.CannotExportPubKey=Imposs\u00edvel exportar chaves p\u00fablicas do tipo {0} \ +e com objetivo {1}. +#KeyczarTool.FileExists=File {0} already exists +KeyczarTool.FileExists=Arquivo {0} j\u00e1 existe +#KeyczarTool.MissingVersion=Must specify a key version +KeyczarTool.MissingVersion=\u00c9 necess\u00e1rio especificar uma vers\u00e3o de chave +#KeyczarTool.UnableToDelete=Unable to delete revoked key file +KeyczarTool.UnableToDelete=Imposs\u00edvel deletar arquivo de chave revogada +#KeyczarTool.UnableToWrite=Unable to write to: {0} +KeyczarTool.UnableToWrite=Imposs\u00edvel escrever em: {0} +#KeyczarTool.MustDefineDestination=Must define a key set destination +KeyczarTool.MustDefineDestination=\u00c9 necess\u00e1rio definir destino do conjunto de \ +chaves + +#Flag.UnknownFlag=Unknown flag: {0} +Flag.UnknownFlag=Flag desconhecida: {0} +#Command.UnknownCommand=Unknown command: {0} +Command.UnknownCommand=Comando desconhecido: {0} + +# This is a multi-line usage message +# The output looks like the following when arguments are passed in +#Usage: "KeyczarTool command flags" +#Commands: create addkey pubkey promote demote revoke +#Flags: location name size status purpose destination version asymmetric crypter +#Command Usage: +#create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)] +# Creates a new, empty key set in the given location. +# This key set must have a purpose of either "crypt" or "sign" +# and may optionally be given a name. The optional asymmetric +# flag will generate a public key set of the given algorithm. +# The "dsa" asymmetric value is valid only for sets with "sign" purpose. +# with the given purpose. +#addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation] +# Adds a new key to an existing key set. Optionally +# specify a status, which is active by default. Optionally +# specify a key size in bits. Also optionally specify the +# location of a set of crypting keys, which will be used to +# encrypt this key set. +#pubkey --location=/path/to/keys --destination=/destination +# Extracts public keys from a given key set and writes them +# to the destination. The "pubkey" command Only works for +# key sets that were created with the "--asymmetric" flag. +#promote --location=/path/to/keys --version=versionNumber +# Promotes the status of the given key version in the given +# location. Active keys are promoted to primary (which demotes +# any existing primary key to active). Keys scheduled for +# revocation are promoted to be active. +#demote --location=/path/to/keys --version=versionNumber +# Demotes the status of the given key version in the given +# location. Primary keys are demoted to active. Active keys +# are scheduled for revocation. +#revoke --location=/path/to/keys --version=versionNumber +# Revokes the key of the given version number. +# This key must have been scheduled for revocation by the +# promote command. WARNING: The key will be destroyed. +# +#Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c" +#are the valid choices + +KeyczarTool.Usage=Forma de utiliza\u00e7\u00e3o: \"KeyczarTool flags\"\n\ +Comandos: {0} {1} {2} {3} {4} {5}\n\ +Flags: {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +Uso dos comandos:\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"A name\"] [--{14}=(dsa|rsa)]\n\ +\tCria um conjunto de chaves novo e vazio no local informado.\n\ +\tO objetivo deste conjunto tem que ser "crypt" ou "sign"\n\ +\te um nome opcional pode ser escolhido. A flag opcional {14} \n\ +\tir\u00e1 gerar um conjunto de chaves p\u00fablicas do algoritmo dado.\n\ +\tO valor assim\u00e9trico "dsa" \u00e9 v\u00e1lido apenas para conjuntos do tipo "sign".\n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\tAdiciona uma nova chave a um conjunto existente. Opcionalmente\n\ +\tespecifica um status, ativo por padr\u00e3o. Opcionalmente\n\ +\tespecifica um tamanho de chave em bits. Tamb\u00e9m opcionalmente\n\ +\tespecifica a localiza\u00e7\u00e3o das chaves usadas para cifrar este\n\ +\tconjunto.\n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\tExtrai chaves p\u00fablicas de um conjunto e as escreve no\n\ +\tdestino. O comand "pubkey" funciona somente para conjuntos\n\ +\tcriados com a flag "--asymmetric".\n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tPromove o status da vers\u00e3o de chave dada no local \n\ +\tespecificado. Chaves ativas s\u00e3o promovidas para prim\u00e1rias \n\ +\t(rebaixando qualquer chave prim\u00e1ria existente para ativa). \n\ +\tChaves marcadas para revoga\u00e7\u00e3o s\u00e3o promovidas para ativas.\n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tRebaixa o status da vers\u00e3o de chave dada no local especificado.\n\ +\tChaves prim\u00e1rias s\u00e3o rebaixadas para ativas. Chaves ativas\n\ +\ts\u00e3o marcadas para revoga\u00e7\u00e3o.\n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tRevoga a chave correspondente ao n\u00famero de vers\u00e3o informado.\n\ +\tEssa chave deve ter sido marcada para revoga\u00e7\u00e3o pelo \n\ +\tcomando "{4}". AVISO: a chave ser\u00e1 destru\u00edda.\n\n\ +Flags opcionais est\u00e3o em [colchetes]. A nota\u00e7\u00e3o (a|b|c) significa que "a", "b", and "c"\n\ +s\u00e3o escolhar v\u00e1lidas + + diff --git a/src/cz/cvut/keyczar/i18n/Messages.java b/src/cz/cvut/keyczar/i18n/Messages.java new file mode 100644 index 0000000..0dfb5ad --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/Messages.java @@ -0,0 +1,37 @@ +package cz.cvut.keyczar.i18n; + +import cz.cvut.keyczar.annotations.ForTesting; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +/** + * TODO(steveweis): javadoc this + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public class Messages { + private static final String BUNDLE_NAME = "cz.cvut.keyczar.i18n.messages"; + + private static ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + private Messages() { + } + + @ForTesting + public static void changeLocale(Locale locale) { + RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME, locale); + } + + public static String getString(String key, Object... params) { + try { + return MessageFormat.format(RESOURCE_BUNDLE.getString(key), params); + } catch (MissingResourceException e) { + return '!' + key + '!'; + } + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/i18n/messages.properties b/src/cz/cvut/keyczar/i18n/messages.properties new file mode 100644 index 0000000..4d4a9f9 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/messages.properties @@ -0,0 +1,89 @@ +CiphertextTooShort=Input of length {0} is too short to be valid ciphertext +InputBufferTooShort=Input buffer is too short. Given: {0} bytes. Need: {1} +BadVersionNumber=Received a bad version number: {0} +SignatureTooShort=Input of length {0} is too short to be valid signature +NoPrimaryKeyFound=No primary key found +InvalidSignatureException=Invalid ciphertext signature. +KeyWithHashIdentifier=Key with hash identifier {0} not found +Signer.Signing=Signing {0} bytes +InvalidTypeInInput=Invalid type in input: {0} +Verifier.Verifying=Verifying {0} bytes +Base64Coder.IllegalLength=Input source is of illegal length: {0} +Base64Coder.IllegalCharacter=Illegal character in Base64 string: {0} +Encrypter.Encrypting=Encrypting {0} bytes. +Crypter.Decrypting=Decrypting {0} bytes. +KeyczarFileReader.FileError=Error reading file: {0} +KeyczarKey.PublicKeyExport=Public keys of type {0} must be exported from \ +private keys. +Keyczar.UnacceptablePurpose=Unacceptable purpose: {0} +Keyczar.NeedEncryptedReader=Must use an EncryptedReader to read encrypted \ +key sets. +Keyczar.SinglePrimary=Key sets may only have a single primary version +Keyczar.ReadVersion=Read version: {0} +Keyczar.SizeWarning=WARNING: {0}-bit key size is less than the recommended \ +default key size of {1} bits for {2} keys. +Keyczar.NewVersion=Created new version: {0} +Keyczar.PromotedVersion=Promoting version: {0} +Keyczar.CantPromotePrimary=Can't promote a primary key. +Keyczar.DemotingVersion=Demoting version: {0} +Keyczar.CantDemoteScheduled=Can't demote an inactive key. +Keyczar.CantRevoke=Can't revoke key unless inactive. +Keyczar.NoSuchVersion=No such version number: {0} + +KeyczarTool.NeedLocation=Must define a key set location with the --{0} flag +KeyczarTool.MustDefinePublic=Must define a public key location +KeyczarTool.UnsupportedPurpose=Unsupported purpose: {0} +KeyczarTool.MustDefinePurpose=Must specify a purpose +KeyczarTool.MustDefineLocation=Must specify a key set location +KeyczarTool.CannotExportPubKey=Cannot export public keys for {0} key type and \ +{1} purpose. +KeyczarTool.FileExists=File {0} already exists +KeyczarTool.MissingVersion=Must specify a key version +KeyczarTool.UnableToDelete=Unable to delete revoked key file +KeyczarTool.UnableToWrite=Unable to write to: {0} +KeyczarTool.MustDefineDestination=Must define a key set destination + +Flag.UnknownFlag=Unknown flag: {0} +Command.UnknownCommand=Unknown command: {0} + + +KeyczarTool.Usage=Usage: \"KeyczarTool command flags\"\n\ +Commands: {0} {1} {2} {3} {4} {5}\n\ +Flags: {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +Command Usage:\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"A name\"] [--{14}=(dsa|rsa|ec)]\n\ +\tCreates a new, empty key set in the given location.\n\ +\tThis key set must have a purpose of either "crypt" or "sign"\n\ +\tand may optionally be given a name. The optional {14} \n\ +\tflag will generate a public key set of the given algorithm.\n\ +\tThe "dsa" and "ec" asymmetric values are valid only for sets\n\ +\twith "sign" purpose.\n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\tAdds a new key to an existing key set. Optionally\n\ +\tspecify a status, which is active by default. Optionally\n\ +\tspecify a key size in bits. Also optionally specify the\n\ +\tlocation of a set of crypting keys, which will be used to\n\ +\tencrypt this key set.\n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\tExtracts public keys from a given key set and writes them\n\ +\tto the destination. The "{2}" command Only works for\n\ +\tkey sets that were created with the "--asymmetric" flag.\n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tPromotes the status of the given key version in the given \n\ +\tlocation. Active keys are promoted to primary (which demotes \n\ +\tany existing primary key to active). Inactive keys are \n\ +\tpromoted to be active.\n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tDemotes the status of the given key version in the given\n\ +\tlocation. Primary keys are demoted to active. Active keys\n\ +\tare made inactive.\n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tRevokes the key of the given version number.\n\ +\tThis key must have been demoted to inactive to be revoked.\n\ +\tWARNING: The key will be destroyed.\n\n\ +Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c"\n\ +are the valid choices + + diff --git a/src/cz/cvut/keyczar/i18n/messages_hi.properties b/src/cz/cvut/keyczar/i18n/messages_hi.properties new file mode 100644 index 0000000..5214b70 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/messages_hi.properties @@ -0,0 +1,121 @@ +CiphertextTooShort={0} \u0932\u0902\u092c\u093e\u0908 \u0915\u0940 \u2018\u0907\u0928\u092a\u0941\u091f\u2019 \u092c\u0939\u0941\u0924 \u091b\u094b\u091f\u0940 \u0939\u0948, \u090f\u0915 \u0938\u0939\u0940 \u2018\u0938\u093e\u092f\u092b\u0930 \u091f\u0947\u0915\u094d\u0938\u091f\u2019 \u0939\u094b\u0928\u0947 \u0915\u0947 \u0932\u093f\u092f\u0947 +InputBufferTooShort= \u2018\u0907\u0928\u092a\u0941\u091f \u092c\u092b\u094d\u092b\u0930\u2019 \u092c\u0939\u0941\u0924 \u091b\u094b\u091f\u0940 \u0939\u0948, \u0926\u093f\u092f\u093e \u0917\u092f\u093e \u0939\u0948: {0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019\u0964 \u091c\u0930\u0942\u0930\u0924 \u0939\u0948: {1} +BadVersionNumber=\u0939\u092e\u093e\u0930\u0947 \u092a\u093e\u0938 \u0906\u092f\u093e \u090f\u0915 \u092c\u0941\u0930\u093e \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u093e \u0928\u0902\u092c\u0930: {0} +SignatureTooShort= {0} \u0932\u0902\u092c\u093e\u0908 \u0915\u0940 \u2018\u0907\u0928\u092a\u0941\u091f\u2019 \u092c\u0939\u0941\u0924 \u091b\u094b\u091f\u0940 \u0939\u0948, \u090f\u0915 \u0938\u0939\u0940 \u2018\u0938\u093f\u0917\u0928\u0947\u091a\u0930\u2019 \u0939\u094b\u0928\u0947 \u0915\u0947 \u0932\u093f\u092f\u0947 NoPrimaryKeyFound=\u0915\u094b\u0908 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0928\u0939\u0940 \u092e\u093f\u0932\u0940 +InvalidSignatureException=\u092f\u0947 \u2018\u0938\u093e\u092f\u092b\u0930 \u091f\u0947\u0915\u094d\u0938\u091f \u0938\u093f\u0917\u0928\u0947\u091a\u0930\u2019 \u0938\u0939\u0940 \u0928\u0939\u0940 \u0939\u0948 +KeyWithHashIdentifier= \u2018\u0915\u0940\u2019 \u092e\u093f\u0932\u0940 \u0928\u0939\u0940 \u091c\u093f\u0938 \u0915\u093e \u2018\u0939\u093e\u0937 \u0906\u0907\u0919\u0947\u0902\u091f\u093f\u092b\u093e\u092f\u0930\u2019 {0} \u0939\u0948 +Signer.Signing= \u2018\u0938\u093e\u0908\u0928\u093f\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 {0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 +InvalidTypeInInput= \u2018\u0907\u0928\u092a\u0941\u091f\u2019 \u0915\u093e \u2018\u091f\u093e\u0908\u092a\u2019 \u0917\u0932\u0924 \u0939\u0948: {0} +Verifier.Verifying= {0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 \u2018\u0935\u0947\u0930\u093f\u092b\u093e\u0908\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 +Base64Coder.IllegalLength= \u2018\u0907\u0928\u092a\u0941\u091f \u0938\u094b\u0930\u0938\u2019 \u0915\u0940 \u0932\u0902\u092c\u093e\u0908 \u0917\u0932\u0924 \u0939\u0948: {0} +Base64Coder.IllegalCharacter= \u0917\u0932\u0924 \u2018\u0915\u093e\u0930\u0948\u0915\u091f\u0930\u2019 \u0939\u0948 \u2018\u092c\u0947\u0938\u096c\u096a \u0938\u094d\u091f\u094d\u0930\u093f\u0902\u0917\u2019 \u092e\u0947\u0902: {0} +Encrypter.Encrypting={0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 +Crypter.Decrypting={0} \u2018\u092c\u093e\u0908\u091f\u094d\u0938\u2019 \u0915\u0940 \u2018\u0921\u0940\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917\u2019 \u0939\u094b \u0930\u0939\u0940 \u0939\u0948 +KeyczarFileReader.FileError= \u2018\u092b\u093e\u0908\u0932\u2019 \u092a\u0922\u0928\u0947 \u092e\u0947 \u0917\u0932\u0924\u0940 \u0939\u0941\u0908: {0} +KeyczarKey.PublicKeyExport= \u2018\u091f\u093e\u0908\u092a\u2019 {0} \u0915\u0940 \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c\u2019 \u0915\u094b \u2018\u092a\u0930\u093e\u0908\u0935\u0947\u091f \u0915\u0940\u091c\u093c\u2019 \u0938\u0947 \u2018\u090f\u0915\u094d\u0938\u092a\u094b\u0930\u091f\u2019 \u0915\u0930\u0928\u093e \u092a\u0921\u0947\u0917\u093e +Keyczar.UnacceptablePurpose=\u092f\u0947 \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u0928\u093e\u091c\u093e\u0907\u091c\u093c \u0939\u0948: {0} +Keyczar.NeedEncryptedReader= \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0921\u093c \u0930\u0940\u0921\u093c\u0930\u2019 \u0907\u0938\u0924\u093f\u092e\u093e\u0932 \u0915\u0930\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0921\u093c \u0915\u0940 \u0938\u0947\u091f\u094d\u0938\u2019 \u092a\u0922\u0928\u0947 \u0915\u0947 \u0932\u093f\u092f\u0947 +Keyczar.SinglePrimary= \u2018\u0915\u0940 \u0938\u0947\u091f\u094d\u0938\u2019 \u092e\u0947\u0902 \u0938\u093f\u0930\u092b \u0910\u0915 \u2018\u092a\u0930\u093e\u0908\u0902\u092e\u0930\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0939\u094b \u0938\u0915\u0924\u093e \u0939\u0948 +Keyczar.ReadVersion=\u2018\u0930\u0940\u0921 \u0935\u0930\u0937\u093f\u0928\u2019: {0} +Keyczar.SizeWarning=\u0938\u093e\u0935\u0927\u093e\u0928: {0}- \u2018\u092c\u093f\u091f \u0915\u0940\u2019 \u0915\u0940 \u0932\u0902\u092c\u093e\u0908 \u0915\u092e \u0939\u0948 \u0935\u094b \u092e\u0941\u0928\u093e\u0938\u093f\u092c \u0932\u0902\u092c\u093e\u0908 \u0938\u0947 \u091c\u094b \u0939\u0948 \u2018\u0921\u0940\u092b\u093e\u0932\u094d\u091f\u2019 {1} \u2018\u092c\u093f\u091f\u094d\u0938\u2019 {2} \u2018\u0915\u0940\u091c\u093c\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 +Keyczar.Version= \u0928\u092f\u093e \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u092c\u0928\u093e\u092f\u093e \u0917\u092f\u093e: {0} +Keyczar.PromotedVersion={0}: \u2018\u0935\u0930\u0937\u093f\u0928 \u092a\u094d\u0930\u094b\u092e\u094b\u091f\u2019 +Keyczar.CantPromotePrimary= \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0915\u094b \u2018\u092a\u094d\u0930\u094b\u092e\u094b\u091f\u2019 \u0915\u0930 \u0928\u0939\u0940 \u0938\u0915\u0924\u093e +Keyczar.DemotingVersion={0}: \u2018\u0935\u0930\u0937\u093f\u0928 \u0921\u0940\u092e\u094b\u091f\u2019 \u0939\u094b \u0930\u0939\u093e \u0939\u0948 +Keyczar.CantDemoteScheduled= \u0935\u094b \u2018\u0915\u0940 \u0921\u0940\u092e\u094b\u091f\u2019 \u0915\u0930 \u0928\u0939\u0940 \u0938\u0915\u0924\u0947 \u091c\u093f\u0938\u0915\u0940 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0939\u094b\u0928\u0947 \u0935\u093e\u0932\u0940 \u0939\u0948 +Keyczar.CantRevoke=\u092f\u0947 \u2018\u0915\u0940 \u0930\u093f\u0935\u094b\u0915\u2019 \u0928\u0939\u0940 \u0915\u0930 \u0938\u0915\u0924\u0947 \u091c\u094b \u092a\u0939\u0932\u0947 \u0938\u0947 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0928\u0939\u0940 \u0915\u0940 \u0917\u092f\u0940 +Keyczar.NoSuchVersion=\u0910\u0938\u093e \u0915\u094b\u0908 \u2018\u0935\u0930\u0937\u093f\u0928 \u0928\u0902\u092c\u0930\u2019 \u0928\u0939\u0940 \u0939\u0948: {0} + +KeyczarTool.NeedLocation= \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0930\u0916\u0928\u0947 \u0915\u0940 \u091c\u0917\u0939 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 --{0} \u2018\u092b\u094d\u0932\u093e\u0917\u2019 +KeyczarTool.MustDefinePublic= \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u2019 \u0930\u0916\u0928\u0947 \u0915\u0940 \u091c\u0917\u0939 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.UnsupportedPurpose=\u092f\u0947 \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u091a\u0932 \u0928\u0939\u0940 \u0938\u0915\u0924\u093e: {0} +KeyczarTool.MustDefinePurpose=\u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.MustDefineLocation=\u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u0940 \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.CannotExportPubKey=\u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c \u090f\u0915\u094d\u0938\u092a\u094b\u0930\u091f\u2019 \u0915\u0930 \u0928\u0939\u0940 \u0938\u0915\u0924\u0947,{0} \u2018\u0915\u0940 \u091f\u093e\u0908\u092a\u2019 \u0914\u0930 {1} \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 +KeyczarTool.FileExists= \u2018\u092b\u093e\u0908\u0932\u2019 {0} \u092a\u0939\u0932\u0947 \u0938\u0947 \u092e\u094c\u091c\u0942\u0926 \u0939\u0948 +KeyczarTool.MissingVersion=\u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 +KeyczarTool.UnableToDelete= \u2018\u0930\u093f\u0935\u094b\u0915\u0921\u093c \u0915\u0940 \u092b\u093e\u0908\u0932\u2019 \u092e\u093f\u091f \u0928\u0939\u0940 \u0938\u0915\u0940 +KeyczarTool.UnableToWrite=\u0932\u093f\u0916 \u0928\u0939\u0940 \u0938\u0915\u093e: {0} +KeyczarTool.MustDefineDestination= \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u0921\u0947\u0938\u091f\u093f\u0928\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e\u0928\u093e \u091c\u0930\u0942\u0930\u0940 \u0939\u0948 + +Flag.UnknownFlag=\u092f\u0947 \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u0915\u0940 \u092a\u0939\u091a\u093e\u0928 \u0928\u0939\u0940 \u0939\u0948: {0} +Command.UnknownCommand= \u2018\u0915\u092e\u093e\u0902\u0921\u2019 \u0915\u0940 \u092a\u0939\u091a\u093e\u0928 \u0928\u0939\u0940 \u0939\u0948: {0} + +# \u092f\u0947 \u0905\u0928\u0947\u0915 \u2018\u0932\u093e\u0908\u0928\u2019 \u0915\u093e \u2018\u092f\u0942\u0938\u0947\u091c \u092e\u0948\u0938\u0947\u091c\u093c\u2019 \u0939\u0948 +# \u091c\u092c \u2018\u0906\u0930\u0917\u094d\u092f\u0941\u092e\u0948\u0902\u091f\u0938\u2019 \u0926\u093f\u092f\u0947 \u091c\u093e\u0924\u0947 \u0939\u0948 \u0924\u092c \u2018\u0906\u090a\u091f\u092a\u0941\u091f\u2019 \u0910\u0938\u0947 \u0928\u091c\u0930 \u0906\u0924\u0947 \u0939\u0948 +# Usage: "KeyczarTool command flags" +#Commands: create addkey pubkey promote demote revoke +#Flags: location name size status purpose destination version asymmetric crypter +#Command Usage: +#create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)] +# \u0910\u0915 \u0928\u092f\u0940 \u0916\u093e\u0932\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u0913 \u0907\u0938 \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092a\u0930\u0964 +# \u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u092a\u0930\u092a\u091c\u093c\u2019 "crypt" \u092f\u093e \u0924\u094b "sign" \u0939\u094b\u0928\u093e \u091a\u093e\u0939\u093f\u090f \u0914\u0930 \u090f\u0915 \u0928\u093e\u092e \u092d\u0940 +# \u0926\u093f\u092f\u093e \u091c\u093e \u0938\u0915\u0924\u093e \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u0905\u0938\u093f\u092e\u094d\u092e\u0948\u091f\u0930\u093f\u0915 \u092b\u094d\u0932\u093e\u0917\u2019 \u092d\u0940 \u0926\u0947 \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b \u0910\u0915 \u2018\u092a\u092c\u0932\u093f\u0915 +# \u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u090f\u0917\u093e \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0905\u0932\u0917\u094b\u0930\u093f\u0924\u094d\u092e\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 +# "dsa" \u2018\u0905\u0938\u093f\u092e\u094d\u092e\u0948\u091f\u0930\u093f\u0915 \u0935\u093e\u0932\u092f\u0941\u2019 \u0938\u0939\u0940 \u0939\u0948 \u092c\u0938 \u0935\u094b \u2018\u0938\u0947\u091f\u094d\u0938\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 \u091c\u093f\u0928\u0915\u093e +# \u2018\u092a\u0930\u092a\u091c\u093c\u2019 "sign" \u0939\u094b\u0964 +#addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation] +# \u092a\u0941\u0930\u093e\u0928\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092e\u0947 \u090f\u0915 \u0928\u092f\u0940 \u2018\u0915\u0940\u2019 \u0926\u093e\u0932\u0940 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b +# \u091c\u093f\u0938\u0915\u093e \u2018\u0921\u0940\u092b\u093e\u0932\u094d\u091f \u0906\u0915\u091f\u093f\u0935\u2019 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092c\u093f\u091f\u094d\u0938\u2019 \u092e\u0947 \u2018\u0915\u0940\u2019 \u0915\u0940 \u0932\u0902\u092c\u0964\u0908 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b\u0964 +# \u0914\u0930 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917 \u0915\u0940\u091c\u093c\u2019 \u0915\u093e \u2018\u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b +# \u0907\u0938\u0924\u0947\u092e\u093e\u0932 \u0939\u094b\u0917\u093e \u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u094b \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u094d\u091f\u2019 \u0915\u0930\u0928\u0947\u0964 +#pubkey --location=/path/to/keys --destination=/destination +# \u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0938\u0947 \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c\u2019 \u0928\u093f\u0915\u093e\u0932\u094b \u0914\u0930 \u0909\u0928\u0915\u094b \u0928\u092f\u0947 \u0920\u093f\u0915\u093e\u0928\u0947 \u0932\u093f\u0916 \u0926\u094b\u0964 +# "pubkey" \u2018\u0915\u092e\u093e\u0902\u0921\u2019 \u0935\u094b\u0939\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u0947 \u0938\u093e\u0925 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u091c\u094b \u092c\u0928\u093e\u092f\u0947 \u0917\u092f\u0947 \u0925\u0947 +# "--asymmetric" \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 +#promote --location=/path/to/keys --version=versionNumber +# \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u092c\u0922\u093e\u0913\u0964 +# \u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940\u2019 \u0914\u0930 (\u092a\u0939\u0932\u0940 \u0935\u093e\u0932\u0940 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 +# \u0939\u0948 \u2018\u0906\u0915\u091f\u093f\u0935 \u2019)\u0964 \u0905\u0917\u0930 \u2018\u0915\u0940\u2019 \u0915\u093e \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0939\u094b\u0928\u0947 \u0935\u093e\u0932\u093e \u0925\u093e \u0924\u094b \u0935\u094b \u2018\u0915\u0940\u2019 \u092c\u0922 \u0915\u0947 +# \u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 +#demote --location=/path/to/keys --version=versionNumber +# \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u0917\u093f\u0930\u093e\u0913\u0964 +# \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0915\u094b \u0917\u093f\u0930\u093e \u0915\u0947 \u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928\u093e\u0913\u0964 \u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u091c\u093c\u2019 \u0915\u094b \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 +# \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u0930\u094b\u0964 +#revoke --location=/path/to/keys --version=versionNumber +# \u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u2018\u0915\u0940\u2019 \u0915\u094b \u0939\u092e\u0947\u0936\u093e \u0915\u0947 \u0932\u093f\u090f \u0928\u093f\u0915\u093e\u0932 \u0926\u094b\u0964 \u092f\u0947 \u2018\u0915\u0940\u2019 \u0915\u094b +# \u2018\u092a\u094d\u0930\u094b\u092e\u094b\u091f \u0915\u092e\u093e\u0902\u0921\u2019 \u0928\u0947 \u092a\u0939\u0932\u0947 \u0938\u0947 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u093f\u092f\u093e \u0939\u094b\u0917\u093e\u0964 +# \u0938\u093e\u0935\u0927\u093e\u0928: \u092f\u0947 \u2018\u0915\u0940\u2019 \u0939\u092e\u0947\u0936\u093e \u0915\u0947 \u0932\u093f\u090f \u0928\u093f\u0915\u093e\u0932 \u0926\u0940 \u091c\u093e\u090f\u0917\u0940\u0964 +# +# \u2018\u092b\u094d\u0932\u093e\u0917\u091c\u093c\u2019 \u091c\u094b \u0939\u094b \u092d\u0940 \u0938\u0915\u0924\u0947 \u0939\u0948 \u0914\u0930 \u0928\u0939\u0940 \u092d\u0940 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948 \u0935\u094b [\u2018\u092c\u0930\u093e\u0915\u0947\u091f\u094d\u0938\u2019] \u092e\u0947 \u0939\u0948\u0964 \u092f\u0947 +# \u0928\u093f\u0936\u093e\u0928\u0940 (a|b|c) \u0915\u093e \u092e\u0924\u0932\u092c \u0939\u0948 "a", "b", \u0914\u0930 "c" \u0938\u092d\u0940 \u0907\u0938\u0924\u093f\u092e\u093e\u0932 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948\u0964 + +KeyczarTool.Usage=Usage: \"KeyczarTool command flags\"\n\ +Commands: {0} {1} {2} {3} {4} {5}\n\ +Flags: {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +Command Usage:\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"A name\"] [--{14}=(dsa|rsa)]\n\ +\t\u0910\u0915 \u0928\u092f\u0940 \u0916\u093e\u0932\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u0913 \u0907\u0938 \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092a\u0930\u0964 \n\ +\t\u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u092a\u0930\u092a\u091c\u093c\u2019 "crypt" \u092f\u093e \u0924\u094b "sign" \u0939\u094b\u0928\u093e \u091a\u093e\u0939\u093f\u090f \u0914\u0930 \u090f\u0915 \u0928\u093e\u092e \u092d\u0940 \n\ +\t\u0926\u093f\u092f\u093e \u091c\u093e \u0938\u0915\u0924\u093e \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b {14} \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u092d\u0940 \u0926\u0947 \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b \u0910\u0915 \u2018\u092a\u092c\u0932\u093f\u0915 \n\ +\t\u0915\u0940 \u0938\u0947\u091f\u2019 \u092c\u0928\u093e\u090f\u0917\u093e \u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u2018\u0905\u0932\u0917\u094b\u0930\u093f\u0924\u094d\u092e\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 \n\ +\t"dsa" \u2018\u0905\u0938\u093f\u092e\u094d\u092e\u0948\u091f\u0930\u093f\u0915 \u0935\u093e\u0932\u092f\u0941\u2019 \u0938\u0939\u0940 \u0939\u0948 \u092c\u0938 \u0935\u094b \u2018\u0938\u0947\u091f\u094d\u0938\u2019 \u0915\u0947 \u0932\u093f\u092f\u0947 \u091c\u093f\u0928\u0915\u093e \n\ +\t\u2018\u092a\u0930\u092a\u091c\u093c\u2019 "sign" \u0939\u094b\u0964 \n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\t\u092a\u0941\u0930\u093e\u0928\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u092e\u0947 \u090f\u0915 \u0928\u092f\u0940 \u2018\u0915\u0940\u2019 \u0926\u093e\u0932\u0940 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092a\u0930\u092a\u091c\u093c\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b \n\ +\t\u091c\u093f\u0938\u0915\u093e \u2018\u0921\u0940\u092b\u093e\u0932\u091f \u0906\u0915\u091f\u093f\u0935\u2019 \u0939\u0948\u0964 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u092c\u093f\u091f\u094d\u0938\u2019 \u092e\u0947 \u2018\u0915\u0940\u2019 \u0915\u0940 \u0932\u0902\u092c\u0964\u0908 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b\u0964 \n\ +\t\u0914\u0930 \u091a\u093e\u0939\u094b \u0924\u094b \u2018\u0915\u094d\u0930\u093f\u092a\u091f\u093f\u0902\u0917 \u0915\u0940\u091c\u093c\u2019 \u0915\u093e \u2018\u0938\u0947\u091f\u2019 \u0915\u093e \u2018\u0932\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u092c\u0924\u093e \u0938\u0915\u0924\u0947 \u0939\u094b \u091c\u094b \n\ +\t\u0907\u0938\u0924\u0947\u092e\u093e\u0932 \u0939\u094b\u0917\u093e \u092f\u0947 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u094b \u2018\u090f\u0928\u0915\u094d\u0930\u093f\u092a\u094d\u091f\u2019 \u0915\u0930\u0928\u0947\u0964 \n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\t\u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0938\u0947 \u2018\u092a\u092c\u0932\u093f\u0915 \u0915\u0940\u091c\u093c\u2019 \u0928\u093f\u0915\u093e\u0932\u094b \u0914\u0930 \u0909\u0928\u0915\u094b \u0928\u092f\u0947 \u0920\u093f\u0915\u093e\u0928\u0947 \u0932\u093f\u0916 \u0926\u094b\u0964 \n\ +\t"pubkey" \u2018\u0915\u092e\u093e\u0902\u0921\u2019 \u0935\u094b\u0939\u0940 \u2018\u0915\u0940 \u0938\u0947\u091f\u2019 \u0915\u0947 \u0938\u093e\u0925 \u0915\u093e\u092e \u0915\u0930\u0947\u0917\u093e \u091c\u094b \u092c\u0928\u093e\u092f\u0947 \u0917\u092f\u0947 \u0925\u0947 \n\ +\t"--asymmetric" \u2018\u092b\u094d\u0932\u093e\u0917\u2019 \u0915\u0947 \u0938\u093e\u0925\u0964 \n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u092c\u0922\u093e\u0913\u0964 \n\ +\t\u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940\u2019 \u0914\u0930 (\u092a\u0939\u0932\u0940 \u0935\u093e\u0932\u0940 \u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \n\ +\t\u0939\u0948 \u2018\u0906\u0915\u091f\u093f\u0935 \u2019)\u0964 \u0905\u0917\u0930 \u2018\u0915\u0940\u2019 \u0915\u093e \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0939\u094b\u0928\u0947 \u0935\u093e\u0932\u093e \u0925\u093e \u0924\u094b \u0935\u094b \u2018\u0915\u0940\u2019 \u092c\u0922 \u0915\u0947 \n\ +\t\u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928 \u091c\u093e\u0924\u0940 \u0939\u0948\u0964 \n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u0926\u093f\u092f\u0947 \u0939\u0941\u090f \u091c\u0917\u0939 \u0915\u0940 \u0926\u0940 \u0939\u0941\u0908 \u2018\u0915\u0940 \u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u0939\u0948\u0938\u0940\u092f\u0924 \u0917\u093f\u0930\u093e\u0913\u0964 \n\ +\t\u2018\u092a\u094d\u0930\u093e\u0908\u092e\u0930\u0940 \u0915\u0940\u2019 \u0915\u094b \u0917\u093f\u0930\u093e \u0915\u0947 \u2018\u0906\u0915\u091f\u093f\u0935\u2019 \u092c\u0928\u093e\u0913\u0964 \u2018\u0906\u0915\u091f\u093f\u0935 \u0915\u0940\u091c\u093c\u2019 \u0915\u094b \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \n\ +\t\u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u0930\u094b\u0964 \n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u0926\u093f\u092f\u093e \u0939\u0941\u0906 \u2018\u0935\u0930\u0937\u093f\u0928\u2019 \u0915\u0940 \u2018\u0915\u0940\u2019 \u0915\u094b \u0939\u092e\u0947\u0936\u093e \u0915\u0947 \u0932\u093f\u090f \u0928\u093f\u0915\u093e\u0932 \u0926\u094b\u0964 \u092f\u0947 \u2018\u0915\u0940\u2019 \u0915\u094b \n\ +\t\u2018\u092a\u094d\u0930\u094b\u092e\u094b\u091f \u0915\u092e\u093e\u0902\u0921\u2019 \u0928\u0947 \u092a\u0939\u0932\u0947 \u0938\u0947 \u2018\u0930\u0947\u0935\u094b\u0915\u0947\u0936\u093f\u0928\u2019 \u0915\u0947 \u0932\u093f\u090f \u0924\u0948\u092f\u093e\u0930 \u0915\u093f\u092f\u093e \u0939\u094b\u0917\u093e\u0964 \n\ +\u2018\u092b\u094d\u0932\u093e\u0917\u091c\u093c\u2019 \u091c\u094b \u0939\u094b \u092d\u0940 \u0938\u0915\u0924\u0947 \u0939\u0948 \u0914\u0930 \u0928\u0939\u0940 \u092d\u0940 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948 \u0935\u094b [brackets] \u092e\u0947 \u0939\u0948\u0964 \u092f\u0947\n\ +\u0928\u093f\u0936\u093e\u0928\u0940 (a|b|c) \u0915\u093e \u092e\u0924\u0932\u092c \u0939\u0948 "a", "b", \u0914\u0930 "c" \u0938\u092d\u0940 \u0907\u0938\u0924\u093f\u092e\u093e\u0932 \u0939\u094b \u0938\u0915\u0924\u0947 \u0939\u0948\u0964 + + + diff --git a/src/cz/cvut/keyczar/i18n/messages_jp.properties b/src/cz/cvut/keyczar/i18n/messages_jp.properties new file mode 100644 index 0000000..2139adb --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/messages_jp.properties @@ -0,0 +1,130 @@ +CiphertextTooShort=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ae\u00e9\u0095\u00b7\u00e3\u0081\u0095\u00ef\u00bc\u0088{0}\u00ef\u00bc\u0089\u00e7\u009f\u00ad\u00e3\u0081\u0099\u00e3\u0081\u008e\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0080\u0081\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e6\u0096\u0087\u00e3\u0081\u00a7\u00e3\u0081\u00af\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +InputBufferTooShort=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0083\u0090\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0083\u00bc\u00e3\u0081\u00af\u00e7\u009f\u00ad\u00e3\u0081\u0099\u00e3\u0081\u008e\u00e3\u0082\u008b\u00e3\u0080\u0082\u00e3\u0083\u0090\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0083\u00bc\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0081\u00af{0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0080\u0081{1}\u00e3\u0081\u008c\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0080\u0082 +BadVersionNumber=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e7\u0095\u00aa\u00e5\u008f\u00b7\u00ef\u00bc\u009a{0} +SignatureTooShort=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ae\u00e9\u0095\u00b7\u00e3\u0081\u0095\u00ef\u00bc\u0088{0}\u00ef\u00bc\u0089\u00e7\u009f\u00ad\u00e3\u0081\u0099\u00e3\u0081\u008e\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0080\u0081\u00e7\u00bd\u00b2\u00e5\u0090\u008d\u00e3\u0081\u00a7\u00e3\u0081\u00af\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +NoPrimaryKeyFound=\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0081\u00af\u00e8\u00a6\u008b\u00e3\u0081\u00a4\u00e3\u0081\u008b\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +InvalidSignatureException=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e6\u0096\u0087\u00e3\u0081\u00ae\u00e8\u00a8\u00bc\u00e6\u0098\u008e\u00e3\u0080\u0082 +KeyWithHashIdentifier=\u00e3\u0083\u008f\u00e3\u0083\u0083\u00e3\u0082\u00b7\u00e3\u0083\u00a5{0}\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0081\u00af\u00e8\u00a6\u008b\u00e3\u0081\u00a4\u00e3\u0081\u008b\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Signer.Signing={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u00bd\u00b2\u00e5\u0090\u008d\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +InvalidTypeInInput=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ab\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0082\u00bf\u00e3\u0082\u00a4\u00e3\u0083\u0097\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Verifier.Verifying={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u00a2\u00ba\u00e8\u00aa\u008d\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Base64Coder.IllegalLength=\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00af\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e9\u0095\u00b7\u00e3\u0081\u0095\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Base64Coder.IllegalCharacter=Base64\u00e3\u0081\u00ab\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e6\u0096\u0087\u00e5\u00ad\u0097\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Encrypter.Encrypting={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Crypter.Decrypting={0}\u00e3\u0083\u0090\u00e3\u0082\u00a4\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e8\u00a4\u0087\u00e5\u0090\u0088\u00e5\u008c\u0096\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarFileReader.FileError=\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0082\u00a4\u00e3\u0083\u00ab\u00e5\u0085\u00a5\u00e5\u008a\u009b\u00e3\u0081\u00ae\u00e3\u0082\u00a8\u00e3\u0083\u00a9\u00e3\u0083\u00bc\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +KeyczarKey.PublicKeyExport=\u00e3\u0082\u00bf\u00e3\u0082\u00a4\u00e3\u0083\u0097{0}\u00e3\u0081\u00ae\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0081\u00af\u00e7\u00a7\u0098\u00e5\u00af\u0086\u00e9\u008d\u00b5\u00e3\u0081\u008b\u00e3\u0082\u0089\u00e3\u0082\u00a8\u00e3\u0082\u00af\u00e3\u0082\u00b9\u00e3\u0083\u009d\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.UnacceptablePurpose=\u00e5\u00af\u00be\u00e5\u00bf\u009c\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00aa\u00e3\u0081\u0084\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Keyczar.NeedEncryptedReader=\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u009f\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u0092EncryptedReader\u00e3\u0081\u00a7\u00e8\u00aa\u00ad\u00e3\u0082\u0080\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.SinglePrimary=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00af\u00e4\u00b8\u0080\u00e3\u0081\u00a4\u00e3\u0081\u00ae\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e6\u008c\u0081\u00e3\u0081\u009f\u00e3\u0081\u00aa\u00e3\u0081\u0091\u00e3\u0082\u008c\u00e3\u0081\u00b0\u00e3\u0081\u0084\u00e3\u0081\u0091\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.ReadVersion=\u00e8\u00aa\u00ad\u00e3\u0082\u0080\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Keyczar.SizeWarning=\u00e8\u00ad\u00a6\u00e5\u0091\u008a\u00ef\u00bc\u009a{0}\u00e3\u0083\u0093\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0081\u00af\u00e3\u0080\u0081{2}\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0081\u00ae\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ae\u00e6\u008e\u00a8\u00e8\u0096\u00a6\u00e3\u0081\u00ae{1}\u00e3\u0083\u0093\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0081\u00af\u00e5\u00b0\u0091\u00e3\u0081\u00aa\u00e3\u0081\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.NewVersion=\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e4\u00bd\u009c\u00e3\u0081\u00a3\u00e3\u0081\u009f\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Keyczar.PromotedVersion=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3{0}\u00e3\u0082\u0092\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0080\u0082 +Keyczar.CantPromotePrimary=\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.DemotingVersion=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3{0}\u00e3\u0082\u0092\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Keyczar.CantDemoteScheduled=inactive\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.CantRevoke=\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u00a4\u00b1\u00e5\u008a\u00b9\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +Keyczar.NoSuchVersion=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3{0}\u00e3\u0081\u00af\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 + +# KeyczarTool commands +KeyczarTool.Create=\u00e4\u00bd\u009c\u00e6\u0088\u0090 +KeyczarTool.Addkey=\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u008a\u00a0\u00e3\u0081\u0088\u00e3\u0082\u008b +KeyczarTool.Pubkey=\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5 +KeyczarTool.Promote= \u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088 +KeyczarTool.Demote= \u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088 +KeyczarTool.Revoke=\u00e5\u00a4\u00b1\u00e5\u008a\u00b9 +KeyczarTool.Usekey=\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e4\u00bd\u00bf\u00e3\u0081\u0086 + +# KeyczarTool flags +KeyczarTool.Location=\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3 +KeyczarTool.Name=\u00e5\u0090\u008d\u00e5\u0089\u008d +KeyczarTool.Status=\u00e3\u0082\u00b9\u00e3\u0083\u0086\u00e3\u0083\u00bc\u00e3\u0082\u00bf\u00e3\u0082\u00b9 +KeyczarTool.Purpose=\u00e7\u009b\u00ae\u00e7\u009a\u0084 +KeyczarTool.Destination=\u00e8\u00a1\u008c\u00e3\u0081\u008d\u00e5\u0085\u0088\u00e3\u0081\u008d +KeyczarTool.Version=\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3 +KeyczarTool.Size=\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba +KeyczarTool.Asymmetric=\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5 +KeyczarTool.Crypter=\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00bf\u00e3\u0083\u00bc + +KeyczarTool.NeedLocation=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092--{0}\u00e3\u0081\u00a7\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.MustDefinePublic=\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.UnsupportedPurpose=\u00e7\u0084\u00a1\u00e5\u008a\u00b9\u00e3\u0081\u00aa\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +KeyczarTool.MustDefinePurpose=\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.MustDefineLocation=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.CannotExportPubKey=\u00e9\u008d\u00b5\u00e3\u0082\u00bf\u00e3\u0082\u00a4\u00e3\u0083\u0097{0}\u00e3\u0081\u00a8\u00e7\u009b\u00ae\u00e7\u009a\u0084{1}\u00e3\u0081\u00af\u00e3\u0080\u0081\u00e3\u0082\u00a8\u00e3\u0082\u00af\u00e3\u0082\u00b9\u00e3\u0083\u009d\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +KeyczarTool.FileExists=\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0082\u00a4\u00e3\u0083\u00ab{0}\u00e3\u0081\u00af\u00e6\u0097\u00a2\u00e3\u0081\u00ab\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.MissingVersion=\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +KeyczarTool.UnableToDelete=\u00e5\u00a4\u00b1\u00e5\u008a\u00b9\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u009f\u00e9\u008d\u00b5\u00e3\u0083\u0095\u00e3\u0082\u00a1\u00e3\u0082\u00a4\u00e3\u0083\u00ab\u00e3\u0082\u0092\u00e5\u0089\u008a\u00e9\u0099\u00a4\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +KeyczarTool.UnableToWrite={0}\u00e3\u0082\u0092\u00e6\u009b\u00b8\u00e3\u0081\u008d\u00e8\u00be\u00bc\u00e3\u0081\u00bf\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082 +KeyczarTool.MustDefineDestination=\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e8\u00a1\u008c\u00e3\u0081\u008d\u00e5\u0085\u0088\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +Flag.UnknownFlag=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 +Command.UnknownCommand=\u00e4\u00b8\u008d\u00e6\u00ad\u00a3\u00e3\u0081\u00aa\u00e3\u0082\u00b3\u00e3\u0083\u009e\u00e3\u0083\u00b3\u00e3\u0083\u0089\u00ef\u00bc\u009a{0}\u00e3\u0080\u0082 + +# This is a multi-line usage message +# The output looks like the following when arguments are passed in +#Usage: "KeyczarTool command flags" +#Commands: create addkey pubkey promote demote revoke +#Flags: location name size status purpose destination version asymmetric crypter +#Command Usage: +#create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)] +# Creates a new, empty key set in the given location. +# This key set must have a purpose of either "crypt" or "sign" +# and may optionally be given a name. The optional asymmetric +# flag will generate a public key set of the given algorithm. +# The "dsa" asymmetric value is valid only for sets with "sign" purpose. +# with the given purpose. +#addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation] +# Adds a new key to an existing key set. Optionally +# specify a purpose, which is active by default. Optionally +# specify a key size in bits. Also optionally specify the +# location of a set of crypting keys, which will be used to +# encrypt this key set. +#pubkey --location=/path/to/keys --destination=/destination +# Extracts public keys from a given key set and writes them +# to the destination. The "pubkey" command Only works for +# key sets that were created with the "--asymmetric" flag. +#promote --location=/path/to/keys --version=versionNumber +# Promotes the status of the given key version in the given +# location. Active keys are promoted to primary (which demotes +# any existing primary key to active). Keys scheduled for +# revocation are promoted to be active. +#demote --location=/path/to/keys --version=versionNumber +# Demotes the status of the given key version in the given +# location. Primary keys are demoted to active. Active keys +# are scheduled for revocation. +#revoke --location=/path/to/keys --version=versionNumber +# Revokes the key of the given version number. +# This key must have been scheduled for revocation by the +# promote command. WARNING: The key will be destroyed. +# +#Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c" +#are the valid choices + +KeyczarTool.Usage=\u00e6\u00a7\u008b\u00e6\u0096\u0087: \"KeyczarTool\u00e3\u0082\u00b3\u00e3\u0083\u009e\u00e3\u0083\u00b3\u00e3\u0083\u0089\u00e3\u0081\u00ae\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\"\n\ +\u00e3\u0082\u00b3\u00e3\u0083\u009e\u00e3\u0083\u00b3\u00e3\u0083\u0089\u00ef\u00bc\u009a {0} {1} {2} {3} {4} {5}\n\ +\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00ef\u00bc\u009a {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +\u00e8\u00aa\u00ac\u00e6\u0098\u008e\u00ef\u00bc\u009a\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"\u00e5\u0090\u008d\u00e5\u0089\u008d\"] [--{14}=(dsa|rsa)]\n\ +\t\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00a7\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0081\u008b\u00e3\u0082\u0089\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e4\u00bd\u009c\u00e6\u0088\u0090\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0081\u00af"crypt"\u00ef\u00bc\u0088\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00ef\u00bc\u0089\u00e3\u0081\u00be\u00e3\u0081\u009f\u00e3\u0081\u00af"sign"\u00ef\u00bc\u0088\u00e7\u00bd\u00b2\u00e5\u0090\u008d\u00e3\u0081\u0099\u00e3\u0082\u008b\u00ef\u00bc\u0089\u00e3\u0081\u00ab\u00e3\u0081\u0097\u00e3\u0080\u0081\n\ +\t\u00e5\u0090\u008d\u00e5\u0089\u008d\u00e3\u0082\u0092\u00e4\u00bb\u0098\u00e3\u0081\u0091\u00e3\u0082\u008b\u00e3\u0081\u0093\u00e3\u0081\u00a8\u00e3\u0081\u008c\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0082\u00a2\u00e3\u0083\u00ab\u00e3\u0082\u00b4\u00e3\u0083\u00aa\u00e3\u0082\u00ba\u00e3\u0083\u00a0\u00e3\u0082\u0092{14} \n\ +\t\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00a7\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00a7\u00e3\u0081\u0084\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t"dsa"\u00e3\u0081\u00ae\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00af"sign"\u00e3\u0081\u00a8\u00e3\u0081\u0084\u00e3\u0081\u0086\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0097\u00e3\u0081\u008b\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082\n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u00ab\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u008a\u00a0\u00e3\u0081\u0088\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00a7\u00e3\u0080\u0081\u00e7\u009b\u00ae\u00e7\u009a\u0084\u00e3\u0080\u0081\u00e9\u008d\u00b5\u00e3\u0082\u00b5\u00e3\u0082\u00a4\u00e3\u0082\u00ba\u00e3\u0080\u0081\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e6\u009a\u0097\u00e5\u008f\u00b7\u00e5\u008c\u0096\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00bf\u00e3\u0083\u00bc\u00e3\u0081\u00ae\u00e3\u0083\u00ad\u00e3\u0082\u00b1\u00e3\u0083\u00bc\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u008c\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\t\u00e9\u008d\u00b5\u00e3\u0082\u00bb\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0081\u008b\u00e3\u0082\u0089\u00e5\u0085\u00ac\u00e9\u0096\u008b\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u008f\u0096\u00e3\u0082\u008a\u00e5\u0087\u00ba\u00e3\u0081\u0097\u00e3\u0080\u0081\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u00ae\u00e8\u00a1\u008c\u00e3\u0081\u008d\u00e5\u0085\u0088\u00e3\u0081\u00ab\u00e6\u009b\u00b8\u00e3\u0081\u008d\u00e8\u00be\u00bc\u00e3\u0081\u00bf\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t"{2}"\u00e3\u0081\u00af"--asymmetric"\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00ae\u00e5\u00a0\u00b4\u00e5\u0090\u0088\u00e3\u0081\u00ab\u00e3\u0081\u0097\u00e3\u0081\u008b\u00e4\u00bd\u00bf\u00e3\u0081\u0088\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093\u00e3\u0080\u0082\n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e3\u0081\u0093\u00e3\u0082\u008c\u00e3\u0081\u00a7\u00e3\u0080\u0081active\u00e9\u008d\u00b5\u00e3\u0082\u0092primary\u00e3\u0081\u00ab\u00e3\u0083\u0097\u00e3\u0083\u00ad\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0080\u0081\n\ +\t\u00e6\u0097\u00a2\u00e3\u0081\u00abprimary\u00e9\u008d\u00b5\u00e3\u0082\u0092active\u00e3\u0081\u00ab\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082inactive\u00e9\u008d\u00b5\u00e3\u0081\u00afactive\u00e3\u0081\u00ab\u00e3\u0081\u00aa\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e3\u0083\u0087\u00e3\u0082\u00a3\u00e3\u0083\u00a2\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e4\u00b8\u0080\u00e6\u00ac\u00a1\u00e9\u008d\u00b5\u00e3\u0081\u00afactive\u00e3\u0081\u00ab\u00e3\u0080\u0081active\u00e3\u0081\u00ae\u00e9\u008d\u00b5\u00e3\u0081\u00afinactive\u00e3\u0081\u00ab\u00e3\u0081\u00aa\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e5\u00a4\u00b1\u00e5\u008a\u00b9\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\ +\t\u00e9\u008d\u00b5\u00e3\u0083\u0090\u00e3\u0083\u00bc\u00e3\u0082\u00b8\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00af\u00e6\u0097\u00a2\u00e3\u0081\u00abinactive\u00e3\u0081\u00ab\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0082\u008b\u00e5\u00bf\u0085\u00e8\u00a6\u0081\u00e3\u0081\u008c\u00e3\u0081\u0082\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e8\u00ad\u00a6\u00e5\u0091\u008a\u00ef\u00bc\u009a\u00e3\u0081\u0093\u00e3\u0082\u008c\u00e3\u0081\u00a7\u00e9\u008d\u00b5\u00e3\u0082\u0092\u00e5\u0089\u008a\u00e9\u0099\u00a4\u00e3\u0081\u0097\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\n\n\ +\u00e9\u008d\u00b5\u00e6\u008b\u00ac\u00e5\u00bc\u00a7\u00e3\u0081\u00a7\u00e5\u009b\u00b2\u00e3\u0081\u00be\u00e3\u0082\u008c\u00e3\u0081\u009f\u00e3\u0082\u00aa\u00e3\u0083\u0097\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0081\u00af\u00e7\u009c\u0081\u00e3\u0081\u0091\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e9\u0081\u00b8\u00e6\u008a\u009e(a|b|c)\u00e3\u0081\u00af"a"\u00e3\u0080\u0081"b"\u00e3\u0080\u0081\u00e3\u0081\u00be\u00e3\u0081\u009f\u00e3\u0081\u00af"c"\u00e3\u0081\u00ae\u00e3\u0081\u00a9\u00e3\u0082\u008c\u00e3\u0081\u008b\u00e3\u0082\u0092\u00e6\u008c\u0087\u00e5\u00ae\u009a\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e6\u0084\u008f\u00e5\u0091\u00b3\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0080\u0082 diff --git a/src/cz/cvut/keyczar/i18n/messages_pt.properties b/src/cz/cvut/keyczar/i18n/messages_pt.properties new file mode 100644 index 0000000..a413d82 --- /dev/null +++ b/src/cz/cvut/keyczar/i18n/messages_pt.properties @@ -0,0 +1,179 @@ +#CiphertextTooShort=Input of length {0} is too short to be valid ciphertext +CiphertextTooShort=Entrada de tamanho {0} \u00e9 muito pequena para ser um texto \ +cifrado v\u00e1lido +#InputBufferTooShort=Input buffer is too short. Given: {0} bytes. Need: {1} +InputBufferTooShort=Buffer de entrada \u00e9 muito pequeno. Dispon\u00edvel: {0} bytes. \ +Necess\u00e1rio: {1} +#BadVersionNumber=Received a bad version number: {0} +BadVersionNumber=N\u00famero de vers\u00e3o inv\u00e1lido: {0} +#SignatureTooShort=Input of length {0} is too short to be valid signature +SignatureTooShort=Entrada de tamanho {0} \u00e9 muito pequena para ser uma \ +assinatura v\u00e1lida +#NoPrimaryKeyFound=No primary key found +NoPrimaryKeyFound=Chave prim\u00e1ria n\u00e3o encontrada +#InvalidSignatureException=Invalid ciphertext signature. +InvalidSignatureException=Assinatura de texto cifrado inv\u00e1lida. +#KeyWithHashIdentifier=Key with hash identifier {0} not found +KeyWithHashIdentifier=Chave com identificador de hash {0} n\u00e3o encontrada +#Signer.Signing=Signing {0} bytes +Signer.Signing=Assinando {0} bytes +#InvalidTypeInInput=Invalid type in input: {0} +InvalidTypeInInput=Tipo inv\u00e1lido na entrada: {0} +#Verifier.Verifying=Verifying {0} bytes +Verifier.Verifying=Verificando {0} bytes +#Base64Coder.IllegalLength=Input source is of illegal length: {0} +Base64Coder.IllegalLength=Entrada de tamanho inv\u00e1lido: {0} +#Base64Coder.IllegalCharacter=Illegal character in Base64 string: {0} +Base64Coder.IllegalCharacter=Caracter inv\u00e1lido em string Base64: {0} +#Encrypter.Encrypting=Encrypting {0} bytes. +Encrypter.Encrypting=Cifrando {0} bytes. +#Crypter.Decrypting=Decrypting {0} bytes. +Crypter.Decrypting=Decifrando {0} bytes. +#KeyczarFileReader.FileError=Error reading file: {0} +KeyczarFileReader.FileError=Erro lendo arquivo: {0} +#KeyczarKey.PublicKeyExport=Public keys of type {0} must be exported from \ +#private keys. +KeyczarKey.PublicKeyExport=Chaves p\u00fablicas de tipo {0} tem que ser exportadas \ +de chaves privadas. +#Keyczar.UnacceptablePurpose=Unacceptable purpose: {0} +Keyczar.UnacceptablePurpose=Objetivo inaceit\u00e1vel: {0} +#Keyczar.NeedEncryptedReader=Must use an EncryptedReader to read encrypted \ +#key sets. +Keyczar.NeedEncryptedReader=\u00c9 necess\u00e1rio usar um EncryptedReader para ler +conjuntos de chaves cifradas. +#Keyczar.SinglePrimary=Key sets may only have a single primary version +Keyczar.SinglePrimary=Conjuntos de chaves podem ter apenas uma vers\u00e3o prim\u00e1ria +#Keyczar.ReadVersion=Read version: {0} +Keyczar.ReadVersion=Vers\u00e3o lida: {0} +#Keyczar.SizeWarning=WARNING: {0}-bit key size is less than the recommended \ +#default key size of {1} bits for {2} keys. +Keyczar.SizeWarning=ATEN\u00e7\u00c3O: chaves de {0} bits s\u00e3o menores do que o padr\u00e3o \ +recomendado de {1} bits para {2} chaves +#Keyczar.NewVersion=Created new version: {0} +Keyczar.NewVersion=Criada uma nova vers\u00e3o: {0} +#Keyczar.PromotedVersion=Promoting version: {0} +Keyczar.PromotedVersion=Promovendo vers\u00e3o: {0} +#Keyczar.CantPromotePrimary=Can't promote a primary key. +Keyczar.CantPromotePrimary=Imposs\u00edvel promover chave prim\u00e1ria. +#Keyczar.DemotingVersion=Demoting version: {0} +Keyczar.DemotingVersion=Demovendo vers\u00e3o: {0} +#Keyczar.CantDemoteScheduled=Can't demote a key scheduled for revocation. +Keyczar.CantDemoteScheduled=Imposs\u00edvel demover chave agendada para revoga\u00e7\u00e3o. +#Keyczar.CantRevoke=Can't revoke key if not scheduled to be revoked. +Keyczar.CantRevoke=Imposs\u00edvel revogar chave n\u00e3o agendada para revoga\u00e7\u00e3o. +#Keyczar.NoSuchVersion=No such version number: {0} +Keyczar.NoSuchVersion=N\u00famero de vers\u00e3o inexistente: {0} + +#KeyczarTool.NeedLocation=Must define a key set location with the --{0} flag +KeyczarTool.NeedLocation=\u00c9 necess\u00e1rio definir a localiza\u00e7\u00e3o do conjunto de \ +chaves com a flag --{0} +#KeyczarTool.MustDefinePublic=Must define a public key location +KeyczarTool.MustDefinePublic=\u00c9 necess\u00e1rio definir a localiza\u00e7\u00e3o da chave \ +p\u00fablica +#KeyczarTool.UnsupportedPurpose=Unsupported purpose: {0} +KeyczarTool.UnsupportedPurpose=Objetivo n\u00e3o suportado: {0} +#KeyczarTool.MustDefinePurpose=Must specify a purpose +KeyczarTool.MustDefinePurpose=\u00c9 preciso especificar um objetivo +#KeyczarTool.MustDefineLocation=Must specify a key set location +KeyczarTool.MustDefineLocation=\u00c9 necess\u00e1rio definir a localiza\u00e7\u00e3o do conjunto \ +de chaves +#KeyczarTool.CannotExportPubKey=Cannot export public keys for {0} key type and \ +#{1} purpose. +KeyczarTool.CannotExportPubKey=Imposs\u00edvel exportar chaves p\u00fablicas do tipo {0} \ +e com objetivo {1}. +#KeyczarTool.FileExists=File {0} already exists +KeyczarTool.FileExists=Arquivo {0} j\u00e1 existe +#KeyczarTool.MissingVersion=Must specify a key version +KeyczarTool.MissingVersion=\u00c9 necess\u00e1rio especificar uma vers\u00e3o de chave +#KeyczarTool.UnableToDelete=Unable to delete revoked key file +KeyczarTool.UnableToDelete=Imposs\u00edvel deletar arquivo de chave revogada +#KeyczarTool.UnableToWrite=Unable to write to: {0} +KeyczarTool.UnableToWrite=Imposs\u00edvel escrever em: {0} +#KeyczarTool.MustDefineDestination=Must define a key set destination +KeyczarTool.MustDefineDestination=\u00c9 necess\u00e1rio definir destino do conjunto de \ +chaves + +#Flag.UnknownFlag=Unknown flag: {0} +Flag.UnknownFlag=Flag desconhecida: {0} +#Command.UnknownCommand=Unknown command: {0} +Command.UnknownCommand=Comando desconhecido: {0} + +# This is a multi-line usage message +# The output looks like the following when arguments are passed in +#Usage: "KeyczarTool command flags" +#Commands: create addkey pubkey promote demote revoke +#Flags: location name size status purpose destination version asymmetric crypter +#Command Usage: +#create --location=/path/to/keys --purpose=(crypt|sign) [--name="A name"] [--asymmetric=(dsa|rsa)] +# Creates a new, empty key set in the given location. +# This key set must have a purpose of either "crypt" or "sign" +# and may optionally be given a name. The optional asymmetric +# flag will generate a public key set of the given algorithm. +# The "dsa" asymmetric value is valid only for sets with "sign" purpose. +# with the given purpose. +#addkey --location=/path/to/keys [--status=(active|primary)] [--size=size] [--crypter=crypterLocation] +# Adds a new key to an existing key set. Optionally +# specify a status, which is active by default. Optionally +# specify a key size in bits. Also optionally specify the +# location of a set of crypting keys, which will be used to +# encrypt this key set. +#pubkey --location=/path/to/keys --destination=/destination +# Extracts public keys from a given key set and writes them +# to the destination. The "pubkey" command Only works for +# key sets that were created with the "--asymmetric" flag. +#promote --location=/path/to/keys --version=versionNumber +# Promotes the status of the given key version in the given +# location. Active keys are promoted to primary (which demotes +# any existing primary key to active). Keys scheduled for +# revocation are promoted to be active. +#demote --location=/path/to/keys --version=versionNumber +# Demotes the status of the given key version in the given +# location. Primary keys are demoted to active. Active keys +# are scheduled for revocation. +#revoke --location=/path/to/keys --version=versionNumber +# Revokes the key of the given version number. +# This key must have been scheduled for revocation by the +# promote command. WARNING: The key will be destroyed. +# +#Optional flags are in [brackets]. The notation (a|b|c) means "a", "b", and "c" +#are the valid choices + +KeyczarTool.Usage=Forma de utiliza\u00e7\u00e3o: \"KeyczarTool flags\"\n\ +Comandos: {0} {1} {2} {3} {4} {5}\n\ +Flags: {7} {8} {9} {10} {11} {12} {13} {14} {15}\n\ +Uso dos comandos:\n\ +{0} --{7}=/path/to/keys --{11}=(crypt|sign) \ +[--{8}=\"A name\"] [--{14}=(dsa|rsa)]\n\ +\tCria um conjunto de chaves novo e vazio no local informado.\n\ +\tO objetivo deste conjunto tem que ser "crypt" ou "sign"\n\ +\te um nome opcional pode ser escolhido. A flag opcional {14} \n\ +\tir\u00e1 gerar um conjunto de chaves p\u00fablicas do algoritmo dado.\n\ +\tO valor assim\u00e9trico "dsa" \u00e9 v\u00e1lido apenas para conjuntos do tipo "sign".\n\ +{1} --{7}=/path/to/keys [--{10}=(active|primary)] \ +[--{9}={9}] [--{15}=crypterLocation]\n\ +\tAdiciona uma nova chave a um conjunto existente. Opcionalmente\n\ +\tespecifica um status, ativo por padr\u00e3o. Opcionalmente\n\ +\tespecifica um tamanho de chave em bits. Tamb\u00e9m opcionalmente\n\ +\tespecifica a localiza\u00e7\u00e3o das chaves usadas para cifrar este\n\ +\tconjunto.\n\ +{2} --{7}=/path/to/keys --{12}=/destination\n\ +\tExtrai chaves p\u00fablicas de um conjunto e as escreve no\n\ +\tdestino. O comand "pubkey" funciona somente para conjuntos\n\ +\tcriados com a flag "--asymmetric".\n\ +{3} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tPromove o status da vers\u00e3o de chave dada no local \n\ +\tespecificado. Chaves ativas s\u00e3o promovidas para prim\u00e1rias \n\ +\t(rebaixando qualquer chave prim\u00e1ria existente para ativa). \n\ +\tChaves marcadas para revoga\u00e7\u00e3o s\u00e3o promovidas para ativas.\n\ +{4} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tRebaixa o status da vers\u00e3o de chave dada no local especificado.\n\ +\tChaves prim\u00e1rias s\u00e3o rebaixadas para ativas. Chaves ativas\n\ +\ts\u00e3o marcadas para revoga\u00e7\u00e3o.\n\ +{5} --{7}=/path/to/keys --{13}=versionNumber\n\ +\tRevoga a chave correspondente ao n\u00famero de vers\u00e3o informado.\n\ +\tEssa chave deve ter sido marcada para revoga\u00e7\u00e3o pelo \n\ +\tcomando "{4}". AVISO: a chave ser\u00e1 destru\u00edda.\n\n\ +Flags opcionais est\u00e3o em [colchetes]. A nota\u00e7\u00e3o (a|b|c) significa que "a", "b", and "c"\n\ +s\u00e3o escolhar v\u00e1lidas + + diff --git a/src/cz/cvut/keyczar/interfaces/.svn/all-wcprops b/src/cz/cvut/keyczar/interfaces/.svn/all-wcprops new file mode 100644 index 0000000..6f7d7a5 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/all-wcprops @@ -0,0 +1,47 @@ +K 25 +svn:wc:ra_dav:version-url +V 60 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces +END +EncryptedReader.java +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/EncryptedReader.java +END +DecryptingStream.java +K 25 +svn:wc:ra_dav:version-url +V 82 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/DecryptingStream.java +END +SigningStream.java +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/SigningStream.java +END +Stream.java +K 25 +svn:wc:ra_dav:version-url +V 72 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/Stream.java +END +KeyczarReader.java +K 25 +svn:wc:ra_dav:version-url +V 79 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/KeyczarReader.java +END +EncryptingStream.java +K 25 +svn:wc:ra_dav:version-url +V 82 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/EncryptingStream.java +END +VerifyingStream.java +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/interfaces/VerifyingStream.java +END diff --git a/src/cz/cvut/keyczar/interfaces/.svn/entries b/src/cz/cvut/keyczar/interfaces/.svn/entries new file mode 100644 index 0000000..58c68ab --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/entries @@ -0,0 +1,266 @@ +10 + +dir +412 +http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/interfaces +http://keyczar.googlecode.com/svn + + + +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + +8f3b247a-914b-0410-8f51-05e301831c82 + +EncryptedReader.java +file + + + + +2010-03-15T07:45:43.215856Z +4cc6a3ebcba34f39b860f6a10812893b +2008-08-06T00:47:06.677166Z +260 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +806 + +DecryptingStream.java +file + + + + +2010-03-15T07:45:43.216866Z +bbd6873895b7ad0d835eafdc89cab969 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +3001 + +SigningStream.java +file + + + + +2010-03-15T07:45:43.217861Z +0817bb551ffd09ce398fed0a60c14387 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +1726 + +Stream.java +file + + + + +2010-03-15T07:45:43.218857Z +53a1403873ab20216671a43bd4c46b27 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +789 + +KeyczarReader.java +file + + + + +2010-03-15T07:45:43.218857Z +88aff9edd082f31dfe0a756893660972 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +1503 + +EncryptingStream.java +file + + + + +2010-03-15T07:45:43.234980Z +2179616632a31a80c86480faf3098266 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +3021 + +VerifyingStream.java +file + + + + +2010-03-15T07:45:43.234980Z +83a83fffaaab52cb5d40905388327057 +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +1770 + diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/DecryptingStream.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/DecryptingStream.java.svn-base new file mode 100644 index 0000000..e2281bf --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/DecryptingStream.java.svn-base @@ -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.interfaces; + +import org.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Decrypting streams are able to decrypt and verify data which has been + * encrypted by {@link EncryptingStream} objects. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface DecryptingStream extends Stream { + + /** + * Returns a Verifying Stream able to verify signatures on ciphertext inputs + * to this Decrypting Stream + * + * @return A Verifying Stream associated with this stream + */ + VerifyingStream getVerifyingStream(); + + /** + * Initializes this stream for decryption. May consume some bytes of the + * input; typically to read an IV if any exists. This must be called before + * updateDecrypt() or doFinalDecrypt(). + * + * @param input The input containing any IV or other header data. + * @throws KeyczarException If there is any error initializing this Stream; + * typically this would be a Java JCE exception. + */ + void initDecrypt(ByteBuffer input) throws KeyczarException; + + /** + * Update with more input to decrypt. Write any decrypted output to the given + * output buffer. Some decrypted output may be buffered and not written out + * until the next call to updateDecrypt() or doFinalDecrypt(). + * + * @param input The input to decrypt. + * @param output The decrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int updateDecrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Do the final decrypt operation. Reads any remaining bytes from the input, + * decrypts them, and writes the plaintext to the output. + * + * @param input The input to decrypt. + * @param output The decrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int doFinalDecrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Returns the maximum length of the output given the input length. + * + * @param inputLen The input length + * @return The max lenght of the output given the input length + */ + int maxOutputSize(int inputLen); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptedReader.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptedReader.java.svn-base new file mode 100644 index 0000000..7444c0b --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptedReader.java.svn-base @@ -0,0 +1,26 @@ +/* + * 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.interfaces; + +/** + * Encrypted Readers are able to read encrypted key sets. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface EncryptedReader extends KeyczarReader { +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptingStream.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptingStream.java.svn-base new file mode 100644 index 0000000..4ecdd07 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/EncryptingStream.java.svn-base @@ -0,0 +1,86 @@ +/* + * 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.interfaces; + +import org.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Encrypting streams are able to encrypt and sign data. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface EncryptingStream extends Stream { + + /** + * Returns a Signing Stream able to sign ciphertexts produced by this + * EncryptingStream. + * + * @return A Signg Stream associated with this stream + */ + SigningStream getSigningStream() throws KeyczarException; + + /** + * Initializes this stream for encryption. May write some header material to + * the output, for example an IV. This must be called before + * updateEncrypt() or doFinalEncrypt(). + * + * @param output The output where any IV material will be written. + * @return The number of bytes written to the output. + * @throws KeyczarException If there is any error initializing this Stream; + * typically this would be a Java JCE exception. + */ + int initEncrypt(ByteBuffer output) throws KeyczarException; + + /** + * Update with more input to encrypt. Write any encrypted output to the given + * output buffer. Some encrypted output may be buffered and not written out + * until the next call to updateEncrypt() or doFinalEncrypt(). + * + * @param input The input to encrypt. + * @param output The encrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int updateEncrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Do the final encrypt operation. Reads any remaining bytes from the input, + * encrypts them, and writes the ciphertext to the output. + * + * @param input The input to encrypt. + * @param output The encrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int doFinalEncrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Given the length of an input, return the maximum possible length of + * the output (including headers, the actual ciphertext, and the signature). + * + * @param inputLen + * @return maximum length of output + */ + int maxOutputSize(int inputLen); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/KeyczarReader.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/KeyczarReader.java.svn-base new file mode 100644 index 0000000..b6e8236 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/KeyczarReader.java.svn-base @@ -0,0 +1,44 @@ +/* + * 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.interfaces; + +import org.keyczar.exceptions.KeyczarException; + +/** + * Abstract class for KeyczarReaders. Typically, these will read key files from + * disk, but may be implemented to read from arbitrary sources. + * + * @author steveweis@gmail.com (Steve Weis) + */ +public interface KeyczarReader { + /** + * Returns an input stream of a particular version of a key + * + * @param version The Version number of the key to read + * @return A JSON string data representation of a Key + * @throws KeyczarException If an error occurs while attempting to read data, + * e.g. an IOException + */ + String getKey(int version) throws KeyczarException; + + /** + * @return A JSON string representation of KeyMetadata + * @throws KeyczarException If an error occurs while attempting to read data, + * e.g. an IOException + */ + String getMetadata() throws KeyczarException; +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/SigningStream.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/SigningStream.java.svn-base new file mode 100644 index 0000000..78c8844 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/SigningStream.java.svn-base @@ -0,0 +1,61 @@ +/* + * 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.interfaces; + +import org.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Signing streams are able to sign data + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface SigningStream extends Stream { + + /** + * Initializes this stream for signing. + * + * @throws KeyczarException If any Java JCE errors occur + */ + void initSign() throws KeyczarException; + + /** + * Update the signature with the given input. + * + * @param input The input to sign. + * @throws KeyczarException If any Java JCE errors occur + */ + void updateSign(ByteBuffer input) throws KeyczarException; + + /** + * Sign the updated input and output the signature in the given buffer. + * + * @param output The output where the signature will be written. + * @throws KeyczarException If any Java JCE errors occur or the output buffer + * is too small. + */ + void sign(ByteBuffer output) throws KeyczarException; + + /** + * Return the size of the signature or digest in number of bytes. + * + * @return size of signature in bytes + */ + int digestSize(); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/Stream.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/Stream.java.svn-base new file mode 100644 index 0000000..8dc9c95 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/Stream.java.svn-base @@ -0,0 +1,27 @@ +/* + * 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.interfaces; + +/** + * This is a placeholder class that is extended by various stream types. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface Stream { + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/.svn/text-base/VerifyingStream.java.svn-base b/src/cz/cvut/keyczar/interfaces/.svn/text-base/VerifyingStream.java.svn-base new file mode 100644 index 0000000..5ed6332 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/.svn/text-base/VerifyingStream.java.svn-base @@ -0,0 +1,59 @@ +/* + * 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.interfaces; + +import org.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Verifying Streams are able to verify data that has been signed by + * {@link SigningStream} objects. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface VerifyingStream extends Stream { + /** + * @return The size of digests that this stream will verify. + */ + int digestSize(); + + /** + * Initialize this stream for verification. This must be called before + * updateVerify(). + * + * @throws KeyczarException If a Java JCE error occurs. + */ + void initVerify() throws KeyczarException; + + /** + * Update the data which has been signed. + * + * @param input Data which has been signed. + * @throws KeyczarException If a Java JCE error occurs. + */ + void updateVerify(ByteBuffer input) throws KeyczarException; + + /** + * Verify that the given signautre is a valid signautre on the updated data. + * @param signature The signature to verify + * @return Whether the given signature is valid. + * @throws KeyczarException If a Java JCE error occurs. + */ + boolean verify(ByteBuffer signature) throws KeyczarException; +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/DecryptingStream.java b/src/cz/cvut/keyczar/interfaces/DecryptingStream.java new file mode 100644 index 0000000..2873156 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/DecryptingStream.java @@ -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.interfaces; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Decrypting streams are able to decrypt and verify data which has been + * encrypted by {@link EncryptingStream} objects. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface DecryptingStream extends Stream { + + /** + * Returns a Verifying Stream able to verify signatures on ciphertext inputs + * to this Decrypting Stream + * + * @return A Verifying Stream associated with this stream + */ + VerifyingStream getVerifyingStream(); + + /** + * Initializes this stream for decryption. May consume some bytes of the + * input; typically to read an IV if any exists. This must be called before + * updateDecrypt() or doFinalDecrypt(). + * + * @param input The input containing any IV or other header data. + * @throws KeyczarException If there is any error initializing this Stream; + * typically this would be a Java JCE exception. + */ + void initDecrypt(ByteBuffer input) throws KeyczarException; + + /** + * Update with more input to decrypt. Write any decrypted output to the given + * output buffer. Some decrypted output may be buffered and not written out + * until the next call to updateDecrypt() or doFinalDecrypt(). + * + * @param input The input to decrypt. + * @param output The decrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int updateDecrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Do the final decrypt operation. Reads any remaining bytes from the input, + * decrypts them, and writes the plaintext to the output. + * + * @param input The input to decrypt. + * @param output The decrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int doFinalDecrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Returns the maximum length of the output given the input length. + * + * @param inputLen The input length + * @return The max lenght of the output given the input length + */ + int maxOutputSize(int inputLen); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/EncryptedReader.java b/src/cz/cvut/keyczar/interfaces/EncryptedReader.java new file mode 100644 index 0000000..d88d326 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/EncryptedReader.java @@ -0,0 +1,26 @@ +/* + * 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.interfaces; + +/** + * Encrypted Readers are able to read encrypted key sets. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface EncryptedReader extends KeyczarReader { +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/EncryptingStream.java b/src/cz/cvut/keyczar/interfaces/EncryptingStream.java new file mode 100644 index 0000000..521749f --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/EncryptingStream.java @@ -0,0 +1,86 @@ +/* + * 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.interfaces; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Encrypting streams are able to encrypt and sign data. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface EncryptingStream extends Stream { + + /** + * Returns a Signing Stream able to sign ciphertexts produced by this + * EncryptingStream. + * + * @return A Signg Stream associated with this stream + */ + SigningStream getSigningStream() throws KeyczarException; + + /** + * Initializes this stream for encryption. May write some header material to + * the output, for example an IV. This must be called before + * updateEncrypt() or doFinalEncrypt(). + * + * @param output The output where any IV material will be written. + * @return The number of bytes written to the output. + * @throws KeyczarException If there is any error initializing this Stream; + * typically this would be a Java JCE exception. + */ + int initEncrypt(ByteBuffer output) throws KeyczarException; + + /** + * Update with more input to encrypt. Write any encrypted output to the given + * output buffer. Some encrypted output may be buffered and not written out + * until the next call to updateEncrypt() or doFinalEncrypt(). + * + * @param input The input to encrypt. + * @param output The encrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int updateEncrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Do the final encrypt operation. Reads any remaining bytes from the input, + * encrypts them, and writes the ciphertext to the output. + * + * @param input The input to encrypt. + * @param output The encrypted output, if any. + * @return The number of bytes written to the output. + * @throws KeyczarException If a Java JCE error occurs or the output buffer + * is too small. + */ + int doFinalEncrypt(ByteBuffer input, ByteBuffer output) + throws KeyczarException; + + /** + * Given the length of an input, return the maximum possible length of + * the output (including headers, the actual ciphertext, and the signature). + * + * @param inputLen + * @return maximum length of output + */ + int maxOutputSize(int inputLen); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/KeyczarReader.java b/src/cz/cvut/keyczar/interfaces/KeyczarReader.java new file mode 100644 index 0000000..f1952bb --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/KeyczarReader.java @@ -0,0 +1,44 @@ +/* + * 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.interfaces; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +/** + * Abstract class for KeyczarReaders. Typically, these will read key files from + * disk, but may be implemented to read from arbitrary sources. + * + * @author steveweis@gmail.com (Steve Weis) + */ +public interface KeyczarReader { + /** + * Returns an input stream of a particular version of a key + * + * @param version The Version number of the key to read + * @return A JSON string data representation of a Key + * @throws KeyczarException If an error occurs while attempting to read data, + * e.g. an IOException + */ + String getKey(int version) throws KeyczarException; + + /** + * @return A JSON string representation of KeyMetadata + * @throws KeyczarException If an error occurs while attempting to read data, + * e.g. an IOException + */ + String getMetadata() throws KeyczarException; +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/SigningStream.java b/src/cz/cvut/keyczar/interfaces/SigningStream.java new file mode 100644 index 0000000..2103b07 --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/SigningStream.java @@ -0,0 +1,61 @@ +/* + * 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.interfaces; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Signing streams are able to sign data + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface SigningStream extends Stream { + + /** + * Initializes this stream for signing. + * + * @throws KeyczarException If any Java JCE errors occur + */ + void initSign() throws KeyczarException; + + /** + * Update the signature with the given input. + * + * @param input The input to sign. + * @throws KeyczarException If any Java JCE errors occur + */ + void updateSign(ByteBuffer input) throws KeyczarException; + + /** + * Sign the updated input and output the signature in the given buffer. + * + * @param output The output where the signature will be written. + * @throws KeyczarException If any Java JCE errors occur or the output buffer + * is too small. + */ + void sign(ByteBuffer output) throws KeyczarException; + + /** + * Return the size of the signature or digest in number of bytes. + * + * @return size of signature in bytes + */ + int digestSize(); +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/Stream.java b/src/cz/cvut/keyczar/interfaces/Stream.java new file mode 100644 index 0000000..ea27bdc --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/Stream.java @@ -0,0 +1,27 @@ +/* + * 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.interfaces; + +/** + * This is a placeholder class that is extended by various stream types. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface Stream { + +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/interfaces/VerifyingStream.java b/src/cz/cvut/keyczar/interfaces/VerifyingStream.java new file mode 100644 index 0000000..d04e6dd --- /dev/null +++ b/src/cz/cvut/keyczar/interfaces/VerifyingStream.java @@ -0,0 +1,59 @@ +/* + * 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.interfaces; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.nio.ByteBuffer; + +/** + * Verifying Streams are able to verify data that has been signed by + * {@link SigningStream} objects. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public interface VerifyingStream extends Stream { + /** + * @return The size of digests that this stream will verify. + */ + int digestSize(); + + /** + * Initialize this stream for verification. This must be called before + * updateVerify(). + * + * @throws KeyczarException If a Java JCE error occurs. + */ + void initVerify() throws KeyczarException; + + /** + * Update the data which has been signed. + * + * @param input Data which has been signed. + * @throws KeyczarException If a Java JCE error occurs. + */ + void updateVerify(ByteBuffer input) throws KeyczarException; + + /** + * Verify that the given signautre is a valid signautre on the updated data. + * @param signature The signature to verify + * @return Whether the given signature is valid. + * @throws KeyczarException If a Java JCE error occurs. + */ + boolean verify(ByteBuffer signature) throws KeyczarException; +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/jce/.svn/all-wcprops b/src/cz/cvut/keyczar/jce/.svn/all-wcprops new file mode 100644 index 0000000..c9c23d8 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/all-wcprops @@ -0,0 +1,41 @@ +K 25 +svn:wc:ra_dav:version-url +V 53 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce +END +EcCore.java +K 25 +svn:wc:ra_dav:version-url +V 65 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce/EcCore.java +END +EcPublicKeyImpl.java +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce/EcPublicKeyImpl.java +END +EcKeyPairGeneratorImpl.java +K 25 +svn:wc:ra_dav:version-url +V 81 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce/EcKeyPairGeneratorImpl.java +END +EcKeyFactoryImpl.java +K 25 +svn:wc:ra_dav:version-url +V 75 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce/EcKeyFactoryImpl.java +END +EcSignatureImpl.java +K 25 +svn:wc:ra_dav:version-url +V 74 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce/EcSignatureImpl.java +END +EcPrivateKeyImpl.java +K 25 +svn:wc:ra_dav:version-url +V 75 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/jce/EcPrivateKeyImpl.java +END diff --git a/src/cz/cvut/keyczar/jce/.svn/entries b/src/cz/cvut/keyczar/jce/.svn/entries new file mode 100644 index 0000000..fe95a36 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/entries @@ -0,0 +1,232 @@ +10 + +dir +412 +http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/jce +http://keyczar.googlecode.com/svn + + + +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + +8f3b247a-914b-0410-8f51-05e301831c82 + +EcCore.java +file + + + + +2010-03-15T07:45:43.401856Z +a00e82c0902e6b32b617a9f0e9abf645 +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + + + + + + + + +27654 + +EcPublicKeyImpl.java +file + + + + +2010-03-15T07:45:43.402856Z +82e7c7a24e5d11160a2442ab09894417 +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + + + + + + + + +2390 + +EcKeyPairGeneratorImpl.java +file + + + + +2010-03-15T07:45:43.402856Z +2fe6aed222557c35e50c3ef3f955cdad +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + + + + + + + + +1703 + +EcKeyFactoryImpl.java +file + + + + +2010-03-15T07:45:43.403857Z +a98e80f8eda705af2372be5d44af52c9 +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + + + + + + + + +5324 + +EcSignatureImpl.java +file + + + + +2010-03-15T07:45:43.403857Z +01a63c5642f48b5bbbc6beb2de45de40 +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + + + + + + + + +7405 + +EcPrivateKeyImpl.java +file + + + + +2010-03-15T07:45:43.430855Z +0fbebc4f05be4750e384bbf5d07a93b1 +2008-09-09T23:52:39.677179Z +304 +steveweis + + + + + + + + + + + + + + + + + + + + + +2480 + diff --git a/src/cz/cvut/keyczar/jce/.svn/text-base/EcCore.java.svn-base b/src/cz/cvut/keyczar/jce/.svn/text-base/EcCore.java.svn-base new file mode 100644 index 0000000..db0ceb8 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/text-base/EcCore.java.svn-base @@ -0,0 +1,688 @@ +/* + * 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.jce; + +import java.math.BigInteger; +import java.security.AccessController; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Provider; +import java.security.Security; +import java.security.Signature; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +/** + * This class implements the basic EC operations such as point addition and + * doubling and point multiplication. Only NSA Suite B / NIST curves are + * supported. + * + * Todo: + * - Add (more) comments - Performance optimizations - Cleanup ASN.1 code, + * possibly replace with own impl - ... + * + * References: + * + * [1] Software Implementation of the NIST Elliptic Curves Over Prime Fields, M. + * Brown et al. [2] Efficient elliptic curve exponentiation using mixed + * coordinates, H. Cohen et al. [3] SEC 1: Elliptic Curve Cryptography. [4] + * Guide to Elliptic Curve Cryptography, D. Hankerson et al., Springer. + * + * @author martclau@gmail.com + * + */ +public final class EcCore extends Provider { + + private static final long serialVersionUID = -1376116429660095993L; + + private static final String INFO = "Google Keyczar (EC key/parameter generation; EC signing)"; + + public static final String NAME = "GooKey"; + + @SuppressWarnings("unchecked") + public EcCore() { + super(NAME, 0.1, INFO); + AccessController.doPrivileged(new java.security.PrivilegedAction() { + public Object run() { + put("Signature.SHA1withECDSA", "org.keyczar.jce.EcSignatureImpl$SHA1"); + put("Alg.Alias.Signature.ECDSA", "SHA1withDSA"); + put("Signature.SHA256withECDSA", + "org.keyczar.jce.EcSignatureImpl$SHA256"); + put("Signature.SHA384withECDSA", + "org.keyczar.jce.EcSignatureImpl$SHA384"); + put("Signature.SHA512withECDSA", + "org.keyczar.jce.EcSignatureImpl$SHA512"); + put("KeyPairGenerator.EC", "org.keyczar.jce.EcKeyPairGeneratorImpl"); + put("KeyFactory.EC", "org.keyczar.jce.EcKeyFactoryImpl"); + put("Signature.SHA1withECDSA KeySize", "521"); + put("Signature.SHA1withECDSA ImplementedIn", "Software"); + put("Signature.SHA256withECDSA KeySize", "521"); + put("Signature.SHA256withECDSA ImplementedIn", "Software"); + put("Signature.SHA384withECDSA KeySize", "521"); + put("Signature.SHA384withECDSA ImplementedIn", "Software"); + put("Signature.SHA512withECDSA KeySize", "521"); + put("Signature.SHA512withECDSA ImplementedIn", "Software"); + put("KeyPairGenerator.EC ImplementedIn", "Software"); + put("KeyFactory.EC ImplementedIn", "Software"); + return null; + } + }); + } + + private static final ECParameterSpec P192 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp(new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16)), + new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16), + new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16)), + new ECPoint( + new BigInteger("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 16), + new BigInteger("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 16)), + new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 16), 1); + + private static final ECParameterSpec P224 = new ECParameterSpec( + new EllipticCurve(new ECFieldFp(new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", 16), + new BigInteger( + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 16)), + new ECPoint(new BigInteger( + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 16), + new BigInteger( + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 16), 1); + + private static final ECParameterSpec P256 = new ECParameterSpec( + new EllipticCurve(new ECFieldFp(new BigInteger( + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + 16)), new BigInteger( + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + 16), new BigInteger( + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + 16)), new ECPoint(new BigInteger( + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + 16), new BigInteger( + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + 16)), new BigInteger( + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 16), 1); + + private static final ECParameterSpec P384 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp( + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + 16), + new BigInteger( + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + 16)), + new ECPoint( + new BigInteger( + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + 16), + new BigInteger( + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 16), 1); + + private static final ECParameterSpec P521 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp( + new BigInteger( + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + 16)), + new BigInteger( + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + 16), + new BigInteger( + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + 16)), + new ECPoint( + new BigInteger( + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + 16), + new BigInteger( + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + 16)), + new BigInteger( + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 16), 1); + + public static final String EC_PARAMS_P192_OID = "1.2.840.10045.3.1.1"; + public static final String EC_PARAMS_P224_OID = "1.3.132.0.33"; + public static final String EC_PARAMS_P256_OID = "1.2.840.10045.3.1.7"; + public static final String EC_PARAMS_P384_OID = "1.3.132.0.34"; + public static final String EC_PARAMS_P521_OID = "1.3.132.0.35"; + + private static Map oidMap = new HashMap(); + private static Map paramsMap = new HashMap(); + private static Map friendlyNameMap = new HashMap(); + + static { + oidMap.put(EC_PARAMS_P192_OID, P192); + oidMap.put(EC_PARAMS_P224_OID, P224); + oidMap.put(EC_PARAMS_P256_OID, P256); + oidMap.put(EC_PARAMS_P384_OID, P384); + oidMap.put(EC_PARAMS_P521_OID, P521); + paramsMap.put(P192, EC_PARAMS_P192_OID); + paramsMap.put(P224, EC_PARAMS_P224_OID); + paramsMap.put(P256, EC_PARAMS_P256_OID); + paramsMap.put(P384, EC_PARAMS_P384_OID); + paramsMap.put(P521, EC_PARAMS_P521_OID); + friendlyNameMap.put(P192, "P-192"); + friendlyNameMap.put(P224, "P-224"); + friendlyNameMap.put(P256, "P-256"); + friendlyNameMap.put(P384, "P-384"); + friendlyNameMap.put(P521, "P-521"); + } + + public static ECParameterSpec getParams(String oid) { + ECParameterSpec params; + if ((params = oidMap.get(oid)) != null) return params; + throw new IllegalArgumentException("Unsupported EC parameters: " + oid); + } + + public static String getOID(ECParameterSpec params) { + String oid; + if ((oid = paramsMap.get(params)) != null) return oid; + throw new IllegalArgumentException("Unsupport EC parameters"); + } + + public static String getFriendlyName(ECParameterSpec params) { + String name; + if ((name = friendlyNameMap.get(params)) != null) return name; + throw new IllegalArgumentException("Unsupport EC parameters"); + } + + private static final BigInteger ZERO = BigInteger.ZERO; + private static final BigInteger ONE = BigInteger.ONE; + private static final BigInteger TWO = BigInteger.valueOf(2); + private static final BigInteger THREE = BigInteger.valueOf(3); + private static final BigInteger FOUR = BigInteger.valueOf(4); + private static final BigInteger EIGHT = BigInteger.valueOf(8); + + private static BigInteger[] doublePointA(BigInteger[] P, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + final BigInteger a = params.getCurve().getA(); + + if (P[0] == null || P[1] == null) return P; + + BigInteger d = (P[0].pow(2).multiply(THREE).add(a)).multiply(P[1] + .shiftLeft(1).modInverse(p)); + BigInteger[] R = new BigInteger[2]; + R[0] = d.pow(2).subtract(P[0].shiftLeft(1)).mod(p); + R[1] = d.multiply(P[0].subtract(R[0])).subtract(P[1]).mod(p); + + return R; + } + + private static BigInteger[] addPointsA(BigInteger[] P1, BigInteger[] P2, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + + if (P2[0] == null || P2[1] == null) return P1; + + if (P1[0] == null || P1[1] == null) return P2; + + BigInteger d = (P2[1].subtract(P1[1])).multiply((P2[0].subtract(P1[0])) + .modInverse(p)); + BigInteger[] R = new BigInteger[2]; + R[0] = d.pow(2).subtract(P1[0]).subtract(P2[0]).mod(p); + R[1] = d.multiply(P1[0].subtract(R[0])).subtract(P1[1]).mod(p); + + return R; + } + + private static BigInteger[] multiplyPointA(BigInteger[] P, BigInteger k, + ECParameterSpec params) { + BigInteger[] Q = new BigInteger[] {null, null}; + + for (int i = k.bitLength() - 1; i >= 0; i--) { + Q = doublePointA(Q, params); + if (k.testBit(i)) Q = addPointsA(Q, P, params); + } + + return Q; + } + + private static BigInteger[] doublePointJ(BigInteger[] P, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + BigInteger A, B, C, D; + + if (P[2].signum() == 0) // point at inf + return P; + + A = FOUR.multiply(P[0]).multiply(P[1].pow(2)).mod(p); + B = EIGHT.multiply(P[1].pow(4)).mod(p); + C = THREE.multiply(P[0].subtract(P[2].pow(2))).multiply( + P[0].add(P[2].pow(2))).mod(p); + D = C.pow(2).subtract(A.add(A)).mod(p); + + return new BigInteger[] { + D, C.multiply(A.subtract(D)).subtract(B).mod(p), + TWO.multiply(P[1]).multiply(P[2]).mod(p)}; + } + + private static BigInteger[] addPointsJA(BigInteger[] P1, BigInteger[] P2, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + BigInteger A, B, C, D; + BigInteger X3; + + if (P1[2].signum() == 0) // point at inf + return new BigInteger[] {P2[0], P2[1], ONE}; + + A = P2[0].multiply(P1[2].pow(2)).mod(p); + B = P2[1].multiply(P1[2].pow(3)).mod(p); + C = A.subtract(P1[0]).mod(p); + D = B.subtract(P1[1]).mod(p); + + X3 = D.pow(2) + .subtract(C.pow(3).add(TWO.multiply(P1[0]).multiply(C.pow(2)))).mod(p); + return new BigInteger[] { + X3, + D.multiply(P1[0].multiply(C.pow(2)).subtract(X3)).subtract( + P1[1].multiply(C.pow(3))).mod(p), P1[2].multiply(C).mod(p)}; + } + + // Binary NAF method for point multiplication + static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger k, + ECParameterSpec params) { + BigInteger h = THREE.multiply(k); + + BigInteger[] Pneg = new BigInteger[] {P[0], P[1].negate()}; + BigInteger[] R = new BigInteger[] {P[0], P[1], ONE}; + + int bitLen = h.bitLength(); + for (int i = bitLen - 2; i > 0; --i) { + R = doublePointJ(R, params); + if (h.testBit(i)) R = addPointsJA(R, P, params); + if (k.testBit(i)) R = addPointsJA(R, Pneg, params); + } + + // // + // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; + // toAffine(SS, params); + // BigInteger[] RR = multiplyPointA(P, k, params); + // if (!SS[0].equals(RR[0]) || !SS[1].equals(RR[1])) + // throw new RuntimeException("Internal mult error"); + // // + + return R; + } + + // Simultaneous multiple point multiplication, also known as Shamir’s trick + static BigInteger[] multiplyPoints(BigInteger[] P, BigInteger k, + BigInteger[] Q, BigInteger l, ECParameterSpec params) { + BigInteger[] PQ = addPointsA(P, Q, params); + BigInteger[] R = new BigInteger[] {null, null, ZERO}; + + int max = Math.max(k.bitLength(), l.bitLength()); + for (int i = max - 1; i >= 0; --i) { + R = doublePointJ(R, params); + if (k.testBit(i)) { + if (l.testBit(i)) + R = addPointsJA(R, PQ, params); + else + R = addPointsJA(R, P, params); + } else if (l.testBit(i)) R = addPointsJA(R, Q, params); + } + + // // + // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; + // toAffine(SS, params); + // BigInteger[] AA = multiplyPointA(P, k, params); + // BigInteger[] BB = multiplyPointA(Q, l, params); + // BigInteger[] AB = addPointsA(AA, BB, params); + // if (!SS[0].equals(AB[0]) || !SS[1].equals(AB[1])) + // throw new RuntimeException("Internal mult error"); + // // + + return R; + } + + // SEC 1, 2.3.5 + static byte[] fieldElemToBytes(BigInteger a, ECParameterSpec params) { + int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; + byte[] bytes = a.toByteArray(); + if (len < bytes.length) { + byte[] tmp = new byte[len]; + System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); + return tmp; + } else if (len > bytes.length) { + byte[] tmp = new byte[len]; + System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); + return tmp; + } + return bytes; + } + + static int fieldElemToBytes(BigInteger a, ECParameterSpec params, + byte[] data, int off) { + int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; + byte[] bytes = a.toByteArray(); + if (len < bytes.length) { + System.arraycopy(bytes, bytes.length - len, data, off, len); + return len; + } else if (len > bytes.length) { + System.arraycopy(bytes, 0, data, len - bytes.length + off, bytes.length); + return len; + } + System.arraycopy(bytes, 0, data, off, bytes.length); + return bytes.length; + } + + // SEC 1, 2.3.3 + static byte[] ecPointToBytes(ECPoint a, ECParameterSpec params) { + byte[] fe1 = fieldElemToBytes(a.getAffineX(), params); + byte[] fe2 = fieldElemToBytes(a.getAffineY(), params); + byte[] bytes = new byte[1 + fe1.length + fe2.length]; + bytes[0] = 0x04; + System.arraycopy(fe1, 0, bytes, 1, fe1.length); + System.arraycopy(fe2, 0, bytes, 1 + fe1.length, fe2.length); + return bytes; + } + + // SEC 1, 2.3.4 + static ECPoint bytesToECPoint(byte[] bytes, ECParameterSpec params) { + switch (bytes[0]) { + case 0x00: // point at inf + throw new IllegalArgumentException( + "Point at infinity is not a valid argument"); + case 0x02: // point compression + case 0x03: + throw new UnsupportedOperationException( + "Point compression is not supported"); + case 0x04: + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + byte[] fe = new byte[(p.bitLength() + 7) / 8]; + System.arraycopy(bytes, 1, fe, 0, fe.length); + BigInteger x = new BigInteger(1, fe); + System.arraycopy(bytes, 1 + fe.length, fe, 0, fe.length); + return new ECPoint(x, new BigInteger(1, fe)); + default: + throw new IllegalArgumentException("Invalid point encoding"); + } + } + + // Convert Jacobian point to affine + static void toAffine(BigInteger[] P, ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); + P[1] = P[1].multiply(P[2].pow(3).modInverse(p)).mod(p); + } + + static void toAffineX(BigInteger[] P, ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); + } + + static BigInteger[] internalPoint(ECPoint P) { + return new BigInteger[] {P.getAffineX(), P.getAffineY()}; + } + + // private static void printPerf(String msg, long start, long stop) { + // String unit = "ms"; + // long diff = stop - start; + // if (diff > 1000) { + // diff /= 1000; + // unit = "s"; + // } + // System.out.printf("%s: %d %s\n", msg, diff, unit); + // } + + public static void main(String[] args) throws Exception { + + Security.insertProviderAt(new EcCore(), 0); + + // ---- + // Test primitives + // ---- + + // GooKey EC private key, 256 bit + // Private value: + // a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2 + // Parameters: P-256 (1.2.840.10045.3.1.7) + // GooKey EC public key, 256 bit + // Public value (x coordinate): + // 86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c + // Public value (y coordinate): + // ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6 + // Parameters: P-256 (1.2.840.10045.3.1.7) + // GooKey EC private key, 256 bit + // Private value: + // b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022 + // Parameters: P-256 (1.2.840.10045.3.1.7) + // GooKey EC public key, 256 bit + // Public value (x coordinate): + // 61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1 + // Public value (y coordinate): + // 3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705 + // Parameters: P-256 (1.2.840.10045.3.1.7) + + // P = kG + BigInteger k = new BigInteger( + "a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2", 16); + BigInteger[] P = new BigInteger[] { + new BigInteger( + "86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c", + 16), + new BigInteger( + "ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6", + 16), ONE}; + + // Q = lG + BigInteger l = new BigInteger( + "b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022", 16); + BigInteger[] Q = new BigInteger[] { + new BigInteger( + "61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1", + 16), + new BigInteger( + "3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705", + 16), ONE}; + + // Known answer for P+Q + BigInteger[] kat1 = new BigInteger[] { + new BigInteger( + "bc7adb05bca2460bbfeb4e0f88b61c384ea88ed3fd56017938ac2582513d4220", + 16), + new BigInteger( + "a640a43df2e9df39eec11445b7e3f7835b743ef1ac4a83cecb570a060b3f1c6c", + 16)}; + + BigInteger[] R = addPointsA(P, Q, P256); + if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) + throw new RuntimeException("kat1 failed"); + + R = addPointsJA(P, Q, P256); + toAffine(R, P256); + if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) + throw new RuntimeException("kat1 failed"); + + + // Known answer for Q+Q + BigInteger[] kat2 = new BigInteger[] { + new BigInteger( + "c79d7f9100c14a70f0bb9bdce59654abf99e10d1ac5afc1a0f1b6bc650d6429b", + 16), + new BigInteger( + "6856814e47adce42bc0d7c3bef308c6c737c418ed093effb31e21f53c7735c97", + 16)}; + + R = doublePointA(P, P256); + if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) + throw new RuntimeException("kat2 failed"); + + R = doublePointJ(P, P256); + toAffine(R, P256); + if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) + throw new RuntimeException("kat2 failed"); + + // Known answer for kP + BigInteger[] kat3 = new BigInteger[] { + new BigInteger( + "97a82a834b9e6b50660ae30d43dac9b200276e8bcd2ed6a6593048de09276d1a", + 16), + new BigInteger( + "30a9590a01066d8ef54a910afcc8648dbc7400c01750af423ce95547f2154d56", + 16)}; + + R = multiplyPointA(P, k, P256); + if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) + throw new RuntimeException("kat3 failed"); + + R = multiplyPoint(P, k, P256); + toAffine(R, P256); + if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) + throw new RuntimeException("kat3 failed"); + + // Known answer for kP+lQ + BigInteger[] kat4 = new BigInteger[] { + new BigInteger( + "6fd51be5cf3d6a6bcb62594bbe41ccf549b37d8fefff6e293a5bea0836efcfc6", + 16), + new BigInteger( + "9bc21a930137aa3814908974c431e4545a05dce61321253c337f3883129c42ca", + 16)}; + + BigInteger[] RR = multiplyPointA(Q, l, P256); + R = addPointsA(R, RR, P256); + if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) + throw new RuntimeException("kat4 failed"); + + R = multiplyPoints(P, k, Q, l, P256); + toAffine(R, P256); + if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) + throw new RuntimeException("kat4 failed"); + + // ---- + // Test ECDSA in various combinations + // ---- + + Provider gooProv = Security.getProvider("GooKey"); + Provider nssProv = Security.getProvider("SunPKCS11-NSS"); + + // Number of iterations: trust me, this is a (stress) good test + // and does provoke bugs in a fuzzing way. + int iter = 50; + + // Iterate over all key lengths and signature schemes. + int[] keyLengths = {192, 224, 256, 384, 521}; + String[] ecdsas = { + "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", + "SHA512withECDSA"}; + for (int s = 0; s < ecdsas.length; s++) { + System.out.println("Signature scheme " + ecdsas[s]); + for (int i = 0; i < keyLengths.length; i++) { + System.out.print("Testing P-" + keyLengths[i] + ": "); + for (int n = 0; n < iter; n++) { + System.out.print("."); + + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", gooProv); + kpGen.initialize(keyLengths[i]); + KeyPair ecKeyPair = kpGen.generateKeyPair(); + + ECPrivateKey ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); + byte[] tmp = ecPrivKey.getEncoded(); + KeyFactory keyFab = KeyFactory.getInstance("EC", gooProv); + keyFab.generatePrivate(new PKCS8EncodedKeySpec(tmp)); + ECPrivateKeySpec ecPrivSpec = new ECPrivateKeySpec(ecPrivKey.getS(), + ecPrivKey.getParams()); + keyFab.generatePrivate(ecPrivSpec); + + ECPublicKey ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); + tmp = ecPubKey.getEncoded(); // dont modify tmp now - is used below + keyFab.generatePublic(new X509EncodedKeySpec(tmp)); + ECPublicKeySpec ecPubSpec = new ECPublicKeySpec(ecPubKey.getW(), + ecPubKey.getParams()); + keyFab.generatePublic(ecPubSpec); + + Signature ecdsa = Signature.getInstance(ecdsas[s], gooProv); + ecdsa.initSign(ecPrivKey); + ecdsa.update(tmp); + byte[] sig = ecdsa.sign(); + ecdsa.initVerify(ecPubKey); + ecdsa.update(tmp); + if (!ecdsa.verify(sig)) + throw new RuntimeException("Signature not verified: " + + keyLengths[i]); + + // Cross verify using NSS if present + if (nssProv != null) { + keyFab = KeyFactory.getInstance("EC", nssProv); + + // For some reason NSS doesnt seem to work for P-192 and P-224?! + if (keyLengths[i] == 192 || keyLengths[i] == 224) continue; + + ECPrivateKey nssPrivKey = (ECPrivateKey) keyFab + .generatePrivate(new PKCS8EncodedKeySpec(ecPrivKey.getEncoded())); + ECPublicKey nssPubKey = (ECPublicKey) keyFab + .generatePublic(new X509EncodedKeySpec(ecPubKey.getEncoded())); + + ecdsa = Signature.getInstance(ecdsas[s], nssProv); + ecdsa.initVerify(nssPubKey); + ecdsa.update(tmp); + if (!ecdsa.verify(sig)) + throw new RuntimeException("Signature not verified 2: " + + keyLengths[i]); + + ecdsa.initSign(nssPrivKey); + ecdsa.update(tmp); + sig = ecdsa.sign(); + ecdsa = Signature.getInstance(ecdsas[s], gooProv); + ecdsa.initVerify(ecPubKey); + ecdsa.update(tmp); + if (!ecdsa.verify(sig)) + throw new RuntimeException("Signature not verified 3: " + + keyLengths[i]); + } + } + System.out.println(" done"); + } + } + + // Test Keyczar integration + // Signer ecdsaSigner = new Signer("c:\\temp\\eckeyset"); + // String tbs = "Sign this"; + // String sig = ecdsaSigner.sign(tbs); + // if (ecdsaSigner.verify(sig, tbs)) + // System.out.println("Keyczar EC OK"); + // else + // System.out.println("Keyczar EC not OK"); + } +} diff --git a/src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyFactoryImpl.java.svn-base b/src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyFactoryImpl.java.svn-base new file mode 100644 index 0000000..4f99749 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyFactoryImpl.java.svn-base @@ -0,0 +1,142 @@ +package org.keyczar.jce; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactorySpi; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import org.mozilla.jss.asn1.ASN1Value; +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; + +/** + * This class implements an EC key factory capable of generating: + *
    + *
  • Private keys from PKCS#8 and ECPrivateKeySpec + *
  • Public keys from X.509 and ECPublicKeySpec + *
+ * + * @author martclau@gmail.com + * + */ +public class EcKeyFactoryImpl extends KeyFactorySpi { + + public EcKeyFactoryImpl() { + super(); + } + + // "Translate" e.g. {1 2 840 10045 2 1} to 1.2.840.10045.2.1 + private static String decodeOID(ASN1Value val) throws Exception { + OBJECT_IDENTIFIER.Template ot = new OBJECT_IDENTIFIER.Template(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + val.encode(baos); + OBJECT_IDENTIFIER o = (OBJECT_IDENTIFIER) ot + .decode(new ByteArrayInputStream(baos.toByteArray())); + StringBuffer sb = new StringBuffer(); + long[] nums = o.getNumbers(); + for (int i = 0; i < nums.length - 1; i++) { + sb.append(nums[i] + "."); + } + sb.append(nums[nums.length - 1]); + return sb.toString(); + } + + @Override + protected PrivateKey engineGeneratePrivate(KeySpec keySpec) + throws InvalidKeySpecException { + if (keySpec instanceof PKCS8EncodedKeySpec) { + try { + PrivateKeyInfo.Template pkiTemp = new PrivateKeyInfo.Template(); + byte[] data = ((PKCS8EncodedKeySpec) keySpec).getEncoded(); + PrivateKeyInfo pki = (PrivateKeyInfo) pkiTemp + .decode(new ByteArrayInputStream(data)); + + AlgorithmIdentifier algid = pki.getPrivateKeyAlgorithm(); + if (!algid.getOID().toString().equals("{1 2 840 10045 2 1}")) // ecPublicKey + throw new IllegalArgumentException("Unsupported key"); + + ECParameterSpec params = EcCore.getParams(decodeOID(algid + .getParameters())); + + SEQUENCE.Template foo = new SEQUENCE.Template(); + foo.addElement(new INTEGER.Template()); + foo.addElement(new OCTET_STRING.Template()); + + SEQUENCE ecPrivateKey = (SEQUENCE) foo.decode(new ByteArrayInputStream( + pki.getEncoded())); + OCTET_STRING arrhh = (OCTET_STRING) ecPrivateKey.elementAt(1); + return new EcPrivateKeyImpl(new BigInteger(1, arrhh.toByteArray()), + params); + } catch (Exception e) { + throw new InvalidKeySpecException("Invalid key encoding", e); + } + } + if (keySpec instanceof ECPrivateKeySpec) { + ECPrivateKeySpec spec = (ECPrivateKeySpec) keySpec; + return new EcPrivateKeyImpl(spec.getS(), spec.getParams()); + } + throw new IllegalArgumentException("Type of KeySpec is not supported"); + } + + @Override + protected PublicKey engineGeneratePublic(KeySpec keySpec) + throws InvalidKeySpecException { + if (keySpec instanceof X509EncodedKeySpec) { + try { + SEQUENCE.Template outer = new SEQUENCE.Template(); + outer.addElement(AlgorithmIdentifier.getTemplate()); + outer.addElement(BIT_STRING.getTemplate()); + + byte[] data = ((X509EncodedKeySpec) keySpec).getEncoded(); + SEQUENCE ecPublicKey = (SEQUENCE) outer + .decode(new ByteArrayInputStream(data)); + + AlgorithmIdentifier algid = (AlgorithmIdentifier) ecPublicKey + .elementAt(0); + if (!algid.getOID().toString().equals("{1 2 840 10045 2 1}")) // ecPublicKey + throw new IllegalArgumentException("Unsupported key"); + + ECParameterSpec params = EcCore.getParams(decodeOID(algid + .getParameters())); + + BIT_STRING bs = (BIT_STRING) ecPublicKey.elementAt(1); + data = bs.getBits(); + + return new EcPublicKeyImpl(EcCore.bytesToECPoint(data, params), params); + } catch (Exception e) { + throw new InvalidKeySpecException("Invalid key encoding", e); + } + } + if (keySpec instanceof ECPublicKeySpec) { + ECPublicKeySpec spec = (ECPublicKeySpec) keySpec; + return new EcPublicKeyImpl(spec.getW(), spec.getParams()); + } + throw new IllegalArgumentException("Type of KeySpec is not supported"); + } + + @Override + protected T engineGetKeySpec(Key key, Class keySpec) { + throw new UnsupportedOperationException("Method not supported"); + } + + @Override + protected Key engineTranslateKey(Key key) { + throw new UnsupportedOperationException("Method not supported"); + } +} diff --git a/src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyPairGeneratorImpl.java.svn-base b/src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyPairGeneratorImpl.java.svn-base new file mode 100644 index 0000000..3c6b517 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/text-base/EcKeyPairGeneratorImpl.java.svn-base @@ -0,0 +1,63 @@ +package org.keyczar.jce; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGeneratorSpi; +import java.security.SecureRandom; +import java.security.spec.ECParameterSpec; + +/** + * This class implements an EC keypair generator. + * + * @author martclau@gmail.com + * + */ +public class EcKeyPairGeneratorImpl extends KeyPairGeneratorSpi { + + private ECParameterSpec params; + + public EcKeyPairGeneratorImpl() { + super(); + } + + // SEC 1, 3.2.1 + @Override + public KeyPair generateKeyPair() { + final BigInteger n = params.getOrder(); + BigInteger S = BigInteger.ZERO; + + do { + S = new BigInteger(n.bitLength(), new SecureRandom()).mod(n); + } while (S.signum() == 0); + + BigInteger[] G = EcCore.internalPoint(params.getGenerator()); + BigInteger[] Q = EcCore.multiplyPoint(G, S, params); + EcCore.toAffine(Q, params); + + return new KeyPair(new EcPublicKeyImpl(Q[0], Q[1], params), + new EcPrivateKeyImpl(S, params)); + } + + @Override + public void initialize(int keysize, SecureRandom random) { + switch (keysize) { + case 192: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P192_OID); + break; + case 224: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P224_OID); + break; + case 256: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P256_OID); + break; + case 384: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P384_OID); + break; + case 521: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P521_OID); + break; + default: + throw new IllegalArgumentException("Unsupported keysize: " + keysize); + } + } +} diff --git a/src/cz/cvut/keyczar/jce/.svn/text-base/EcPrivateKeyImpl.java.svn-base b/src/cz/cvut/keyczar/jce/.svn/text-base/EcPrivateKeyImpl.java.svn-base new file mode 100644 index 0000000..cd95769 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/text-base/EcPrivateKeyImpl.java.svn-base @@ -0,0 +1,92 @@ +package org.keyczar.jce; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECParameterSpec; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; + +/** + * This class implements EC private keys. + * + * @author martclau@gmail.com + * + */ +public class EcPrivateKeyImpl implements ECPrivateKey { + + private static final long serialVersionUID = -237229630170977756L; + + private BigInteger S; + private ECParameterSpec params; + + EcPrivateKeyImpl(BigInteger S, ECParameterSpec params) { + this.S = S; + this.params = params; + } + + public BigInteger getS() { + return S; + } + + public String getAlgorithm() { + return "EC"; + } + + public byte[] getEncoded() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + SEQUENCE privateKeyInfo = new SEQUENCE(); + privateKeyInfo.addElement(new INTEGER(0)); + + SEQUENCE algid = new SEQUENCE(); + algid.addElement(new OBJECT_IDENTIFIER("1.2.840.10045.2.1")); + algid.addElement(new OBJECT_IDENTIFIER(EcCore.getOID(params))); + privateKeyInfo.addElement(algid); + + SEQUENCE ecPrivateKey = new SEQUENCE(); + ecPrivateKey.addElement(new INTEGER(1)); + ecPrivateKey + .addElement(new OCTET_STRING(EcCore.fieldElemToBytes(S, params))); + + try { + ecPrivateKey.encode(baos); + } catch (IOException ioe) { + throw new RuntimeException("Internal ASN.1 encoding error", ioe); + } + + privateKeyInfo.addElement(new OCTET_STRING(baos.toByteArray())); + + baos.reset(); + try { + privateKeyInfo.encode(baos); + } catch (IOException ioe) { + throw new RuntimeException("Internal ASN.1 encoding error", ioe); + } + + return baos.toByteArray(); + } + + public String getFormat() { + return "PKCS#8"; + } + + public ECParameterSpec getParams() { + return params; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + int bitlen = params.getOrder().bitLength(); + sb.append("GooKey EC private key, " + bitlen + " bit\n"); + sb.append(" Private value: " + S.toString(16) + "\n"); + sb.append(" Parameters: " + EcCore.getFriendlyName(params) + " (" + + EcCore.getOID(params) + ")"); + return sb.toString(); + } +} diff --git a/src/cz/cvut/keyczar/jce/.svn/text-base/EcPublicKeyImpl.java.svn-base b/src/cz/cvut/keyczar/jce/.svn/text-base/EcPublicKeyImpl.java.svn-base new file mode 100644 index 0000000..913d361 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/text-base/EcPublicKeyImpl.java.svn-base @@ -0,0 +1,89 @@ +package org.keyczar.jce; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; + +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.SEQUENCE; + +/** + * This class implements EC public keys. + * + * @author martclau@gmail.com + * + */ +public class EcPublicKeyImpl implements ECPublicKey { + + private static final long serialVersionUID = -2181476758766123036L; + + private BigInteger x; + private BigInteger y; + ECParameterSpec params; + + EcPublicKeyImpl(BigInteger x, BigInteger y, ECParameterSpec params) { + this.x = x; + this.y = y; + this.params = params; + } + + EcPublicKeyImpl(ECPoint W, ECParameterSpec params) { + this.x = W.getAffineX(); + this.y = W.getAffineY(); + this.params = params; + } + + + public ECPoint getW() { + return new ECPoint(x, y); + } + + public String getAlgorithm() { + return "EC"; + } + + public byte[] getEncoded() { + SEQUENCE outer = new SEQUENCE(); + + SEQUENCE algid = new SEQUENCE(); + algid.addElement(new OBJECT_IDENTIFIER("1.2.840.10045.2.1")); + algid.addElement(new OBJECT_IDENTIFIER(EcCore.getOID(params))); + outer.addElement(algid); + + BIT_STRING ecPublivKey = new BIT_STRING(EcCore.ecPointToBytes(getW(), + params), 0); + outer.addElement(ecPublivKey); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + outer.encode(baos); + } catch (IOException ioe) { + throw new RuntimeException("Internal ASN.1 encoding error", ioe); + } + return baos.toByteArray(); + } + + public String getFormat() { + return "X.509"; + } + + public ECParameterSpec getParams() { + return params; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + int bitlen = params.getOrder().bitLength(); + sb.append("GooKey EC public key, " + bitlen + " bit\n"); + sb.append(" Public value (x coordinate): " + x.toString(16) + "\n"); + sb.append(" Public value (y coordinate): " + y.toString(16) + "\n"); + sb.append(" Parameters: " + EcCore.getFriendlyName(params) + " (" + + EcCore.getOID(params) + ")"); + return sb.toString(); + } +} diff --git a/src/cz/cvut/keyczar/jce/.svn/text-base/EcSignatureImpl.java.svn-base b/src/cz/cvut/keyczar/jce/.svn/text-base/EcSignatureImpl.java.svn-base new file mode 100644 index 0000000..23b3f83 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/.svn/text-base/EcSignatureImpl.java.svn-base @@ -0,0 +1,225 @@ +package org.keyczar.jce; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.SignatureSpi; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; + +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.SEQUENCE; + +/** + * This class implements the ECDSA signature scheme. + * + * From + * http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html: + * "The ECDSA signature algorithms as defined in ANSI X9.62." This means that an + * ECDSA signature is encoded as SEQUENCE { INTEGER, INTEGER } in ASN.1. + * + * @author martclau@gmail.com + * + */ +public class EcSignatureImpl extends SignatureSpi { + + MessageDigest hash; + ECPrivateKey privateKey; + ECPublicKey publicKey; + ECParameterSpec params; + + private EcSignatureImpl(String digestName) throws NoSuchAlgorithmException { + super(); + hash = MessageDigest.getInstance(digestName); + } + + @Override + protected Object engineGetParameter(String param) + throws InvalidParameterException { + throw new UnsupportedOperationException(); + } + + @Override + protected void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException { + if (!(privateKey instanceof ECPrivateKey)) + throw new InvalidKeyException("Unsupported key type"); + this.privateKey = (ECPrivateKey) privateKey; + this.params = this.privateKey.getParams(); + } + + @Override + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException { + if (!(publicKey instanceof ECPublicKey)) + throw new InvalidKeyException("Unsupported key type"); + this.publicKey = (ECPublicKey) publicKey; + this.params = this.publicKey.getParams(); + } + + @Override + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + throw new UnsupportedOperationException(); + } + + // SEC 1, 4.1.3 + @Override + protected byte[] engineSign() throws SignatureException { + BigInteger e = trimHash(hash.digest(), params); + BigInteger r = BigInteger.ZERO; + BigInteger s = BigInteger.ZERO; + + do { + BigInteger n = params.getOrder(); + BigInteger k = BigInteger.ZERO; + + do { + do { + k = new BigInteger(n.bitLength(), new SecureRandom()).mod(n); + } while (k.signum() == 0); + + BigInteger[] G = EcCore.internalPoint(params.getGenerator()); + BigInteger[] R = EcCore.multiplyPoint(G, k, params); + EcCore.toAffineX(R, params); + + r = R[0].mod(n); + } while (r.signum() == 0); + + s = k.modInverse(n).multiply(e.add(privateKey.getS().multiply(r))).mod(n); + + } while (s.signum() == 0); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + // SEQUENCE seq = new SEQUENCE(); + // seq.addElement(new INTEGER(EcCore.fieldElemToBytes(r, params))); + // seq.addElement(new INTEGER(EcCore.fieldElemToBytes(s, params))); + + // Sigh, another work around... + SEQUENCE seq = new SEQUENCE(); + + byte[] tmp = new byte[2 + (((ECFieldFp) params.getCurve().getField()) + .getFieldSize() + 7) / 8]; + tmp[0] = 0x02; + tmp[1] = (byte) EcCore.fieldElemToBytes(r, params, tmp, 2); + seq.addElement(new ANY(tmp)); + + tmp = new byte[2 + (((ECFieldFp) params.getCurve().getField()) + .getFieldSize() + 7) / 8]; + tmp[0] = 0x02; + tmp[1] = (byte) EcCore.fieldElemToBytes(s, params, tmp, 2); + seq.addElement(new ANY(tmp)); + + seq.encode(baos); + } catch (Exception ex) { + throw new SignatureException("Internal ASN.1 encoding error", ex); + } + + return baos.toByteArray(); + } + + @Override + protected void engineUpdate(byte b) { + hash.update(b); + } + + @Override + protected void engineUpdate(byte[] b, int off, int len) { + hash.update(b, off, len); + + } + + // SEC 1, 4.1.1 + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + try { + // SEQUENCE.Template seqtemp = new SEQUENCE.Template(); + // seqtemp.addElement( INTEGER.getTemplate() ); + // seqtemp.addElement( INTEGER.getTemplate() ); + // SEQUENCE seq = (SEQUENCE)seqtemp.decode(new + // ByteArrayInputStream(sigBytes)); + // BigInteger r = (BigInteger)seq.elementAt(0); + // BigInteger s = (BigInteger)seq.elementAt(1); + + // Arrggg, the following is a work around: JSS creates BigIntegers + // using BigInteger(byte[]) which, if the "sign" bit is set, + // create negative numbers. This, of course, destroys signature + // verification. In this case they should have used the + // BigInteger(1,byte[]) + // constructor. Anyway, we do it manually... + SEQUENCE.Template foo = new SEQUENCE.Template(); + foo.addElement(ANY.getTemplate()); + foo.addElement(ANY.getTemplate()); + SEQUENCE bar = (SEQUENCE) foo.decode(new ByteArrayInputStream(sigBytes)); + BigInteger r = new BigInteger(1, ((ANY) bar.elementAt(0)).getContents()); + BigInteger s = new BigInteger(1, ((ANY) bar.elementAt(1)).getContents()); + + BigInteger e = trimHash(hash.digest(), params); + BigInteger n = params.getOrder(); + + // r in [1,n-1] + if (r.compareTo(BigInteger.ONE) < 0 || r.compareTo(n) >= 0) return false; + + // s in [1,n-1] + if (s.compareTo(BigInteger.ONE) < 0 || s.compareTo(n) >= 0) return false; + + BigInteger c = s.modInverse(n); + BigInteger u1 = e.multiply(c).mod(n); + BigInteger u2 = r.multiply(c).mod(n); + + BigInteger[] G = EcCore.internalPoint(params.getGenerator()); + BigInteger[] W = EcCore.internalPoint(publicKey.getW()); + BigInteger[] R1 = EcCore.multiplyPoints(G, u1, W, u2, params); + EcCore.toAffineX(R1, params); + + BigInteger v = R1[0].mod(n); + + return v.equals(r); + } catch (Exception e) { + throw new SignatureException("Internal error", e); + } + } + + private static BigInteger trimHash(final byte[] hash, ECParameterSpec params) { + BigInteger e = new BigInteger(1, hash); + int orderLength = params.getOrder().bitLength(); + int hashLength = 8 * hash.length; + if (orderLength < hashLength) e = e.shiftRight(hashLength - orderLength); + return e; + } + + public static class SHA1 extends EcSignatureImpl { + public SHA1() throws NoSuchAlgorithmException { + super("SHA-1"); + } + } + + public static class SHA256 extends EcSignatureImpl { + public SHA256() throws NoSuchAlgorithmException { + super("SHA-256"); + } + } + + public static class SHA384 extends EcSignatureImpl { + public SHA384() throws NoSuchAlgorithmException { + super("SHA-384"); + } + } + + public static class SHA512 extends EcSignatureImpl { + public SHA512() throws NoSuchAlgorithmException { + super("SHA-512"); + } + } +} diff --git a/src/cz/cvut/keyczar/jce/EcCore.java b/src/cz/cvut/keyczar/jce/EcCore.java new file mode 100644 index 0000000..5e91da5 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/EcCore.java @@ -0,0 +1,688 @@ +/* + * 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.jce; + +import java.math.BigInteger; +import java.security.AccessController; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Provider; +import java.security.Security; +import java.security.Signature; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +/** + * This class implements the basic EC operations such as point addition and + * doubling and point multiplication. Only NSA Suite B / NIST curves are + * supported. + * + * Todo: + * - Add (more) comments - Performance optimizations - Cleanup ASN.1 code, + * possibly replace with own impl - ... + * + * References: + * + * [1] Software Implementation of the NIST Elliptic Curves Over Prime Fields, M. + * Brown et al. [2] Efficient elliptic curve exponentiation using mixed + * coordinates, H. Cohen et al. [3] SEC 1: Elliptic Curve Cryptography. [4] + * Guide to Elliptic Curve Cryptography, D. Hankerson et al., Springer. + * + * @author martclau@gmail.com + * + */ +public final class EcCore extends Provider { + + private static final long serialVersionUID = -1376116429660095993L; + + private static final String INFO = "Google Keyczar (EC key/parameter generation; EC signing)"; + + public static final String NAME = "GooKey"; + + @SuppressWarnings("unchecked") + public EcCore() { + super(NAME, 0.1, INFO); + AccessController.doPrivileged(new java.security.PrivilegedAction() { + public Object run() { + put("Signature.SHA1withECDSA", "cz.cvut.jce.EcSignatureImpl$SHA1"); + put("Alg.Alias.Signature.ECDSA", "SHA1withDSA"); + put("Signature.SHA256withECDSA", + "cz.cvut.keyczar.jce.EcSignatureImpl$SHA256"); + put("Signature.SHA384withECDSA", + "cz.cvut.keyczar.jce.EcSignatureImpl$SHA384"); + put("Signature.SHA512withECDSA", + "cz.cvut.keyczar.jce.EcSignatureImpl$SHA512"); + put("KeyPairGenerator.EC", "cz.cvut.keyczar.jce.EcKeyPairGeneratorImpl"); + put("KeyFactory.EC", "cz.cvut.keyczar.jce.EcKeyFactoryImpl"); + put("Signature.SHA1withECDSA KeySize", "521"); + put("Signature.SHA1withECDSA ImplementedIn", "Software"); + put("Signature.SHA256withECDSA KeySize", "521"); + put("Signature.SHA256withECDSA ImplementedIn", "Software"); + put("Signature.SHA384withECDSA KeySize", "521"); + put("Signature.SHA384withECDSA ImplementedIn", "Software"); + put("Signature.SHA512withECDSA KeySize", "521"); + put("Signature.SHA512withECDSA ImplementedIn", "Software"); + put("KeyPairGenerator.EC ImplementedIn", "Software"); + put("KeyFactory.EC ImplementedIn", "Software"); + return null; + } + }); + } + + private static final ECParameterSpec P192 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp(new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", 16)), + new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", 16), + new BigInteger("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", 16)), + new ECPoint( + new BigInteger("188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", 16), + new BigInteger("07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", 16)), + new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 16), 1); + + private static final ECParameterSpec P224 = new ECParameterSpec( + new EllipticCurve(new ECFieldFp(new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", 16), + new BigInteger( + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", 16)), + new ECPoint(new BigInteger( + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", 16), + new BigInteger( + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 16), 1); + + private static final ECParameterSpec P256 = new ECParameterSpec( + new EllipticCurve(new ECFieldFp(new BigInteger( + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + 16)), new BigInteger( + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + 16), new BigInteger( + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + 16)), new ECPoint(new BigInteger( + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + 16), new BigInteger( + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + 16)), new BigInteger( + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 16), 1); + + private static final ECParameterSpec P384 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp( + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + 16), + new BigInteger( + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + 16)), + new ECPoint( + new BigInteger( + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + 16), + new BigInteger( + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + 16)), + new BigInteger( + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 16), 1); + + private static final ECParameterSpec P521 = new ECParameterSpec( + new EllipticCurve( + new ECFieldFp( + new BigInteger( + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + 16)), + new BigInteger( + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + 16), + new BigInteger( + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + 16)), + new ECPoint( + new BigInteger( + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + 16), + new BigInteger( + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + 16)), + new BigInteger( + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 16), 1); + + public static final String EC_PARAMS_P192_OID = "1.2.840.10045.3.1.1"; + public static final String EC_PARAMS_P224_OID = "1.3.132.0.33"; + public static final String EC_PARAMS_P256_OID = "1.2.840.10045.3.1.7"; + public static final String EC_PARAMS_P384_OID = "1.3.132.0.34"; + public static final String EC_PARAMS_P521_OID = "1.3.132.0.35"; + + private static Map oidMap = new HashMap(); + private static Map paramsMap = new HashMap(); + private static Map friendlyNameMap = new HashMap(); + + static { + oidMap.put(EC_PARAMS_P192_OID, P192); + oidMap.put(EC_PARAMS_P224_OID, P224); + oidMap.put(EC_PARAMS_P256_OID, P256); + oidMap.put(EC_PARAMS_P384_OID, P384); + oidMap.put(EC_PARAMS_P521_OID, P521); + paramsMap.put(P192, EC_PARAMS_P192_OID); + paramsMap.put(P224, EC_PARAMS_P224_OID); + paramsMap.put(P256, EC_PARAMS_P256_OID); + paramsMap.put(P384, EC_PARAMS_P384_OID); + paramsMap.put(P521, EC_PARAMS_P521_OID); + friendlyNameMap.put(P192, "P-192"); + friendlyNameMap.put(P224, "P-224"); + friendlyNameMap.put(P256, "P-256"); + friendlyNameMap.put(P384, "P-384"); + friendlyNameMap.put(P521, "P-521"); + } + + public static ECParameterSpec getParams(String oid) { + ECParameterSpec params; + if ((params = oidMap.get(oid)) != null) return params; + throw new IllegalArgumentException("Unsupported EC parameters: " + oid); + } + + public static String getOID(ECParameterSpec params) { + String oid; + if ((oid = paramsMap.get(params)) != null) return oid; + throw new IllegalArgumentException("Unsupport EC parameters"); + } + + public static String getFriendlyName(ECParameterSpec params) { + String name; + if ((name = friendlyNameMap.get(params)) != null) return name; + throw new IllegalArgumentException("Unsupport EC parameters"); + } + + private static final BigInteger ZERO = BigInteger.ZERO; + private static final BigInteger ONE = BigInteger.ONE; + private static final BigInteger TWO = BigInteger.valueOf(2); + private static final BigInteger THREE = BigInteger.valueOf(3); + private static final BigInteger FOUR = BigInteger.valueOf(4); + private static final BigInteger EIGHT = BigInteger.valueOf(8); + + private static BigInteger[] doublePointA(BigInteger[] P, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + final BigInteger a = params.getCurve().getA(); + + if (P[0] == null || P[1] == null) return P; + + BigInteger d = (P[0].pow(2).multiply(THREE).add(a)).multiply(P[1] + .shiftLeft(1).modInverse(p)); + BigInteger[] R = new BigInteger[2]; + R[0] = d.pow(2).subtract(P[0].shiftLeft(1)).mod(p); + R[1] = d.multiply(P[0].subtract(R[0])).subtract(P[1]).mod(p); + + return R; + } + + private static BigInteger[] addPointsA(BigInteger[] P1, BigInteger[] P2, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + + if (P2[0] == null || P2[1] == null) return P1; + + if (P1[0] == null || P1[1] == null) return P2; + + BigInteger d = (P2[1].subtract(P1[1])).multiply((P2[0].subtract(P1[0])) + .modInverse(p)); + BigInteger[] R = new BigInteger[2]; + R[0] = d.pow(2).subtract(P1[0]).subtract(P2[0]).mod(p); + R[1] = d.multiply(P1[0].subtract(R[0])).subtract(P1[1]).mod(p); + + return R; + } + + private static BigInteger[] multiplyPointA(BigInteger[] P, BigInteger k, + ECParameterSpec params) { + BigInteger[] Q = new BigInteger[] {null, null}; + + for (int i = k.bitLength() - 1; i >= 0; i--) { + Q = doublePointA(Q, params); + if (k.testBit(i)) Q = addPointsA(Q, P, params); + } + + return Q; + } + + private static BigInteger[] doublePointJ(BigInteger[] P, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + BigInteger A, B, C, D; + + if (P[2].signum() == 0) // point at inf + return P; + + A = FOUR.multiply(P[0]).multiply(P[1].pow(2)).mod(p); + B = EIGHT.multiply(P[1].pow(4)).mod(p); + C = THREE.multiply(P[0].subtract(P[2].pow(2))).multiply( + P[0].add(P[2].pow(2))).mod(p); + D = C.pow(2).subtract(A.add(A)).mod(p); + + return new BigInteger[] { + D, C.multiply(A.subtract(D)).subtract(B).mod(p), + TWO.multiply(P[1]).multiply(P[2]).mod(p)}; + } + + private static BigInteger[] addPointsJA(BigInteger[] P1, BigInteger[] P2, + ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + BigInteger A, B, C, D; + BigInteger X3; + + if (P1[2].signum() == 0) // point at inf + return new BigInteger[] {P2[0], P2[1], ONE}; + + A = P2[0].multiply(P1[2].pow(2)).mod(p); + B = P2[1].multiply(P1[2].pow(3)).mod(p); + C = A.subtract(P1[0]).mod(p); + D = B.subtract(P1[1]).mod(p); + + X3 = D.pow(2) + .subtract(C.pow(3).add(TWO.multiply(P1[0]).multiply(C.pow(2)))).mod(p); + return new BigInteger[] { + X3, + D.multiply(P1[0].multiply(C.pow(2)).subtract(X3)).subtract( + P1[1].multiply(C.pow(3))).mod(p), P1[2].multiply(C).mod(p)}; + } + + // Binary NAF method for point multiplication + static BigInteger[] multiplyPoint(BigInteger[] P, BigInteger k, + ECParameterSpec params) { + BigInteger h = THREE.multiply(k); + + BigInteger[] Pneg = new BigInteger[] {P[0], P[1].negate()}; + BigInteger[] R = new BigInteger[] {P[0], P[1], ONE}; + + int bitLen = h.bitLength(); + for (int i = bitLen - 2; i > 0; --i) { + R = doublePointJ(R, params); + if (h.testBit(i)) R = addPointsJA(R, P, params); + if (k.testBit(i)) R = addPointsJA(R, Pneg, params); + } + + // // + // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; + // toAffine(SS, params); + // BigInteger[] RR = multiplyPointA(P, k, params); + // if (!SS[0].equals(RR[0]) || !SS[1].equals(RR[1])) + // throw new RuntimeException("Internal mult error"); + // // + + return R; + } + + // Simultaneous multiple point multiplication, also known as Shamir�s trick + static BigInteger[] multiplyPoints(BigInteger[] P, BigInteger k, + BigInteger[] Q, BigInteger l, ECParameterSpec params) { + BigInteger[] PQ = addPointsA(P, Q, params); + BigInteger[] R = new BigInteger[] {null, null, ZERO}; + + int max = Math.max(k.bitLength(), l.bitLength()); + for (int i = max - 1; i >= 0; --i) { + R = doublePointJ(R, params); + if (k.testBit(i)) { + if (l.testBit(i)) + R = addPointsJA(R, PQ, params); + else + R = addPointsJA(R, P, params); + } else if (l.testBit(i)) R = addPointsJA(R, Q, params); + } + + // // + // BigInteger[] SS = new BigInteger[] { R[0], R[1], R[2] }; + // toAffine(SS, params); + // BigInteger[] AA = multiplyPointA(P, k, params); + // BigInteger[] BB = multiplyPointA(Q, l, params); + // BigInteger[] AB = addPointsA(AA, BB, params); + // if (!SS[0].equals(AB[0]) || !SS[1].equals(AB[1])) + // throw new RuntimeException("Internal mult error"); + // // + + return R; + } + + // SEC 1, 2.3.5 + static byte[] fieldElemToBytes(BigInteger a, ECParameterSpec params) { + int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; + byte[] bytes = a.toByteArray(); + if (len < bytes.length) { + byte[] tmp = new byte[len]; + System.arraycopy(bytes, bytes.length - tmp.length, tmp, 0, tmp.length); + return tmp; + } else if (len > bytes.length) { + byte[] tmp = new byte[len]; + System.arraycopy(bytes, 0, tmp, tmp.length - bytes.length, bytes.length); + return tmp; + } + return bytes; + } + + static int fieldElemToBytes(BigInteger a, ECParameterSpec params, + byte[] data, int off) { + int len = (((ECFieldFp) params.getCurve().getField()).getP().bitLength() + 7) / 8; + byte[] bytes = a.toByteArray(); + if (len < bytes.length) { + System.arraycopy(bytes, bytes.length - len, data, off, len); + return len; + } else if (len > bytes.length) { + System.arraycopy(bytes, 0, data, len - bytes.length + off, bytes.length); + return len; + } + System.arraycopy(bytes, 0, data, off, bytes.length); + return bytes.length; + } + + // SEC 1, 2.3.3 + static byte[] ecPointToBytes(ECPoint a, ECParameterSpec params) { + byte[] fe1 = fieldElemToBytes(a.getAffineX(), params); + byte[] fe2 = fieldElemToBytes(a.getAffineY(), params); + byte[] bytes = new byte[1 + fe1.length + fe2.length]; + bytes[0] = 0x04; + System.arraycopy(fe1, 0, bytes, 1, fe1.length); + System.arraycopy(fe2, 0, bytes, 1 + fe1.length, fe2.length); + return bytes; + } + + // SEC 1, 2.3.4 + static ECPoint bytesToECPoint(byte[] bytes, ECParameterSpec params) { + switch (bytes[0]) { + case 0x00: // point at inf + throw new IllegalArgumentException( + "Point at infinity is not a valid argument"); + case 0x02: // point compression + case 0x03: + throw new UnsupportedOperationException( + "Point compression is not supported"); + case 0x04: + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + byte[] fe = new byte[(p.bitLength() + 7) / 8]; + System.arraycopy(bytes, 1, fe, 0, fe.length); + BigInteger x = new BigInteger(1, fe); + System.arraycopy(bytes, 1 + fe.length, fe, 0, fe.length); + return new ECPoint(x, new BigInteger(1, fe)); + default: + throw new IllegalArgumentException("Invalid point encoding"); + } + } + + // Convert Jacobian point to affine + static void toAffine(BigInteger[] P, ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); + P[1] = P[1].multiply(P[2].pow(3).modInverse(p)).mod(p); + } + + static void toAffineX(BigInteger[] P, ECParameterSpec params) { + final BigInteger p = ((ECFieldFp) params.getCurve().getField()).getP(); + P[0] = P[0].multiply(P[2].pow(2).modInverse(p)).mod(p); + } + + static BigInteger[] internalPoint(ECPoint P) { + return new BigInteger[] {P.getAffineX(), P.getAffineY()}; + } + + // private static void printPerf(String msg, long start, long stop) { + // String unit = "ms"; + // long diff = stop - start; + // if (diff > 1000) { + // diff /= 1000; + // unit = "s"; + // } + // System.out.printf("%s: %d %s\n", msg, diff, unit); + // } + + public static void main(String[] args) throws Exception { + + Security.insertProviderAt(new EcCore(), 0); + + // ---- + // Test primitives + // ---- + + // GooKey EC private key, 256 bit + // Private value: + // a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2 + // Parameters: P-256 (1.2.840.10045.3.1.7) + // GooKey EC public key, 256 bit + // Public value (x coordinate): + // 86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c + // Public value (y coordinate): + // ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6 + // Parameters: P-256 (1.2.840.10045.3.1.7) + // GooKey EC private key, 256 bit + // Private value: + // b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022 + // Parameters: P-256 (1.2.840.10045.3.1.7) + // GooKey EC public key, 256 bit + // Public value (x coordinate): + // 61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1 + // Public value (y coordinate): + // 3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705 + // Parameters: P-256 (1.2.840.10045.3.1.7) + + // P = kG + BigInteger k = new BigInteger( + "a9231e0d113abdacd3bb5edb24124fbef6f562c5f90b835670f5e48f775019f2", 16); + BigInteger[] P = new BigInteger[] { + new BigInteger( + "86645e0320c0f9dc1a9b8456396cc105754df67a9829c21e13ab6ecf944cf68c", + 16), + new BigInteger( + "ea1721a578043d48f12738359b5eb5f0dac2242ec6128ee0ab6ff40c8fe0cae6", + 16), ONE}; + + // Q = lG + BigInteger l = new BigInteger( + "b84d5cfab214fc3928864abb85f668a85b1006ca0147c78f22deb1dcc7e4a022", 16); + BigInteger[] Q = new BigInteger[] { + new BigInteger( + "61f6f7264f0a19f0debcca3efd079667a0112cc0b8be07a815b4c375e96ad3d1", + 16), + new BigInteger( + "3308c0016d776ed5aa9f021e43348b2e684b3b7a0f25dc9e4c8670b5d87cb705", + 16), ONE}; + + // Known answer for P+Q + BigInteger[] kat1 = new BigInteger[] { + new BigInteger( + "bc7adb05bca2460bbfeb4e0f88b61c384ea88ed3fd56017938ac2582513d4220", + 16), + new BigInteger( + "a640a43df2e9df39eec11445b7e3f7835b743ef1ac4a83cecb570a060b3f1c6c", + 16)}; + + BigInteger[] R = addPointsA(P, Q, P256); + if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) + throw new RuntimeException("kat1 failed"); + + R = addPointsJA(P, Q, P256); + toAffine(R, P256); + if (!R[0].equals(kat1[0]) || !R[1].equals(kat1[1])) + throw new RuntimeException("kat1 failed"); + + + // Known answer for Q+Q + BigInteger[] kat2 = new BigInteger[] { + new BigInteger( + "c79d7f9100c14a70f0bb9bdce59654abf99e10d1ac5afc1a0f1b6bc650d6429b", + 16), + new BigInteger( + "6856814e47adce42bc0d7c3bef308c6c737c418ed093effb31e21f53c7735c97", + 16)}; + + R = doublePointA(P, P256); + if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) + throw new RuntimeException("kat2 failed"); + + R = doublePointJ(P, P256); + toAffine(R, P256); + if (!R[0].equals(kat2[0]) || !R[1].equals(kat2[1])) + throw new RuntimeException("kat2 failed"); + + // Known answer for kP + BigInteger[] kat3 = new BigInteger[] { + new BigInteger( + "97a82a834b9e6b50660ae30d43dac9b200276e8bcd2ed6a6593048de09276d1a", + 16), + new BigInteger( + "30a9590a01066d8ef54a910afcc8648dbc7400c01750af423ce95547f2154d56", + 16)}; + + R = multiplyPointA(P, k, P256); + if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) + throw new RuntimeException("kat3 failed"); + + R = multiplyPoint(P, k, P256); + toAffine(R, P256); + if (!R[0].equals(kat3[0]) || !R[1].equals(kat3[1])) + throw new RuntimeException("kat3 failed"); + + // Known answer for kP+lQ + BigInteger[] kat4 = new BigInteger[] { + new BigInteger( + "6fd51be5cf3d6a6bcb62594bbe41ccf549b37d8fefff6e293a5bea0836efcfc6", + 16), + new BigInteger( + "9bc21a930137aa3814908974c431e4545a05dce61321253c337f3883129c42ca", + 16)}; + + BigInteger[] RR = multiplyPointA(Q, l, P256); + R = addPointsA(R, RR, P256); + if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) + throw new RuntimeException("kat4 failed"); + + R = multiplyPoints(P, k, Q, l, P256); + toAffine(R, P256); + if (!R[0].equals(kat4[0]) || !R[1].equals(kat4[1])) + throw new RuntimeException("kat4 failed"); + + // ---- + // Test ECDSA in various combinations + // ---- + + Provider gooProv = Security.getProvider("GooKey"); + Provider nssProv = Security.getProvider("SunPKCS11-NSS"); + + // Number of iterations: trust me, this is a (stress) good test + // and does provoke bugs in a fuzzing way. + int iter = 50; + + // Iterate over all key lengths and signature schemes. + int[] keyLengths = {192, 224, 256, 384, 521}; + String[] ecdsas = { + "SHA1withECDSA", "SHA256withECDSA", "SHA384withECDSA", + "SHA512withECDSA"}; + for (int s = 0; s < ecdsas.length; s++) { + System.out.println("Signature scheme " + ecdsas[s]); + for (int i = 0; i < keyLengths.length; i++) { + System.out.print("Testing P-" + keyLengths[i] + ": "); + for (int n = 0; n < iter; n++) { + System.out.print("."); + + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("EC", gooProv); + kpGen.initialize(keyLengths[i]); + KeyPair ecKeyPair = kpGen.generateKeyPair(); + + ECPrivateKey ecPrivKey = (ECPrivateKey) ecKeyPair.getPrivate(); + byte[] tmp = ecPrivKey.getEncoded(); + KeyFactory keyFab = KeyFactory.getInstance("EC", gooProv); + keyFab.generatePrivate(new PKCS8EncodedKeySpec(tmp)); + ECPrivateKeySpec ecPrivSpec = new ECPrivateKeySpec(ecPrivKey.getS(), + ecPrivKey.getParams()); + keyFab.generatePrivate(ecPrivSpec); + + ECPublicKey ecPubKey = (ECPublicKey) ecKeyPair.getPublic(); + tmp = ecPubKey.getEncoded(); // dont modify tmp now - is used below + keyFab.generatePublic(new X509EncodedKeySpec(tmp)); + ECPublicKeySpec ecPubSpec = new ECPublicKeySpec(ecPubKey.getW(), + ecPubKey.getParams()); + keyFab.generatePublic(ecPubSpec); + + Signature ecdsa = Signature.getInstance(ecdsas[s], gooProv); + ecdsa.initSign(ecPrivKey); + ecdsa.update(tmp); + byte[] sig = ecdsa.sign(); + ecdsa.initVerify(ecPubKey); + ecdsa.update(tmp); + if (!ecdsa.verify(sig)) + throw new RuntimeException("Signature not verified: " + + keyLengths[i]); + + // Cross verify using NSS if present + if (nssProv != null) { + keyFab = KeyFactory.getInstance("EC", nssProv); + + // For some reason NSS doesnt seem to work for P-192 and P-224?! + if (keyLengths[i] == 192 || keyLengths[i] == 224) continue; + + ECPrivateKey nssPrivKey = (ECPrivateKey) keyFab + .generatePrivate(new PKCS8EncodedKeySpec(ecPrivKey.getEncoded())); + ECPublicKey nssPubKey = (ECPublicKey) keyFab + .generatePublic(new X509EncodedKeySpec(ecPubKey.getEncoded())); + + ecdsa = Signature.getInstance(ecdsas[s], nssProv); + ecdsa.initVerify(nssPubKey); + ecdsa.update(tmp); + if (!ecdsa.verify(sig)) + throw new RuntimeException("Signature not verified 2: " + + keyLengths[i]); + + ecdsa.initSign(nssPrivKey); + ecdsa.update(tmp); + sig = ecdsa.sign(); + ecdsa = Signature.getInstance(ecdsas[s], gooProv); + ecdsa.initVerify(ecPubKey); + ecdsa.update(tmp); + if (!ecdsa.verify(sig)) + throw new RuntimeException("Signature not verified 3: " + + keyLengths[i]); + } + } + System.out.println(" done"); + } + } + + // Test Keyczar integration + // Signer ecdsaSigner = new Signer("c:\\temp\\eckeyset"); + // String tbs = "Sign this"; + // String sig = ecdsaSigner.sign(tbs); + // if (ecdsaSigner.verify(sig, tbs)) + // System.out.println("Keyczar EC OK"); + // else + // System.out.println("Keyczar EC not OK"); + } +} diff --git a/src/cz/cvut/keyczar/jce/EcKeyFactoryImpl.java b/src/cz/cvut/keyczar/jce/EcKeyFactoryImpl.java new file mode 100644 index 0000000..fdd1a9a --- /dev/null +++ b/src/cz/cvut/keyczar/jce/EcKeyFactoryImpl.java @@ -0,0 +1,141 @@ +package cz.cvut.keyczar.jce; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.Key; +import java.security.KeyFactorySpi; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPrivateKeySpec; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import org.mozilla.jss.asn1.ASN1Value; +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; + +/** + * This class implements an EC key factory capable of generating: + *
    + *
  • Private keys from PKCS#8 and ECPrivateKeySpec + *
  • Public keys from X.509 and ECPublicKeySpec + *
+ * + * @author martclau@gmail.com + * + */ +public class EcKeyFactoryImpl extends KeyFactorySpi { + + public EcKeyFactoryImpl() { + super(); + } + + // "Translate" e.g. {1 2 840 10045 2 1} to 1.2.840.10045.2.1 + private static String decodeOID(ASN1Value val) throws Exception { + OBJECT_IDENTIFIER.Template ot = new OBJECT_IDENTIFIER.Template(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + val.encode(baos); + OBJECT_IDENTIFIER o = (OBJECT_IDENTIFIER) ot + .decode(new ByteArrayInputStream(baos.toByteArray())); + StringBuffer sb = new StringBuffer(); + long[] nums = o.getNumbers(); + for (int i = 0; i < nums.length - 1; i++) { + sb.append(nums[i] + "."); + } + sb.append(nums[nums.length - 1]); + return sb.toString(); + } + + @Override + protected PrivateKey engineGeneratePrivate(KeySpec keySpec) + throws InvalidKeySpecException { + if (keySpec instanceof PKCS8EncodedKeySpec) { + try { + PrivateKeyInfo.Template pkiTemp = new PrivateKeyInfo.Template(); + byte[] data = ((PKCS8EncodedKeySpec) keySpec).getEncoded(); + PrivateKeyInfo pki = (PrivateKeyInfo) pkiTemp + .decode(new ByteArrayInputStream(data)); + + AlgorithmIdentifier algid = pki.getPrivateKeyAlgorithm(); + if (!algid.getOID().toString().equals("{1 2 840 10045 2 1}")) // ecPublicKey + throw new IllegalArgumentException("Unsupported key"); + + ECParameterSpec params = EcCore.getParams(decodeOID(algid + .getParameters())); + + SEQUENCE.Template foo = new SEQUENCE.Template(); + foo.addElement(new INTEGER.Template()); + foo.addElement(new OCTET_STRING.Template()); + + SEQUENCE ecPrivateKey = (SEQUENCE) foo.decode(new ByteArrayInputStream( + pki.getEncoded())); + OCTET_STRING arrhh = (OCTET_STRING) ecPrivateKey.elementAt(1); + return new EcPrivateKeyImpl(new BigInteger(1, arrhh.toByteArray()), + params); + } catch (Exception e) { + throw new InvalidKeySpecException("Invalid key encoding", e); + } + } + if (keySpec instanceof ECPrivateKeySpec) { + ECPrivateKeySpec spec = (ECPrivateKeySpec) keySpec; + return new EcPrivateKeyImpl(spec.getS(), spec.getParams()); + } + throw new IllegalArgumentException("Type of KeySpec is not supported"); + } + + @Override + protected PublicKey engineGeneratePublic(KeySpec keySpec) + throws InvalidKeySpecException { + if (keySpec instanceof X509EncodedKeySpec) { + try { + SEQUENCE.Template outer = new SEQUENCE.Template(); + outer.addElement(AlgorithmIdentifier.getTemplate()); + outer.addElement(BIT_STRING.getTemplate()); + + byte[] data = ((X509EncodedKeySpec) keySpec).getEncoded(); + SEQUENCE ecPublicKey = (SEQUENCE) outer + .decode(new ByteArrayInputStream(data)); + + AlgorithmIdentifier algid = (AlgorithmIdentifier) ecPublicKey + .elementAt(0); + if (!algid.getOID().toString().equals("{1 2 840 10045 2 1}")) // ecPublicKey + throw new IllegalArgumentException("Unsupported key"); + + ECParameterSpec params = EcCore.getParams(decodeOID(algid + .getParameters())); + + BIT_STRING bs = (BIT_STRING) ecPublicKey.elementAt(1); + data = bs.getBits(); + + return new EcPublicKeyImpl(EcCore.bytesToECPoint(data, params), params); + } catch (Exception e) { + throw new InvalidKeySpecException("Invalid key encoding", e); + } + } + if (keySpec instanceof ECPublicKeySpec) { + ECPublicKeySpec spec = (ECPublicKeySpec) keySpec; + return new EcPublicKeyImpl(spec.getW(), spec.getParams()); + } + throw new IllegalArgumentException("Type of KeySpec is not supported"); + } + + @Override + protected T engineGetKeySpec(Key key, Class keySpec) { + throw new UnsupportedOperationException("Method not supported"); + } + + @Override + protected Key engineTranslateKey(Key key) { + throw new UnsupportedOperationException("Method not supported"); + } +} diff --git a/src/cz/cvut/keyczar/jce/EcKeyPairGeneratorImpl.java b/src/cz/cvut/keyczar/jce/EcKeyPairGeneratorImpl.java new file mode 100644 index 0000000..ff4c6ce --- /dev/null +++ b/src/cz/cvut/keyczar/jce/EcKeyPairGeneratorImpl.java @@ -0,0 +1,63 @@ +package cz.cvut.keyczar.jce; + +import java.math.BigInteger; +import java.security.KeyPair; +import java.security.KeyPairGeneratorSpi; +import java.security.SecureRandom; +import java.security.spec.ECParameterSpec; + +/** + * This class implements an EC keypair generator. + * + * @author martclau@gmail.com + * + */ +public class EcKeyPairGeneratorImpl extends KeyPairGeneratorSpi { + + private ECParameterSpec params; + + public EcKeyPairGeneratorImpl() { + super(); + } + + // SEC 1, 3.2.1 + @Override + public KeyPair generateKeyPair() { + final BigInteger n = params.getOrder(); + BigInteger S = BigInteger.ZERO; + + do { + S = new BigInteger(n.bitLength(), new SecureRandom()).mod(n); + } while (S.signum() == 0); + + BigInteger[] G = EcCore.internalPoint(params.getGenerator()); + BigInteger[] Q = EcCore.multiplyPoint(G, S, params); + EcCore.toAffine(Q, params); + + return new KeyPair(new EcPublicKeyImpl(Q[0], Q[1], params), + new EcPrivateKeyImpl(S, params)); + } + + @Override + public void initialize(int keysize, SecureRandom random) { + switch (keysize) { + case 192: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P192_OID); + break; + case 224: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P224_OID); + break; + case 256: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P256_OID); + break; + case 384: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P384_OID); + break; + case 521: + this.params = EcCore.getParams(EcCore.EC_PARAMS_P521_OID); + break; + default: + throw new IllegalArgumentException("Unsupported keysize: " + keysize); + } + } +} diff --git a/src/cz/cvut/keyczar/jce/EcPrivateKeyImpl.java b/src/cz/cvut/keyczar/jce/EcPrivateKeyImpl.java new file mode 100644 index 0000000..44d6197 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/EcPrivateKeyImpl.java @@ -0,0 +1,92 @@ +package cz.cvut.keyczar.jce; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.interfaces.ECPrivateKey; +import java.security.spec.ECParameterSpec; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; + +/** + * This class implements EC private keys. + * + * @author martclau@gmail.com + * + */ +public class EcPrivateKeyImpl implements ECPrivateKey { + + private static final long serialVersionUID = -237229630170977756L; + + private BigInteger S; + private ECParameterSpec params; + + EcPrivateKeyImpl(BigInteger S, ECParameterSpec params) { + this.S = S; + this.params = params; + } + + public BigInteger getS() { + return S; + } + + public String getAlgorithm() { + return "EC"; + } + + public byte[] getEncoded() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + SEQUENCE privateKeyInfo = new SEQUENCE(); + privateKeyInfo.addElement(new INTEGER(0)); + + SEQUENCE algid = new SEQUENCE(); + algid.addElement(new OBJECT_IDENTIFIER("1.2.840.10045.2.1")); + algid.addElement(new OBJECT_IDENTIFIER(EcCore.getOID(params))); + privateKeyInfo.addElement(algid); + + SEQUENCE ecPrivateKey = new SEQUENCE(); + ecPrivateKey.addElement(new INTEGER(1)); + ecPrivateKey + .addElement(new OCTET_STRING(EcCore.fieldElemToBytes(S, params))); + + try { + ecPrivateKey.encode(baos); + } catch (IOException ioe) { + throw new RuntimeException("Internal ASN.1 encoding error", ioe); + } + + privateKeyInfo.addElement(new OCTET_STRING(baos.toByteArray())); + + baos.reset(); + try { + privateKeyInfo.encode(baos); + } catch (IOException ioe) { + throw new RuntimeException("Internal ASN.1 encoding error", ioe); + } + + return baos.toByteArray(); + } + + public String getFormat() { + return "PKCS#8"; + } + + public ECParameterSpec getParams() { + return params; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + int bitlen = params.getOrder().bitLength(); + sb.append("GooKey EC private key, " + bitlen + " bit\n"); + sb.append(" Private value: " + S.toString(16) + "\n"); + sb.append(" Parameters: " + EcCore.getFriendlyName(params) + " (" + + EcCore.getOID(params) + ")"); + return sb.toString(); + } +} diff --git a/src/cz/cvut/keyczar/jce/EcPublicKeyImpl.java b/src/cz/cvut/keyczar/jce/EcPublicKeyImpl.java new file mode 100644 index 0000000..54a1c23 --- /dev/null +++ b/src/cz/cvut/keyczar/jce/EcPublicKeyImpl.java @@ -0,0 +1,89 @@ +package cz.cvut.keyczar.jce; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; + +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.SEQUENCE; + +/** + * This class implements EC public keys. + * + * @author martclau@gmail.com + * + */ +public class EcPublicKeyImpl implements ECPublicKey { + + private static final long serialVersionUID = -2181476758766123036L; + + private BigInteger x; + private BigInteger y; + ECParameterSpec params; + + EcPublicKeyImpl(BigInteger x, BigInteger y, ECParameterSpec params) { + this.x = x; + this.y = y; + this.params = params; + } + + EcPublicKeyImpl(ECPoint W, ECParameterSpec params) { + this.x = W.getAffineX(); + this.y = W.getAffineY(); + this.params = params; + } + + + public ECPoint getW() { + return new ECPoint(x, y); + } + + public String getAlgorithm() { + return "EC"; + } + + public byte[] getEncoded() { + SEQUENCE outer = new SEQUENCE(); + + SEQUENCE algid = new SEQUENCE(); + algid.addElement(new OBJECT_IDENTIFIER("1.2.840.10045.2.1")); + algid.addElement(new OBJECT_IDENTIFIER(EcCore.getOID(params))); + outer.addElement(algid); + + BIT_STRING ecPublivKey = new BIT_STRING(EcCore.ecPointToBytes(getW(), + params), 0); + outer.addElement(ecPublivKey); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + outer.encode(baos); + } catch (IOException ioe) { + throw new RuntimeException("Internal ASN.1 encoding error", ioe); + } + return baos.toByteArray(); + } + + public String getFormat() { + return "X.509"; + } + + public ECParameterSpec getParams() { + return params; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(); + int bitlen = params.getOrder().bitLength(); + sb.append("GooKey EC public key, " + bitlen + " bit\n"); + sb.append(" Public value (x coordinate): " + x.toString(16) + "\n"); + sb.append(" Public value (y coordinate): " + y.toString(16) + "\n"); + sb.append(" Parameters: " + EcCore.getFriendlyName(params) + " (" + + EcCore.getOID(params) + ")"); + return sb.toString(); + } +} diff --git a/src/cz/cvut/keyczar/jce/EcSignatureImpl.java b/src/cz/cvut/keyczar/jce/EcSignatureImpl.java new file mode 100644 index 0000000..b38000e --- /dev/null +++ b/src/cz/cvut/keyczar/jce/EcSignatureImpl.java @@ -0,0 +1,225 @@ +package cz.cvut.keyczar.jce; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.SignatureException; +import java.security.SignatureSpi; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; + +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.SEQUENCE; + +/** + * This class implements the ECDSA signature scheme. + * + * From + * http://java.sun.com/javase/6/docs/technotes/guides/security/StandardNames.html: + * "The ECDSA signature algorithms as defined in ANSI X9.62." This means that an + * ECDSA signature is encoded as SEQUENCE { INTEGER, INTEGER } in ASN.1. + * + * @author martclau@gmail.com + * + */ +public class EcSignatureImpl extends SignatureSpi { + + MessageDigest hash; + ECPrivateKey privateKey; + ECPublicKey publicKey; + ECParameterSpec params; + + private EcSignatureImpl(String digestName) throws NoSuchAlgorithmException { + super(); + hash = MessageDigest.getInstance(digestName); + } + + @Override + protected Object engineGetParameter(String param) + throws InvalidParameterException { + throw new UnsupportedOperationException(); + } + + @Override + protected void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException { + if (!(privateKey instanceof ECPrivateKey)) + throw new InvalidKeyException("Unsupported key type"); + this.privateKey = (ECPrivateKey) privateKey; + this.params = this.privateKey.getParams(); + } + + @Override + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException { + if (!(publicKey instanceof ECPublicKey)) + throw new InvalidKeyException("Unsupported key type"); + this.publicKey = (ECPublicKey) publicKey; + this.params = this.publicKey.getParams(); + } + + @Override + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + throw new UnsupportedOperationException(); + } + + // SEC 1, 4.1.3 + @Override + protected byte[] engineSign() throws SignatureException { + BigInteger e = trimHash(hash.digest(), params); + BigInteger r = BigInteger.ZERO; + BigInteger s = BigInteger.ZERO; + + do { + BigInteger n = params.getOrder(); + BigInteger k = BigInteger.ZERO; + + do { + do { + k = new BigInteger(n.bitLength(), new SecureRandom()).mod(n); + } while (k.signum() == 0); + + BigInteger[] G = EcCore.internalPoint(params.getGenerator()); + BigInteger[] R = EcCore.multiplyPoint(G, k, params); + EcCore.toAffineX(R, params); + + r = R[0].mod(n); + } while (r.signum() == 0); + + s = k.modInverse(n).multiply(e.add(privateKey.getS().multiply(r))).mod(n); + + } while (s.signum() == 0); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + // SEQUENCE seq = new SEQUENCE(); + // seq.addElement(new INTEGER(EcCore.fieldElemToBytes(r, params))); + // seq.addElement(new INTEGER(EcCore.fieldElemToBytes(s, params))); + + // Sigh, another work around... + SEQUENCE seq = new SEQUENCE(); + + byte[] tmp = new byte[2 + (((ECFieldFp) params.getCurve().getField()) + .getFieldSize() + 7) / 8]; + tmp[0] = 0x02; + tmp[1] = (byte) EcCore.fieldElemToBytes(r, params, tmp, 2); + seq.addElement(new ANY(tmp)); + + tmp = new byte[2 + (((ECFieldFp) params.getCurve().getField()) + .getFieldSize() + 7) / 8]; + tmp[0] = 0x02; + tmp[1] = (byte) EcCore.fieldElemToBytes(s, params, tmp, 2); + seq.addElement(new ANY(tmp)); + + seq.encode(baos); + } catch (Exception ex) { + throw new SignatureException("Internal ASN.1 encoding error", ex); + } + + return baos.toByteArray(); + } + + @Override + protected void engineUpdate(byte b) { + hash.update(b); + } + + @Override + protected void engineUpdate(byte[] b, int off, int len) { + hash.update(b, off, len); + + } + + // SEC 1, 4.1.1 + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + try { + // SEQUENCE.Template seqtemp = new SEQUENCE.Template(); + // seqtemp.addElement( INTEGER.getTemplate() ); + // seqtemp.addElement( INTEGER.getTemplate() ); + // SEQUENCE seq = (SEQUENCE)seqtemp.decode(new + // ByteArrayInputStream(sigBytes)); + // BigInteger r = (BigInteger)seq.elementAt(0); + // BigInteger s = (BigInteger)seq.elementAt(1); + + // Arrggg, the following is a work around: JSS creates BigIntegers + // using BigInteger(byte[]) which, if the "sign" bit is set, + // create negative numbers. This, of course, destroys signature + // verification. In this case they should have used the + // BigInteger(1,byte[]) + // constructor. Anyway, we do it manually... + SEQUENCE.Template foo = new SEQUENCE.Template(); + foo.addElement(ANY.getTemplate()); + foo.addElement(ANY.getTemplate()); + SEQUENCE bar = (SEQUENCE) foo.decode(new ByteArrayInputStream(sigBytes)); + BigInteger r = new BigInteger(1, ((ANY) bar.elementAt(0)).getContents()); + BigInteger s = new BigInteger(1, ((ANY) bar.elementAt(1)).getContents()); + + BigInteger e = trimHash(hash.digest(), params); + BigInteger n = params.getOrder(); + + // r in [1,n-1] + if (r.compareTo(BigInteger.ONE) < 0 || r.compareTo(n) >= 0) return false; + + // s in [1,n-1] + if (s.compareTo(BigInteger.ONE) < 0 || s.compareTo(n) >= 0) return false; + + BigInteger c = s.modInverse(n); + BigInteger u1 = e.multiply(c).mod(n); + BigInteger u2 = r.multiply(c).mod(n); + + BigInteger[] G = EcCore.internalPoint(params.getGenerator()); + BigInteger[] W = EcCore.internalPoint(publicKey.getW()); + BigInteger[] R1 = EcCore.multiplyPoints(G, u1, W, u2, params); + EcCore.toAffineX(R1, params); + + BigInteger v = R1[0].mod(n); + + return v.equals(r); + } catch (Exception e) { + throw new SignatureException("Internal error", e); + } + } + + private static BigInteger trimHash(final byte[] hash, ECParameterSpec params) { + BigInteger e = new BigInteger(1, hash); + int orderLength = params.getOrder().bitLength(); + int hashLength = 8 * hash.length; + if (orderLength < hashLength) e = e.shiftRight(hashLength - orderLength); + return e; + } + + public static class SHA1 extends EcSignatureImpl { + public SHA1() throws NoSuchAlgorithmException { + super("SHA-1"); + } + } + + public static class SHA256 extends EcSignatureImpl { + public SHA256() throws NoSuchAlgorithmException { + super("SHA-256"); + } + } + + public static class SHA384 extends EcSignatureImpl { + public SHA384() throws NoSuchAlgorithmException { + super("SHA-384"); + } + } + + public static class SHA512 extends EcSignatureImpl { + public SHA512() throws NoSuchAlgorithmException { + super("SHA-512"); + } + } +} diff --git a/src/cz/cvut/keyczar/util/.svn/all-wcprops b/src/cz/cvut/keyczar/util/.svn/all-wcprops new file mode 100644 index 0000000..58a93ff --- /dev/null +++ b/src/cz/cvut/keyczar/util/.svn/all-wcprops @@ -0,0 +1,17 @@ +K 25 +svn:wc:ra_dav:version-url +V 54 +/svn/!svn/ver/376/trunk/java/code/src/org/keyczar/util +END +Base64Coder.java +K 25 +svn:wc:ra_dav:version-url +V 71 +/svn/!svn/ver/315/trunk/java/code/src/org/keyczar/util/Base64Coder.java +END +Util.java +K 25 +svn:wc:ra_dav:version-url +V 64 +/svn/!svn/ver/376/trunk/java/code/src/org/keyczar/util/Util.java +END diff --git a/src/cz/cvut/keyczar/util/.svn/entries b/src/cz/cvut/keyczar/util/.svn/entries new file mode 100644 index 0000000..4465ec6 --- /dev/null +++ b/src/cz/cvut/keyczar/util/.svn/entries @@ -0,0 +1,96 @@ +10 + +dir +412 +http://keyczar.googlecode.com/svn/trunk/java/code/src/org/keyczar/util +http://keyczar.googlecode.com/svn + + + +2009-01-29T23:35:25.884121Z +376 +steveweis + + + + + + + + + + + + + + +8f3b247a-914b-0410-8f51-05e301831c82 + +Base64Coder.java +file + + + + +2010-03-15T07:45:43.959980Z +eccdb8aa088321a62223e0619c2f62be +2008-08-06T21:37:46.564888Z +262 +arkajit.dey + + + + + + + + + + + + + + + + + + + + + +5553 + +Util.java +file + + + + +2010-03-15T07:45:43.959980Z +4c33bebfefb18730b3fc5ddb6faa08d9 +2009-01-29T23:35:25.884121Z +376 +steveweis + + + + + + + + + + + + + + + + + + + + + +8488 + diff --git a/src/cz/cvut/keyczar/util/.svn/text-base/Base64Coder.java.svn-base b/src/cz/cvut/keyczar/util/.svn/text-base/Base64Coder.java.svn-base new file mode 100644 index 0000000..7208849 --- /dev/null +++ b/src/cz/cvut/keyczar/util/.svn/text-base/Base64Coder.java.svn-base @@ -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.util; + + +import org.keyczar.exceptions.Base64DecodingException; +import org.keyczar.i18n.Messages; + +/** + * A web-safe Base64 encoding and decoding utility class. See RFC 3548 + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public class Base64Coder { + /** + * Mapping table from 6-bit nibbles to Base64 characters. + */ + private static final char[] ALPHABET = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '-', '_'}; + /** + * Mapping table from Base64 characters to 6-bit nibbles. + */ + private static final byte[] DECODE = new byte[128]; + private static final char[] WHITESPACE = {'\t', '\n', '\r', ' ', '\f'}; + + static { + for (int i = 0; i < DECODE.length; i++) { + DECODE[i] = -1; + } + + for (int i = 0; i < WHITESPACE.length; i++) { + DECODE[WHITESPACE[i]] = -2; + } + + for (int i = 0; i < ALPHABET.length; i++) { + DECODE[ALPHABET[i]] = (byte) i; + } + } + + private Base64Coder() { + // Don't new me. + } + + /** + * Decodes a web-safe Base64 encoded string + * @param source The string to decode. May contain whitespace and optionally + * up to two padding '=' characters. + * @return A byte array representation of the encoded data. + * @throws Base64DecodingException If the source string contains an illegal + * character or is of an illegal length (1 mod 4). + */ + public static byte[] decode(String source) throws Base64DecodingException { + char[] input = source.toCharArray(); + int inLen = input.length; + // Trim up to two trailing '=' padding characters + if (input[inLen - 1] == '=') { + inLen--; + } + if (input[inLen - 1] == '=') { + inLen--; + } + + // Ignore whitespace + int whiteSpaceChars = 0; + for (char c : input) { + if (isWhiteSpace(c)) { + whiteSpaceChars++; + } + } + + inLen -= whiteSpaceChars; + int inputBlocks = inLen / 4; + int remainder = inLen % 4; + int outputLen = inputBlocks * 3; + switch (remainder) { + case 1: + throw new Base64DecodingException( + Messages.getString("Base64Coder.IllegalLength", inLen)); + case 2: + outputLen += 1; + break; + case 3: + outputLen += 2; + break; + } + byte[] out = new byte[outputLen]; + int buffer = 0; + int buffCount = 0; + int outPos = 0; + for (int i = 0; i < inLen + whiteSpaceChars; i++) { + if (!isWhiteSpace(input[i])) { + buffer = (buffer << 6) | getByte(input[i]); + buffCount++; + } + if (buffCount == 4) { + out[outPos++] = (byte) (buffer >> 16); + out[outPos++] = (byte) (buffer >> 8); + out[outPos++] = (byte) buffer; + buffer = 0; + buffCount = 0; + } + } + switch (buffCount) { + case 2: + out[outPos++] = (byte) (buffer >> 4); + break; + case 3: + out[outPos++] = (byte) (buffer >> 10); + out[outPos++] = (byte) (buffer >> 2); + break; + } + return out; + } + + /** + * Encodes an arbitrary array of input as a web-safe Base64 string. + * @param input Input bytes to encode as a web-safe Base64 String + * @return A web-safe Base64 representation of the input. This string will not + * be padded with '=' characters. + */ + public static String encode(byte[] input) { + int inputBlocks = input.length / 3; + int remainder = input.length % 3; + int outputLen = inputBlocks * 4; + + switch (remainder) { + case 1: + outputLen += 2; + break; + case 2: + outputLen += 3; + break; + } + + char[] out = new char[outputLen]; + int outPos = 0; + int inPos = 0; + + for (int i = 0; i < inputBlocks; i++) { + int buffer = (0xFF & input[inPos++]) << 16 | (0xFF & input[inPos++]) << 8 + | (0xFF & input[inPos++]); + out[outPos++] = ALPHABET[(buffer >> 18) & 0x3F]; + out[outPos++] = ALPHABET[(buffer >> 12) & 0x3F]; + out[outPos++] = ALPHABET[(buffer >> 6) & 0x3F]; + out[outPos++] = ALPHABET[buffer & 0x3F]; + } + + if (remainder > 0) { + int buffer = (0xFF & input[inPos++]) << 16; + if (remainder == 2) { + buffer |= (0xFF & input[inPos++]) << 8; + } + out[outPos++] = ALPHABET[(buffer >> 18) & 0x3F]; + out[outPos++] = ALPHABET[(buffer >> 12) & 0x3F]; + if (remainder == 2) { + out[outPos++] = ALPHABET[(buffer >> 6) & 0x3F]; + } + } + return new String(out); + } + + private static byte getByte(int i) throws Base64DecodingException { + if (i < 0 || i > 127 || DECODE[i] == -1) { + throw new Base64DecodingException( + Messages.getString("Base64Coder.IllegalCharacter", i)); + } + return DECODE[i]; + } + + private static boolean isWhiteSpace(int i) { + return DECODE[i] == -2; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/util/.svn/text-base/Util.java.svn-base b/src/cz/cvut/keyczar/util/.svn/text-base/Util.java.svn-base new file mode 100644 index 0000000..dcddcca --- /dev/null +++ b/src/cz/cvut/keyczar/util/.svn/text-base/Util.java.svn-base @@ -0,0 +1,279 @@ +/* + * 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.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import org.keyczar.exceptions.KeyczarException; + +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * A miscellaneous utility class. Includes random number generation, int-to-byte + * conversion, etc. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public class Util { + private static final ConcurrentLinkedQueue DIGEST_QUEUE = + new ConcurrentLinkedQueue(); + private static final ConcurrentLinkedQueue RAND_QUEUE = + new ConcurrentLinkedQueue(); + + private Util() { + // Don't new me. + } + + private static final Gson GSON = + new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + public static Gson gson() { + return GSON; + } + + public static byte[] stripLeadingZeros(byte[] input) { + int zeros = 0; + + // Find the first non-zero byte + while (zeros < input.length && input[zeros] == 0) { + zeros++; + } + + if (zeros == 0) { + return input; + } else { + byte[] output = new byte[input.length - zeros]; + System.arraycopy(input, zeros, output, 0, output.length); + return output; + } + } + + /** + * Returns a byte array containing 4 big-endian ordered bytes representing the + * given integer. + * + * @param input The integer to convert to a byte array. + * @return A byte array representation of an integer. + */ + public static byte[] fromInt(int input) { + byte[] output = new byte[4]; + writeInt(input, output, 0); + return output; + } + + /** + * Returns a byte array containing 8 big-endian ordered bytes representing the + * given long. + * + * @param input The long to convert to a byte array. + * @return A byte array representation of a long. + */ + public static byte[] fromLong(long input) { + byte[] output = new byte[8]; + writeLong(input, output, 0); + return output; + } + + /** + * Takes a variable number of byte arrays as input and hashes each one + * prefixed by an integer representation of its size. For example, + * prefixHash({0, 1, 2}, {1}) would hash the bytes equivalent to: + * {3, 0, 1, 2, 1, 1} + * + * @param inputs The inputs to hash + * @return The hash output + * @throws KeyczarException If the SHA-1 algorithm is not found + */ + public static byte[] prefixHash(byte[]... inputs) throws KeyczarException { + MessageDigest md = DIGEST_QUEUE.poll(); + if (md == null) { + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new KeyczarException(e); + } + } + for (byte[] array : inputs) { + md.update(fromInt(array.length)); + md.update(array); + } + byte[] digest = md.digest(); + DIGEST_QUEUE.add(md); + return digest; + } + + /** + * Hashes a variable number of byte arrays + * + * @param inputs The inputs to hash + * @return The hash output + * @throws KeyczarException If the SHA-1 algorithm is not found + */ + public static byte[] hash(byte[]... inputs) throws KeyczarException { + MessageDigest md = DIGEST_QUEUE.poll(); + if (md == null) { + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new KeyczarException(e); + } + } + for (byte[] array : inputs) { + md.update(array); + } + byte[] digest = md.digest(); + DIGEST_QUEUE.add(md); + return digest; + } + + /** + * Write random bytes into the destination. Uses pre-cached secure random + * objects + * + * @param dest Destionation to write the data + */ + public static void rand(byte[] dest) { + SecureRandom random = RAND_QUEUE.poll(); + if (random == null) { + random = new SecureRandom(); + } + random.nextBytes(dest); + RAND_QUEUE.add(random); + } + + /** + * Returns an array of random bytes of the given length + * @param len The length of the random array to output + * @return A random array of bytes + */ + public static byte[] rand(int len) { + byte[] output = new byte[len]; + rand(output); + return output; + } + + /** + * Reads 4 big-endian ordered bytes from a given offset in an array and + * returns an integer representation. + * + * This method does not check the source array length. + * + * @param src The source array to read bytes from + * @param offset The offset to start reading bytes from. + * @return The integer value represented by the source array from the offset + */ + static int readInt(byte[] src, int offset) { + int output = 0; + output |= (src[offset++] & 0xFF) << 24; + output |= (src[offset++] & 0xFF) << 16; + output |= (src[offset++] & 0xFF) << 8; + output |= (src[offset++] & 0xFF); + return output; + } + + /** + * Reads 8 big-endian ordered bytes from a given offset in an array and + * returns a long representation. + * + * This method does not check the source array length. + * + * @param src The source array to read bytes from + * @param offset The offset to start reading bytes from. + * @return The long value represented by the source array from the offset + */ + static long readLong(byte[] src, int offset) { + long output = 0; + output |= (src[offset++] & 0xFFL) << 56; + output |= (src[offset++] & 0xFFL) << 48; + output |= (src[offset++] & 0xFFL) << 40; + output |= (src[offset++] & 0xFFL) << 32; + output |= (src[offset++] & 0xFFL) << 24; + output |= (src[offset++] & 0xFFL) << 16; + output |= (src[offset++] & 0xFFL) << 8; + output |= (src[offset++] & 0xFFL); + return output; + } + + /** + * Converts a given byte array to an integer. Reads the bytes in big-endian + * order. + * + * This method does not check the source array length. + * + * @param src A big-endian representation of an integer + * @return The integer value represented by the source array + */ + public static int toInt(byte[] src) { + return readInt(src, 0); + } + + /** + * Converts a given byte array to a long. Reads the bytes in big-endian order. + * + * This method does not check the source array length. + * + * @param src A big-endian representation of a long + * @return The long value represented by the source array + */ + public static long toLong(byte[] src) { + return readLong(src, 0); + } + + /** + * Writes 4 big-endian ordered bytes representing the given integer into the + * destination byte array starting from the given offset. + * + * This method does not check the destination array length. + * + * @param input The integer to convert to bytes + * @param dest The array in which to write the integer byte representation + * @param offset The offset to start writing the bytes from + */ + static void writeInt(int input, byte[] dest, int offset) { + dest[offset++] = (byte) (input >> 24); + dest[offset++] = (byte) (input >> 16); + dest[offset++] = (byte) (input >> 8); + dest[offset++] = (byte) (input); + } + + /** + * Writes 8 big-endian ordered bytes representing the given long into the + * destination byte array starting from the given offset. + * + * This method does not check the destination array length. + * + * @param input The long to convert to bytes + * @param dest The array in which to write the long byte representation + * @param offset The offset to start writing the bytes from + */ + static void writeLong(long input, byte[] dest, int offset) { + dest[offset++] = (byte) (input >> 56); + dest[offset++] = (byte) (input >> 48); + dest[offset++] = (byte) (input >> 40); + dest[offset++] = (byte) (input >> 32); + dest[offset++] = (byte) (input >> 24); + dest[offset++] = (byte) (input >> 16); + dest[offset++] = (byte) (input >> 8); + dest[offset++] = (byte) (input); + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/util/Base64Coder.java b/src/cz/cvut/keyczar/util/Base64Coder.java new file mode 100644 index 0000000..e9f50e3 --- /dev/null +++ b/src/cz/cvut/keyczar/util/Base64Coder.java @@ -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.util; + + +import cz.cvut.keyczar.exceptions.Base64DecodingException; +import cz.cvut.keyczar.i18n.Messages; + +/** + * A web-safe Base64 encoding and decoding utility class. See RFC 3548 + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public class Base64Coder { + /** + * Mapping table from 6-bit nibbles to Base64 characters. + */ + private static final char[] ALPHABET = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', + 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '-', '_'}; + /** + * Mapping table from Base64 characters to 6-bit nibbles. + */ + private static final byte[] DECODE = new byte[128]; + private static final char[] WHITESPACE = {'\t', '\n', '\r', ' ', '\f'}; + + static { + for (int i = 0; i < DECODE.length; i++) { + DECODE[i] = -1; + } + + for (int i = 0; i < WHITESPACE.length; i++) { + DECODE[WHITESPACE[i]] = -2; + } + + for (int i = 0; i < ALPHABET.length; i++) { + DECODE[ALPHABET[i]] = (byte) i; + } + } + + private Base64Coder() { + // Don't new me. + } + + /** + * Decodes a web-safe Base64 encoded string + * @param source The string to decode. May contain whitespace and optionally + * up to two padding '=' characters. + * @return A byte array representation of the encoded data. + * @throws Base64DecodingException If the source string contains an illegal + * character or is of an illegal length (1 mod 4). + */ + public static byte[] decode(String source) throws Base64DecodingException { + char[] input = source.toCharArray(); + int inLen = input.length; + // Trim up to two trailing '=' padding characters + if (input[inLen - 1] == '=') { + inLen--; + } + if (input[inLen - 1] == '=') { + inLen--; + } + + // Ignore whitespace + int whiteSpaceChars = 0; + for (char c : input) { + if (isWhiteSpace(c)) { + whiteSpaceChars++; + } + } + + inLen -= whiteSpaceChars; + int inputBlocks = inLen / 4; + int remainder = inLen % 4; + int outputLen = inputBlocks * 3; + switch (remainder) { + case 1: + throw new Base64DecodingException( + Messages.getString("Base64Coder.IllegalLength", inLen)); + case 2: + outputLen += 1; + break; + case 3: + outputLen += 2; + break; + } + byte[] out = new byte[outputLen]; + int buffer = 0; + int buffCount = 0; + int outPos = 0; + for (int i = 0; i < inLen + whiteSpaceChars; i++) { + if (!isWhiteSpace(input[i])) { + buffer = (buffer << 6) | getByte(input[i]); + buffCount++; + } + if (buffCount == 4) { + out[outPos++] = (byte) (buffer >> 16); + out[outPos++] = (byte) (buffer >> 8); + out[outPos++] = (byte) buffer; + buffer = 0; + buffCount = 0; + } + } + switch (buffCount) { + case 2: + out[outPos++] = (byte) (buffer >> 4); + break; + case 3: + out[outPos++] = (byte) (buffer >> 10); + out[outPos++] = (byte) (buffer >> 2); + break; + } + return out; + } + + /** + * Encodes an arbitrary array of input as a web-safe Base64 string. + * @param input Input bytes to encode as a web-safe Base64 String + * @return A web-safe Base64 representation of the input. This string will not + * be padded with '=' characters. + */ + public static String encode(byte[] input) { + int inputBlocks = input.length / 3; + int remainder = input.length % 3; + int outputLen = inputBlocks * 4; + + switch (remainder) { + case 1: + outputLen += 2; + break; + case 2: + outputLen += 3; + break; + } + + char[] out = new char[outputLen]; + int outPos = 0; + int inPos = 0; + + for (int i = 0; i < inputBlocks; i++) { + int buffer = (0xFF & input[inPos++]) << 16 | (0xFF & input[inPos++]) << 8 + | (0xFF & input[inPos++]); + out[outPos++] = ALPHABET[(buffer >> 18) & 0x3F]; + out[outPos++] = ALPHABET[(buffer >> 12) & 0x3F]; + out[outPos++] = ALPHABET[(buffer >> 6) & 0x3F]; + out[outPos++] = ALPHABET[buffer & 0x3F]; + } + + if (remainder > 0) { + int buffer = (0xFF & input[inPos++]) << 16; + if (remainder == 2) { + buffer |= (0xFF & input[inPos++]) << 8; + } + out[outPos++] = ALPHABET[(buffer >> 18) & 0x3F]; + out[outPos++] = ALPHABET[(buffer >> 12) & 0x3F]; + if (remainder == 2) { + out[outPos++] = ALPHABET[(buffer >> 6) & 0x3F]; + } + } + return new String(out); + } + + private static byte getByte(int i) throws Base64DecodingException { + if (i < 0 || i > 127 || DECODE[i] == -1) { + throw new Base64DecodingException( + Messages.getString("Base64Coder.IllegalCharacter", i)); + } + return DECODE[i]; + } + + private static boolean isWhiteSpace(int i) { + return DECODE[i] == -2; + } +} \ No newline at end of file diff --git a/src/cz/cvut/keyczar/util/Util.java b/src/cz/cvut/keyczar/util/Util.java new file mode 100644 index 0000000..0d72d19 --- /dev/null +++ b/src/cz/cvut/keyczar/util/Util.java @@ -0,0 +1,278 @@ +/* + * 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.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import cz.cvut.keyczar.exceptions.KeyczarException; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * A miscellaneous utility class. Includes random number generation, int-to-byte + * conversion, etc. + * + * @author steveweis@gmail.com (Steve Weis) + * + */ +public class Util { + private static final ConcurrentLinkedQueue DIGEST_QUEUE = + new ConcurrentLinkedQueue(); + private static final ConcurrentLinkedQueue RAND_QUEUE = + new ConcurrentLinkedQueue(); + + private Util() { + // Don't new me. + } + + private static final Gson GSON = + new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create(); + + public static Gson gson() { + return GSON; + } + + public static byte[] stripLeadingZeros(byte[] input) { + int zeros = 0; + + // Find the first non-zero byte + while (zeros < input.length && input[zeros] == 0) { + zeros++; + } + + if (zeros == 0) { + return input; + } else { + byte[] output = new byte[input.length - zeros]; + System.arraycopy(input, zeros, output, 0, output.length); + return output; + } + } + + /** + * Returns a byte array containing 4 big-endian ordered bytes representing the + * given integer. + * + * @param input The integer to convert to a byte array. + * @return A byte array representation of an integer. + */ + public static byte[] fromInt(int input) { + byte[] output = new byte[4]; + writeInt(input, output, 0); + return output; + } + + /** + * Returns a byte array containing 8 big-endian ordered bytes representing the + * given long. + * + * @param input The long to convert to a byte array. + * @return A byte array representation of a long. + */ + public static byte[] fromLong(long input) { + byte[] output = new byte[8]; + writeLong(input, output, 0); + return output; + } + + /** + * Takes a variable number of byte arrays as input and hashes each one + * prefixed by an integer representation of its size. For example, + * prefixHash({0, 1, 2}, {1}) would hash the bytes equivalent to: + * {3, 0, 1, 2, 1, 1} + * + * @param inputs The inputs to hash + * @return The hash output + * @throws KeyczarException If the SHA-1 algorithm is not found + */ + public static byte[] prefixHash(byte[]... inputs) throws KeyczarException { + MessageDigest md = DIGEST_QUEUE.poll(); + if (md == null) { + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new KeyczarException(e); + } + } + for (byte[] array : inputs) { + md.update(fromInt(array.length)); + md.update(array); + } + byte[] digest = md.digest(); + DIGEST_QUEUE.add(md); + return digest; + } + + /** + * Hashes a variable number of byte arrays + * + * @param inputs The inputs to hash + * @return The hash output + * @throws KeyczarException If the SHA-1 algorithm is not found + */ + public static byte[] hash(byte[]... inputs) throws KeyczarException { + MessageDigest md = DIGEST_QUEUE.poll(); + if (md == null) { + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + throw new KeyczarException(e); + } + } + for (byte[] array : inputs) { + md.update(array); + } + byte[] digest = md.digest(); + DIGEST_QUEUE.add(md); + return digest; + } + + /** + * Write random bytes into the destination. Uses pre-cached secure random + * objects + * + * @param dest Destionation to write the data + */ + public static void rand(byte[] dest) { + SecureRandom random = RAND_QUEUE.poll(); + if (random == null) { + random = new SecureRandom(); + } + random.nextBytes(dest); + RAND_QUEUE.add(random); + } + + /** + * Returns an array of random bytes of the given length + * @param len The length of the random array to output + * @return A random array of bytes + */ + public static byte[] rand(int len) { + byte[] output = new byte[len]; + rand(output); + return output; + } + + /** + * Reads 4 big-endian ordered bytes from a given offset in an array and + * returns an integer representation. + * + * This method does not check the source array length. + * + * @param src The source array to read bytes from + * @param offset The offset to start reading bytes from. + * @return The integer value represented by the source array from the offset + */ + static int readInt(byte[] src, int offset) { + int output = 0; + output |= (src[offset++] & 0xFF) << 24; + output |= (src[offset++] & 0xFF) << 16; + output |= (src[offset++] & 0xFF) << 8; + output |= (src[offset++] & 0xFF); + return output; + } + + /** + * Reads 8 big-endian ordered bytes from a given offset in an array and + * returns a long representation. + * + * This method does not check the source array length. + * + * @param src The source array to read bytes from + * @param offset The offset to start reading bytes from. + * @return The long value represented by the source array from the offset + */ + static long readLong(byte[] src, int offset) { + long output = 0; + output |= (src[offset++] & 0xFFL) << 56; + output |= (src[offset++] & 0xFFL) << 48; + output |= (src[offset++] & 0xFFL) << 40; + output |= (src[offset++] & 0xFFL) << 32; + output |= (src[offset++] & 0xFFL) << 24; + output |= (src[offset++] & 0xFFL) << 16; + output |= (src[offset++] & 0xFFL) << 8; + output |= (src[offset++] & 0xFFL); + return output; + } + + /** + * Converts a given byte array to an integer. Reads the bytes in big-endian + * order. + * + * This method does not check the source array length. + * + * @param src A big-endian representation of an integer + * @return The integer value represented by the source array + */ + public static int toInt(byte[] src) { + return readInt(src, 0); + } + + /** + * Converts a given byte array to a long. Reads the bytes in big-endian order. + * + * This method does not check the source array length. + * + * @param src A big-endian representation of a long + * @return The long value represented by the source array + */ + public static long toLong(byte[] src) { + return readLong(src, 0); + } + + /** + * Writes 4 big-endian ordered bytes representing the given integer into the + * destination byte array starting from the given offset. + * + * This method does not check the destination array length. + * + * @param input The integer to convert to bytes + * @param dest The array in which to write the integer byte representation + * @param offset The offset to start writing the bytes from + */ + static void writeInt(int input, byte[] dest, int offset) { + dest[offset++] = (byte) (input >> 24); + dest[offset++] = (byte) (input >> 16); + dest[offset++] = (byte) (input >> 8); + dest[offset++] = (byte) (input); + } + + /** + * Writes 8 big-endian ordered bytes representing the given long into the + * destination byte array starting from the given offset. + * + * This method does not check the destination array length. + * + * @param input The long to convert to bytes + * @param dest The array in which to write the long byte representation + * @param offset The offset to start writing the bytes from + */ + static void writeLong(long input, byte[] dest, int offset) { + dest[offset++] = (byte) (input >> 56); + dest[offset++] = (byte) (input >> 48); + dest[offset++] = (byte) (input >> 40); + dest[offset++] = (byte) (input >> 32); + dest[offset++] = (byte) (input >> 24); + dest[offset++] = (byte) (input >> 16); + dest[offset++] = (byte) (input >> 8); + dest[offset++] = (byte) (input); + } +} \ No newline at end of file diff --git a/src/log4j.properties b/src/log4j.properties new file mode 100644 index 0000000..5ed4c51 --- /dev/null +++ b/src/log4j.properties @@ -0,0 +1,4 @@ + +log4j.rootLogger=OFF + +