According to JavaTM Cryptography Extension (JCE) Reference Guide
for the JavaTM 2 SDK, Standard Edition, v 1.4. Supposedly, RSA is
supported for Cipher (but DSA is not).
Is there a way to encrypt using a PrivateKey of a KeyStore, or am I
on the wrong path?
The keystore was created as follows:
keytool -genkey -validity 365 -alias RobinHood -keyalg RSA -keysize 1024
-keypass RobinHood -dname "CN=Robin Hood, O=Robin Hood and his Merry
Men, L=Sherwood Forest, C=GB" -keystore ./RobinHoodKeystore -storepass
RobinHood
Is there a need to specify a provider when getting an instance?
java PrintProviders | grep name:
name: SUN
name: SunJSSE
name: SunRsaSign
name: SunJCE
name: SunJGSS
[david@localhost ch07]$ java EncryptUsingPrivateKey ./RobinHoodKeystore
RobinHood RobinHood input.txt output.txt
Private key: algorithm: RSA format: PKCS8
Exception in thread "main" java.security.NoSuchAlgorithmException:
Cannot find any provider supporting RSA
at javax.crypto.Cipher.getInstance(DashoA6275)
at EncryptUsingPrivateKey.main(EncryptUsingPrivateKey.java:37)
import java.io.BufferedInputStream ;
import java.io.BufferedOutputStream ;
import java.io.FileInputStream ;
import java.io.FileOutputStream ;
import java.security.KeyStore ;
import java.security.PrivateKey ;
import javax.crypto.Cipher ;
public class EncryptUsingPrivateKey
{
public static void main ( String[] args )
throws Exception
{
if ( args.length != 5 )
{
System.out.println (
"usage: EncryptUsingPrivateKey keystore storepass alias " +
"inputFile outputFile" ) ;
return ;
}
String keystorefile = args[0] ;
String storepass = args[1] ;
String alias = args[2] ;
String inputFile = args[3] ;
String outputFile = args[4] ;
KeyStore keystore = KeyStore.getInstance ( "JKS" ) ;
keystore.load ( new FileInputStream ( keystorefile ),
storepass.toCharArray() ) ;
PrivateKey privateKey = (PrivateKey) keystore.getKey ( alias,
storepass.toCharArray() ) ;
System.out.println ( "Private key: algorithm: " +
privateKey.getAlgorithm () +
" format: " + privateKey.getFormat () ) ;
Cipher cipher = Cipher.getInstance ( privateKey.getAlgorithm () ) ;
cipher.init ( Cipher.ENCRYPT_MODE, privateKey ) ;
BufferedInputStream in = new BufferedInputStream ( new FileInputStream
( inputFile ) ) ;
BufferedOutputStream out = new BufferedOutputStream ( new
FileOutputStream ( outputFile ) ) ;
byte[] buffer = new byte [ 8192 ] ;
int bytesRead ;
while ( ( bytesRead = in.read ( buffer, 0, buffer.length ) ) != -1 )
{
byte [] encryptedBytes = cipher.update ( buffer, 0, bytesRead ) ;
out.write ( encryptedBytes, 0, encryptedBytes.length ) ;
}
in.close () ;
out.close () ;
}
}
> I am attempting to write an encryption program using a PrivateKey from a
> KeyStore. Apparently, I can't because I am getting an exception.
> Private key: algorithm: RSA format: PKCS8
> Exception in thread "main" java.security.NoSuchAlgorithmException:
> Cannot find any provider supporting RSA
Apperently you don't have a provider installed that supports RSA
encryption :-)
HTH
Wolfgang
--
IAIK-Graz University of Technology
Inffeldgasse 16a, 8010 Graz, Austria
http://jce.iaik.tugraz.at
>Apperently you don't have a provider installed that supports RSA
>encryption
For the java glossary, how do you get a list of JCE does support?
--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
> -keyalg RSA -keysize 1024
what happens when you shrink the keysize? Do you need to download
some special version of the library to get the high number of bits?
Do your clients?
I tried setting the key size to 512, which is the lowest available
keysize for RSA.
I also tried downloading the Unlimited Strength Jurisdiction Policy
Files and installing them (there were 2 .jar files:
[david@localhost cryptography]$ ll $JAVA_HOME/jre/lib/security/*.jar
-r--r--r-- 1 root bin 4368 Oct 27 22:54
/usr/java/j2sdk1.4.2/jre/lib/security/local_policy.jar
-r--r--r-- 1 root bin 4355 Oct 27 22:54
/usr/java/j2sdk1.4.2/jre/lib/security/US_export_policy.jar
David Stevenson
[
I tried setting the key size to 512, which is the lowest available
I tried setting the key size to 512, which is the lowest available
keysize for RSA. Still the same exception, except that I switched
from using PrivateKey to PublicKey.
I tried setting the key size to 512, which is the lowest available
keysize for RSA.
I also tried downloading the Unlimited Strength Jurisdiction Policy
JavaTM Cryptography Extension (JCE) Reference Guide
http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html#AppA
Says that RSA is supported as part of JDK 1.4.2.
From Cryptix README.TXT file (I downloaded Unlimited Strength
Jurisdiction Policy Files" - there were .jar files).
Is the capability of Digital Signatures using RSA a different capability
than encryption? Perhaps only the digital signature capability is provided.
JDK 1.4 (Java 2 version 1.4)
Cryptix JCE works out-of-the-box on JDK 1.4 but its functionality is
restricted to what Sun allows trough their Jurisdiction Policy Files.
In practice this means that you are limited to what the French
government
allows in terms of key sizes. Why Sun forces the French policy on the
rest of the world, and especially the USA, is an open question.
If you require using Cryptix without any restrictions whatsoever,
you must have the "Java Cryptography Extension (JCE) Unlimited Strength
Jurisdiction Policy Files" installed. At the time of writing they can be
found at: http://java.sun.com/j2se/1.4/ . Installing these is
non-trivial
for casual users.
OVERVIEW
--------
The Cryptix JCE includes:
FEATURES
--------
Digital Signatures:
RSASSA-PSS (with choice of MD2, MD4, MD5, RIPEMD-128, RIPEMD-160, SHA-1,
SHA-256, SHA-384, SHA-512 or Tiger hash algorithms)
NOTE: The hash function you choose when you instantiate RSASSA-PSS is
used
for both message hashing and for the Mask Generation Function
(MGF1).
It is presently not possible to use one hash function for message
hashing and another for MGF1.
RSASSA-PKCS1 (with MD4, MD5, RIPEMD-128, RIPEMD-160 or SHA-1)
import java.util.Iterator ;
import java.security.Security ;
import java.security.Provider ;
public class PrintProviders
{
public static void main ( String [] args )
{
Provider [ ] providers = Security.getProviders () ;
for ( int i = 0 ; i < providers.length ; i++ )
{
String name = providers[i].getName () ;
String info = providers[i].getInfo () ;
double version = providers[i].getVersion () ;
System.out.println (
"-------------------------------------" ) ;
System.out.println ( "name: " + name ) ;
System.out.println ( "info: " + info ) ;
System.out.println ( "version: " + version ) ;
for ( Iterator iter = providers[i].keySet
().iterator () ; iter.hasNext () ; )
{
String key = (String) iter.next () ;
System.out.println ( "\t" + key +
"\t" +
providers[i].getProperty ( key ) ) ;
}
System.out.println (
"-------------------------------------" ) ;
}
}
}
Attached is output:
>I tried setting the key size to 512, which is the lowest available
>keysize for RSA.
try the examples mentioned at
http://mindprod.com/jgloss/keytool.html
They do work. Then gradually modify them to what you want to do to
find out which parameter is giving the grief.
This is just a pointer to the standard names. What algorithms are
actually supported depends on the installed providers. You'll have to
download and install a provider that implements a RSA cipher. (Rememeber
in 1.4 this provider has to be signed).
> Is the capability of Digital Signatures using RSA a different capability
> than encryption? Perhaps only the digital signature capability is provided.
There is definitely a difference between signing and encrypting and
thats probably the reason why they call their provider SunRsaSign ;-)
What is it that you mean by encryption using a private key? Something
"encrypted" with a private key could be decrypted with the corresponding
public key, so you won't get any confidentiality from "encrypting" with
a private key.
Normally you encrypt a (short) message with an RSA public key. The
message remains confidential from an eavesdropper who gets the
ciphertext. The holder of the corresponding private key can decrypt that
ciphertext to recover the message.
Perhaps you could explain what you're trying to accomplish.
--Mike Amling
This is not a business project. It is just my attempts to learn the Java
cryptography package. I am interested for work applications in
determining if I can encrypt data with a Public Key and then decrypt
with a Private Key. Essentially I was considering encrypting a password
and/or user name across an HTTP/web page. Also, I just wanted to get
some practice with Public Key/Private Keys in preparation for dealing
with SSL/TLS.
In Chapter 2, page 15, of the book Java Cryptography, under the heading
of Asymmetric Ciphers, I saw Figure 2-4: Operation of an asymmetric cipher.
This shows Maid Marian encrypting plaintext using Robin Hood's public
key, and Robin Hood decrypting the encrypted text using Robin Hood's
private key, producing the original plaintext from Maid Marian.
I did get the Private Key/Public Key mixed up in my first program.
The second version of my program attempted to use a Public Key instead.
(However, the section on signatures shows Maid Marian encrypting a
Message Digest with her Private Key, producing a signature. Yes, I know
that a signature can be produced with the Signature.sign method).
The following is my revised program using a Public Key.
import java.io.BufferedInputStream ;
import java.io.BufferedOutputStream ;
import java.io.FileInputStream ;
import java.io.FileOutputStream ;
import java.security.KeyStore ;
import java.security.PublicKey ;
import java.security.cert.Certificate ;
import javax.crypto.Cipher ;
public class EncryptUsingPublicKey
{
public static void main ( String[] args )
throws Exception
{
if ( args.length != 5 )
{
System.out.println (
"usage: EncryptUsingPrivateKey keystore storepass alias " +
"inputFile outputFile" ) ;
return ;
}
String keystorefile = args[0] ;
String storepass = args[1] ;
String alias = args[2] ;
String inputFile = args[3] ;
String outputFile = args[4] ;
KeyStore keystore = KeyStore.getInstance ( "JKS" ) ;
keystore.load ( new FileInputStream ( keystorefile ),
storepass.toCharArray() ) ;
Certificate certificate = keystore.getCertificate ( alias ) ;
PublicKey publicKey = (PublicKey) certificate.getPublicKey () ;
System.out.println ( "Public key: algorithm: " +
publicKey.getAlgorithm () +
" format: " + publicKey.getFormat () ) ;
// Cipher cipher = Cipher.getInstance ( publicKey.getAlgorithm () ) ;
Cipher cipher = Cipher.getInstance ( "RSA/ECB/PKCS1Padding" ) ;
cipher.init ( Cipher.ENCRYPT_MODE, publicKey ) ;
BufferedInputStream in = new BufferedInputStream ( new FileInputStream
( inputFile ) ) ;
BufferedOutputStream out = new BufferedOutputStream ( new
FileOutputStream ( outputFile ) ) ;
byte[] buffer = new byte [ 8192 ] ;
int bytesRead ;
while ( ( bytesRead = in.read ( buffer, 0, buffer.length ) ) != -1 )
{
byte [] encryptedBytes = cipher.update ( buffer, 0, bytesRead ) ;
out.write ( encryptedBytes, 0, encryptedBytes.length ) ;
}
in.close () ;
out.close () ;
}
}
I am still getting the Exception:
java EncryptUsingPublicKey ./MaidMarionKeystore MaidMarion RobinHood
input.txt output.txt
Public key: algorithm: RSA format: X509
Exception in thread "main" java.security.NoSuchAlgorithmException:
Cannot find any provider supporting RSA/ECB/PKCS1Padding at
javax.crypto.Cipher.getInstance(DashoA6275)
at EncryptUsingPublicKey.main(EncryptUsingPublicKey.java:41)
Like someone later said, there is probably a major difference between
the Sun 1.4.2 JDK providing DSA and RSA signatures, and providing the
ability for DSA and RSA encryption. Given that, I suspect that one needs
to buy the SDK package from www.rsasecurity.com if one wants to use the
RSA encryption, instead of just signatures.
David Stevenson
P.S. I apologize for the duplicate postings. I am new to Linux and was
having trouble with Mozilla posting to the newsgroup.
[
I am getting "keytool" to work fine, even with a key size of 512.
I have been able to get the Signature.sign and Signature.verify to work
with DSA (haven't tried RSA, but I suspect it would work).
The No Such Algorithm Exception for RSA encryption (Cipher.getInstance (
"RSA" ) suggests that while Signature support for DSA and RSA is
provided with Sun JDK 1.4.2, encryption with DSA and RSA is not
supported. I guess the provider can determine which encryptions to
provide, and which ones not to provide.
David Stevenson
I have eventually settled on the Cryptix provider, which does provide RSA
encryption. However, I'm unable to get decryption to work.
Having generated a key pair for RSA, I've created a sealed object with a
Cipher using RSASSA-PKCS1. The sealing occurs just fine. However, when I
try to decrypt the sealed object using the private key, I get the
following exception:
java.lang.IllegalArgumentException: Null input buffer
at javax.crypto.Cipher.doFinal(DashoA6275)
at javax.crypto.SealedObject.unseal(DashoA6275)
at javax.crypto.SealedObject.getObject(DashoA6275)
Is this a bug in the Cryptix library?
Cas :)
--
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/