Java Forum / Security / November 2003
Encrypt using PrivateKey? NoSuchAlgorithmException: Cannot find any provider supporting RSA (JDK 1.4.2)
David Stevenson - 28 Oct 2003 03:48 GMT I am attempting to write an encryption program using a PrivateKey from a KeyStore. Apparently, I can't because I am getting an exception.
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 () ; } }
Wolfgang Bauer - 28 Oct 2003 14:00 GMT > 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
 Signature IAIK-Graz University of Technology Inffeldgasse 16a, 8010 Graz, Austria http://jce.iaik.tugraz.at
Roedy Green - 28 Oct 2003 21:35 GMT >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.
David Stevenson - 29 Oct 2003 02:45 GMT >> I am attempting to write an encryption program using a PrivateKey from >> a KeyStore. Apparently, I can't because I am getting an exception. [quoted text clipped - 9 lines] > > Wolfgang 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:
Wolfgang Bauer - 29 Oct 2003 09:49 GMT > 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. 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 ;-)
Wolfgang
 Signature IAIK-Graz University of Technology Inffeldgasse 16a, 8010 Graz, Austria http://jce.iaik.tugraz.at
Roedy Green - 29 Oct 2003 00:40 GMT > -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?
-- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
David Stevenson - 29 Oct 2003 02:40 GMT >>-keyalg RSA -keysize 1024 > [quoted text clipped - 6 lines] > Coaching, problem solving, economical contract programming. > See http://mindprod.com/jgloss/jgloss.html for The Java Glossary. 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 [
Roedy Green - 29 Oct 2003 02:50 GMT >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.
-- Canadian Mind Products, Roedy Green. Coaching, problem solving, economical contract programming. See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
David Stevenson - 30 Oct 2003 01:46 GMT >>I tried setting the key size to 512, which is the lowest available >>keysize for RSA. [quoted text clipped - 9 lines] > Coaching, problem solving, economical contract programming. > See http://mindprod.com/jgloss/jgloss.html for The Java Glossary. 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
Caspian Rychlik-Prince - 27 Nov 2003 12:28 GMT I've been working towards solving the same problem (it would appear the the Sun JDK documentation is basically very vague and unhelpful).
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 :)
>>> I tried setting the key size to 512, which is the lowest available >>> keysize for RSA. [quoted text clipped - 20 lines] > > David Stevenson
 Signature Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
David Stevenson - 29 Oct 2003 02:43 GMT >>-keyalg RSA -keysize 1024 > [quoted text clipped - 6 lines] > Coaching, problem solving, economical contract programming. > See http://mindprod.com/jgloss/jgloss.html for The Java Glossary. 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 [
David Stevenson - 29 Oct 2003 02:44 GMT >>-keyalg RSA -keysize 1024 > [quoted text clipped - 6 lines] > Coaching, problem solving, economical contract programming. > See http://mindprod.com/jgloss/jgloss.html for The Java Glossary. 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 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 [
David Stevenson - 29 Oct 2003 02:45 GMT >>-keyalg RSA -keysize 1024 > [quoted text clipped - 6 lines] > Coaching, problem solving, economical contract programming. > See http://mindprod.com/jgloss/jgloss.html for The Java Glossary. 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 [
Michael Amling - 29 Oct 2003 15:11 GMT > I am attempting to write an encryption program using a PrivateKey from a > KeyStore. Apparently, I can't because I am getting an exception. 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
David Stevenson - 30 Oct 2003 01:43 GMT >> I am attempting to write an encryption program using a PrivateKey from >> a KeyStore. Apparently, I can't because I am getting an exception. [quoted text clipped - 10 lines] > > --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. [
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|