Hallo,
ein Problem ist sicher, dass du etwas versuchst, was aus gutem
Grund niemand so macht:
Asymmetrisches Verschlüsseln von großen Datenmengen ist nicht
wirklich praktikabel. Programme wie PGP, GPG etc. lösen das
so, dass sie einen zufälligen symmetrischen Schlüssel
auswürfeln, und nur diesen asymmetrisch mit dem öffentlichen
Schlüssel jedes Empfängers verschlüsseln, was bei bei der
Länge eines AES-256-Schlüssels kein Problem gibt.
Ich denke auch das ist die einzige sinnvolle Möglichkeit. Denn genau für diesen Anwendungsfall gibt es schon bequeme/vorgefertigte Methoden in der Java Cryptographic Architecture (JCA)…
Zum Thema RSA Sicherheit es wurde schon ein RSA 768bit Schlüssel geknackt… Also ist alles kleiner gleich 786bit nicht sicher!!!
hier kucks du: http://www.rsa.com/rsalabs/node.asp?id=3723
Aber rein aus Interesse möchte ich es trotzdem wissen, wo mein Fehler ist…
ich habe die Buffergröße für den Iterator fest verdrahtet, da ich bei meinen Schlüssel weiß, das beim verschlüsseln 52 rein => 128 raus und logischer weise beim entschlüsseln 128 rein => 52 raus. Das ist nur zu Testzwecken, wird später entfernt…
hier mein Code:
/\*\*
\* Test Implementierung fuer die auf Zertifikate basierende Verschluesselung
\*
\* @author Daniel
\* @version 1.0
\* @since 06.07.2010
\*/
public class CertificateBasedRSA implements AsymmetricCryptoTool
{
/\*\*
\* Das Chipher Objekt welche mit DES initialisiert wird
\*/
private Cipher cipherCert;
/\*\*
\* das Encoding fuer die String Repraesentation (siehe
\* {@link Charset#defaultCharset()})
\*/
private String encoding;
/\*\*
\* das Key-Paar (oeffentliche und privater Schluessel)
\*/
private String keystorePassword;
/\*\*
\* das Zertifikat fuer die Ver/Entschluesselung
\*/
private Certificate cert;
/\*\*
\* das Schluesselpaar (oeffenlicher und privater Schluessel)
\*/
private KeyPair keypair;
/\*\*
\* der Standard Konstruktor
\*/
@SuppressWarnings("nls")
public CertificateBasedRSA()
{
this("", Charset.defaultCharset().name());
}
/\*\*
\* der Konstruktor zum definieren des Passwortes fuer den KeyStore
\*
\* @param keyStorePasswd
\* das KeyStore Passwort
\*/
public CertificateBasedRSA(String keyStorePasswd)
{
this(keyStorePasswd, Charset.defaultCharset().name());
}
/\*\*
\* der Konstruktor zum definieren des Passwortes fuer den KeyStore und das
\* Encoding (siehe {@link Charset#name()})
\*
\* @param keyStorePasswd
\* das KeyStore Passwort
\* @param encoding
\* das Encoding (siehe {@link Charset#name()})
\*/
public CertificateBasedRSA(String keyStorePasswd, String encoding)
{
this.keystorePassword = keyStorePasswd;
this.encoding = encoding;
}
/\*\*
\* initialisiere des das Chipher Objekt mit dem DES Algorithmus
\*
\* @param mode
\* true =\> encrytion, false =\> decrytion
\* @throws NoSuchAlgorithmException
\* Wenn der Algorithmus nicht implementiert ist
\* @throws NoSuchPaddingException
\* wenn ein Fehler beim Padding auftritt
\* @throws InvalidKeyException
\* wenn der Key einen fehlerhaft ist
\* @throws IOException
\* Wenn ein Fehler beim Zugriff auf den KeyStore auftritt
\* @throws CertificateException
\* Wenn ein Fehler bei der Verarbeitung des Zertifikats auftritt
\* @throws KeyStoreException
\* Wenn ein Fehler bei der Initialisierung des KeyStores auftritt
\* @throws UnrecoverableKeyException
\* Wenn ein Fehler beim initialisieren des Zertifaktes/Schluessels
\* auftritt
\*/
@SuppressWarnings("nls")
private void initCipher(boolean mode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IOException, CertificateException, KeyStoreException, UnrecoverableKeyException
{
// init keystore
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
char[] password = this.keystorePassword.toCharArray();
// read keystore data
FileInputStream inputStream = null;
try
{
inputStream = new FileInputStream(new File("C:/Program Files/Java/Tomcat 6.0/conf/keystore/ssl1"));
keystore.load(inputStream, password);
}
finally
{
if (inputStream != null)
{
inputStream.close();
}
}
// generate cert, private key
this.cert = keystore.getCertificate("tomcat");
PrivateKey privateKey = (PrivateKey) keystore.getKey("tomcat", password);
if (this.cert == null)
{
throw new IOException("kein Zertifikat gefunden");
}
// init keypair
this.keypair = new KeyPair(this.cert.getPublicKey(), privateKey);
if(this.cipherCert == null)
{
this.cipherCert = Cipher.getInstance("RSA");
}
if (mode)
{
this.cipherCert.init(Cipher.ENCRYPT\_MODE, this.keypair.getPublic());
}
else
{
this.cipherCert.init(Cipher.DECRYPT\_MODE, this.keypair.getPrivate());
}
}
/\*\*
\* entschluessel einen Content
\*
\* @param content
\* der zu entschluesselnde String
\* @return der entschluesselte String
\* @throws DecodeException
\* wenn ein Fehler bei der Entschluesselung auftritt
\*/
public String decode(String content) throws DecodeException
{
try
{
this.initCipher(false);
byte[] result = new byte[1];
String base64DecryptedContent = Base64.encodeBase64String(content.getBytes());
Iterator it = new ContentIterator(base64DecryptedContent.getBytes(this.encoding), 128);
while(it.hasNext())
{
byte[] plain = it.next();
byte[] cryptedContent = this.cipherCert.doFinal(plain);
byte[] tempResult = new byte[result.length+cryptedContent.length];
//copy result to temp
System.arraycopy(result, 0, tempResult, 0, result.length);
//copy crypted to temp
System.arraycopy(cryptedContent, 0, tempResult, result.length, cryptedContent.length);
//init result with new values
result = new byte[tempResult.length];
System.arraycopy(tempResult, 0, result, 0, tempResult.length);
this.initCipher(true);
}
//workaround for delete the first NULL element
byte[] temp = new byte[result.length-1];
System.arraycopy(result, 1, temp, 0, result.length-1);
return new String(temp, this.encoding);
}
catch (InvalidKeyException error)
{
throw new DecodeException(error);
}
catch (NoSuchAlgorithmException error)
{
throw new DecodeException(error);
}
catch (NoSuchPaddingException error)
{
throw new DecodeException(error);
}
catch (UnsupportedEncodingException error)
{
throw new DecodeException(error);
}
catch (IllegalBlockSizeException error)
{
throw new DecodeException(error);
}
catch (BadPaddingException error)
{
throw new DecodeException(error);
}
catch (CertificateException error)
{
throw new DecodeException(error);
}
catch (IOException error)
{
throw new DecodeException(error);
}
catch (UnrecoverableKeyException error)
{
throw new DecodeException(error);
}
catch (KeyStoreException error)
{
throw new DecodeException(error);
}
}
/\*\*
\* verschluessel eines String Inhaltes
\*
\* @param content
\* der zu verschluesselnde String
\* @return der verschluesselte String
\* @throws EncodeException
\* wenn ein Fehler bei der Verschluesselung auftritt
\*/
public String encode(String content) throws EncodeException
{
try
{
this.initCipher(true);
byte[] result = new byte[1];
Iterator it = new ContentIterator(content.getBytes(this.encoding), 52);
while(it.hasNext())
{
byte[] plain = it.next();
byte[] cryptedContent = this.cipherCert.doFinal(plain);
byte[] tempResult = new byte[result.length+cryptedContent.length];
//copy result to temp
System.arraycopy(result, 0, tempResult, 0, result.length);
//copy crypted to temp
System.arraycopy(cryptedContent, 0, tempResult, result.length, cryptedContent.length);
//init result with new values
result = new byte[tempResult.length];
System.arraycopy(tempResult, 0, result, 0, tempResult.length);
this.initCipher(true);
}
//workaround for delete the first NULL element
byte[] temp = new byte[result.length-1];
System.arraycopy(result, 1, temp, 0, result.length-1);
return Base64.encodeBase64String(temp);
}
catch (InvalidKeyException error)
{
throw new EncodeException(error);
}
catch (NoSuchAlgorithmException error)
{
throw new EncodeException(error);
}
catch (NoSuchPaddingException error)
{
throw new EncodeException(error);
}
catch (UnsupportedEncodingException error)
{
throw new EncodeException(error);
}
catch (IllegalBlockSizeException error)
{
throw new EncodeException(error);
}
catch (BadPaddingException error)
{
throw new EncodeException(error);
}
catch (CertificateException error)
{
throw new EncodeException(error);
}
catch (IOException error)
{
throw new EncodeException(error);
}
catch (UnrecoverableKeyException error)
{
throw new EncodeException(error);
}
catch (KeyStoreException error)
{
throw new EncodeException(error);
}
}
/\*\*
\* hole das derzeit verwendete Encoding fuer die Strings (siehe
\* {@link Charset#defaultCharset()})
\*
\* @return das derzeit verwendete Encoding fuer die Strings (siehe
\* {@link Charset#defaultCharset()})
\*/
public String getEncoding()
{
return this.encoding;
}
/\*\*
\* setze das derzeit verwendete Encoding fuer die Strings (siehe
\* {@link Charset#defaultCharset()})
\*
\* @param encoding
\* das derzeit verwendete Encoding fuer die Strings (siehe
\* {@link Charset#name()})
\* @throws GeneralCryptoException
\* wenn das Encoding nicht von der JVM unterstuetzt wird
\*/
@SuppressWarnings("nls")
public void setEncoding(String encoding) throws GeneralCryptoException
{
if (!Charset.isSupported(encoding))
{
throw new GeneralCryptoException(new Throwable("Dieser Zeichensatz wird nicht von der JVM unterstützt"));
}
this.encoding = encoding;
}
/\*\*
\* hole das Key-Paar (oeffentlicher und privater Schluessel)
\*
\* @return das Key-Paar (oeffentlicher und privater Schluessel)
\*/
public KeyPair getKeyPair()
{
return this.keypair;
}
/\*\*
\* setze das Key-Paar (oeffentlicher und privater Schluessel)
\*
\* @param keyPair
\* das Key-Paar (oeffentlicher und privater Schluessel)
\* @throws GeneralCryptoException
\* wenn das Schluesselpaar keine RSA Schluessel sind
\*/
@SuppressWarnings("nls")
public void setKeyPair(KeyPair keyPair) throws GeneralCryptoException
{
if (!keyPair.getPublic().getAlgorithm().toLowerCase().contains("rsa")
|| !keyPair.getPrivate().getAlgorithm().toLowerCase().contains("rsa"))
{
throw new GeneralCryptoException(new Throwable(
"Das Schlüsselpaar enthält keine RSA Schlüssel (private key has \"" + keyPair.getPrivate().getAlgorithm()
+ "\" algorithmn, public key has \"" + keyPair.getPublic().getAlgorithm() + "\" algorithmn"));
}
this.keypair = keyPair;
}
/\*\*
\* Der Iterator um durch die zu ver/entschlüsselnde Menge zu iterieren
\*
\* @author Daniel
\* @version 1.0
\* @since 07.07.2010
\*/
private class ContentIterator implements Iterator
{
/\*\*
\* die aktuelle Position in der Menge
\*/
private int index;
/\*\*
\* die Laenge eines jeden "Schrittes"
\*/
private int stepLength;
/\*\*
\* die Menge durch welche iteriert wird
\*/
private byte[] content;
/\*\*
\* der InputStream zum Lesen des Contents
\*/
private ByteArrayInputStream inputStream;
/\*\*
\* der Konstruktor mit der Definition der Menge
\* @param content die Menge durch die iteriert wird
\* @param stepLength die Laenge eines jeden "Schrittes"
\*/
public ContentIterator(byte[] content, int stepLength)
{
this.content = content;
this.index = -1;
this.stepLength = stepLength;
this.inputStream = new ByteArrayInputStream(this.content);
}
/\*\*
\* gibt es ein weiteres Element?
\*
\* @return gibt es ein weiteres Element?
\*/
public boolean hasNext()
{
if(this.index == -1) this.index = 0;
if (this.index = this.content.length)
{
throw new NoSuchElementException("iteration has no more elements");
}
try
{
byte[] buffer = new byte[this.stepLength];
int read = this.inputStream.read(buffer, 0, this.stepLength);
if(read != -1)
{
this.index += read;
//if buffer complete?
if(read == buffer.length)
{
return buffer;
}
//partial copy
byte[] tmp = new byte[read];
System.arraycopy(buffer, 0, tmp, 0, read);
return tmp;
}
this.inputStream.close();
throw new NoSuchElementException("iteration has no more elements");
}
catch(IOException error)
{
throw new NoSuchElementException("iteration has no more elements or an internal error is occured");
}
}
/\*\*
\* enferne ein Element aus der Menge
\* **diese Methode ist nicht von diesem Iterator implementiert**
\*
\* @exception IllegalStateException
\* Wenn diese Methode aufgerufen wird bevor das erste mal next
\* aufgerufen wird
\* @exception UnsupportedOperationException
\* diese Methode ist nicht von diesem Iterator implementiert
\*/
@SuppressWarnings("nls")
public void remove()
{
if (this.index == -1)
{
throw new IllegalStateException("if the next() method has not yet been called");
}
throw new UnsupportedOperationException("This is not supported by this iterator");
}
}
}
hier ist der Stacktrace:
Exception in thread "main" de.buntklicken.util.crypto.contract.exception.DecodeException: javax.crypto.BadPaddingException: Data must start with zero
at de.buntklicken.util.crypto.CertificateBasedRSA.decode(CertificateBasedRSA.java:240)
at de.buntklicken.util.crypto.CertTest.main(CertTest.java:321)
Caused by: javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.a(DashoA13\*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13\*..)
at javax.crypto.Cipher.doFinal(DashoA13\*..)
at de.quick.meldecenter.util.crypto.CertificateBasedRSA.decode(CertificateBasedRSA.java:198)
... 1 more