зеркало из https://github.com/mono/ikvm-fork.git
Updated IcedTea crypto classes to support PBEwithMD5andDES.
This commit is contained in:
Родитель
fff2c860d3
Коммит
c39422e01c
|
@ -10035,6 +10035,7 @@ icedtea/jce/gnu/java/security/hash/Sha384.java
|
||||||
icedtea/jce/gnu/java/security/hash/Sha512.java
|
icedtea/jce/gnu/java/security/hash/Sha512.java
|
||||||
icedtea/jce/gnu/java/security/hash/Tiger.java
|
icedtea/jce/gnu/java/security/hash/Tiger.java
|
||||||
icedtea/jce/gnu/java/security/hash/Whirlpool.java
|
icedtea/jce/gnu/java/security/hash/Whirlpool.java
|
||||||
|
icedtea/jce/gnu/java/security/icedtea/CertBundleKeyStoreImpl.java
|
||||||
icedtea/jce/gnu/java/security/icedtea/GNUTlsKeyMaterialGeneratorImpl.java
|
icedtea/jce/gnu/java/security/icedtea/GNUTlsKeyMaterialGeneratorImpl.java
|
||||||
icedtea/jce/gnu/java/security/icedtea/GNUTlsMasterSecretGenerator.java
|
icedtea/jce/gnu/java/security/icedtea/GNUTlsMasterSecretGenerator.java
|
||||||
icedtea/jce/gnu/java/security/icedtea/GNUTlsPrfGeneratorImpl.java
|
icedtea/jce/gnu/java/security/icedtea/GNUTlsPrfGeneratorImpl.java
|
||||||
|
@ -10206,6 +10207,7 @@ icedtea/jce/gnu/javax/crypto/cipher/WeakKeyException.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/DiffieHellmanImpl.java
|
icedtea/jce/gnu/javax/crypto/jce/DiffieHellmanImpl.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/GnuCrypto.java
|
icedtea/jce/gnu/javax/crypto/jce/GnuCrypto.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/GnuSasl.java
|
icedtea/jce/gnu/javax/crypto/jce/GnuSasl.java
|
||||||
|
icedtea/jce/gnu/javax/crypto/jce/PBESecretKeyFactory.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java
|
icedtea/jce/gnu/javax/crypto/jce/PBKDF2SecretKeyFactory.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/AES128KeyWrapSpi.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/AES192KeyWrapSpi.java
|
||||||
|
@ -10221,6 +10223,7 @@ icedtea/jce/gnu/javax/crypto/jce/cipher/DESSpi.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/KeyWrappingAlgorithmAdapter.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/KhazadSpi.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/KhazadSpi.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/NullCipherSpi.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/NullCipherSpi.java
|
||||||
|
icedtea/jce/gnu/javax/crypto/jce/cipher/PBE.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/PBES2.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/PBES2.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/RijndaelSpi.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/RijndaelSpi.java
|
||||||
icedtea/jce/gnu/javax/crypto/jce/cipher/SerpentSpi.java
|
icedtea/jce/gnu/javax/crypto/jce/cipher/SerpentSpi.java
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
/* CertBundleKeyStoreImpl.java
|
||||||
|
Copyright (C) 2007 Casey Marshall <csm@gnu.org>
|
||||||
|
|
||||||
|
This file is part of IcedTea.
|
||||||
|
|
||||||
|
IcedTea is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, version 2.
|
||||||
|
|
||||||
|
IcedTea is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with IcedTea; see the file COPYING. If not, write to
|
||||||
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Linking this library statically or dynamically with other modules is
|
||||||
|
making a combined work based on this library. Thus, the terms and
|
||||||
|
conditions of the GNU General Public License cover the whole
|
||||||
|
combination.
|
||||||
|
|
||||||
|
As a special exception, the copyright holders of this library give you
|
||||||
|
permission to link this library with independent modules to produce an
|
||||||
|
executable, regardless of the license terms of these independent
|
||||||
|
modules, and to copy and distribute the resulting executable under
|
||||||
|
terms of your choice, provided that you also meet, for each linked
|
||||||
|
independent module, the terms and conditions of the license of that
|
||||||
|
module. An independent module is a module which is not derived from
|
||||||
|
or based on this library. If you modify this library, you may extend
|
||||||
|
this exception to your version of the library, but you are not
|
||||||
|
obligated to do so. If you do not wish to do so, delete this
|
||||||
|
exception statement from your version. */
|
||||||
|
|
||||||
|
|
||||||
|
package gnu.java.security.icedtea;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.KeyStoreSpi;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.UnrecoverableKeyException;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.security.cert.CertificateFactory;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A key store implementation for "certificate bundle" files, commonly used
|
||||||
|
* on many free operating systems. Certificate bundles are plain text files
|
||||||
|
* containing one or more "PEM" encoded X.509 certificates, which comprise
|
||||||
|
* a list of trusted root certificates.
|
||||||
|
*
|
||||||
|
* This class implements a read-only key store that reads in one or more
|
||||||
|
* certificate bundles, storing all certificates successfully read. Calling
|
||||||
|
* load multiple times will add certificates to the store.
|
||||||
|
*
|
||||||
|
* @author Casey Marshall (csm@gnu.org)
|
||||||
|
*/
|
||||||
|
public class CertBundleKeyStoreImpl extends KeyStoreSpi
|
||||||
|
{
|
||||||
|
private int x = 0;
|
||||||
|
private Map<String, Certificate> certs = new HashMap<String, Certificate>();
|
||||||
|
|
||||||
|
@Override public Enumeration<String> engineAliases()
|
||||||
|
{
|
||||||
|
return new Vector<String>(certs.keySet()).elements();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean engineContainsAlias(String alias)
|
||||||
|
{
|
||||||
|
return certs.containsKey(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void engineDeleteEntry(String alias) throws KeyStoreException
|
||||||
|
{
|
||||||
|
certs.remove(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Certificate engineGetCertificate(String alias)
|
||||||
|
{
|
||||||
|
return certs.get(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String engineGetCertificateAlias(Certificate cert)
|
||||||
|
{
|
||||||
|
for (Map.Entry<String, Certificate> e : certs.entrySet())
|
||||||
|
{
|
||||||
|
if (e.getValue().equals(cert))
|
||||||
|
return e.getKey();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Certificate[] engineGetCertificateChain(String arg0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Date engineGetCreationDate(String alias)
|
||||||
|
{
|
||||||
|
return new Date(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Key engineGetKey(String arg0, char[] arg1)
|
||||||
|
throws NoSuchAlgorithmException, UnrecoverableKeyException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean engineIsCertificateEntry(String alias)
|
||||||
|
{
|
||||||
|
return certs.containsKey(alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean engineIsKeyEntry(String arg0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void engineLoad(InputStream in, char[] arg1)
|
||||||
|
throws IOException, NoSuchAlgorithmException, CertificateException
|
||||||
|
{
|
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
|
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||||
|
PrintWriter out = new PrintWriter(new OutputStreamWriter(bout));
|
||||||
|
BufferedReader rin = new BufferedReader(new InputStreamReader(in));
|
||||||
|
String line;
|
||||||
|
boolean push = false;
|
||||||
|
while ((line = rin.readLine()) != null)
|
||||||
|
{
|
||||||
|
if (line.equals("-----BEGIN CERTIFICATE-----"))
|
||||||
|
{
|
||||||
|
push = true;
|
||||||
|
out.println(line);
|
||||||
|
}
|
||||||
|
else if (push)
|
||||||
|
{
|
||||||
|
out.println(line);
|
||||||
|
if (line.equals("-----END CERTIFICATE-----"))
|
||||||
|
{
|
||||||
|
push = false;
|
||||||
|
out.flush();
|
||||||
|
byte[] bytes = bout.toByteArray();
|
||||||
|
Certificate cert = cf.generateCertificate(new ByteArrayInputStream(bytes));
|
||||||
|
bout.reset();
|
||||||
|
String alias = "cert-" + (x++);
|
||||||
|
certs.put(alias, cert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void engineSetCertificateEntry(String alias, Certificate cert)
|
||||||
|
throws KeyStoreException
|
||||||
|
{
|
||||||
|
certs.put(alias, cert);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void engineSetKeyEntry(String arg0, byte[] arg1,
|
||||||
|
Certificate[] arg2)
|
||||||
|
throws KeyStoreException
|
||||||
|
{
|
||||||
|
throw new KeyStoreException("not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void engineSetKeyEntry(String arg0, Key arg1, char[] arg2,
|
||||||
|
Certificate[] arg3)
|
||||||
|
throws KeyStoreException
|
||||||
|
{
|
||||||
|
throw new KeyStoreException("not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int engineSize()
|
||||||
|
{
|
||||||
|
return certs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void engineStore(OutputStream arg0, char[] arg1)
|
||||||
|
throws IOException, NoSuchAlgorithmException, CertificateException
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("read-only key stores");
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,9 +48,13 @@ public class IcedTls extends Provider
|
||||||
{
|
{
|
||||||
super("IcedTls", 1.0, "Free replacements for encumbered Sun sources for TLS");
|
super("IcedTls", 1.0, "Free replacements for encumbered Sun sources for TLS");
|
||||||
|
|
||||||
|
// Key generators for Sun's JSSE.
|
||||||
put("KeyGenerator.SunTlsRsaPremasterSecret", GNUTlsRsaPreMasterSecretGeneratorImpl.class.getName());
|
put("KeyGenerator.SunTlsRsaPremasterSecret", GNUTlsRsaPreMasterSecretGeneratorImpl.class.getName());
|
||||||
put("KeyGenerator.SunTlsMasterSecret", GNUTlsMasterSecretGenerator.class.getName());
|
put("KeyGenerator.SunTlsMasterSecret", GNUTlsMasterSecretGenerator.class.getName());
|
||||||
put("KeyGenerator.SunTlsKeyMaterial", GNUTlsKeyMaterialGeneratorImpl.class.getName());
|
put("KeyGenerator.SunTlsKeyMaterial", GNUTlsKeyMaterialGeneratorImpl.class.getName());
|
||||||
put("KeyGenerator.SunTlsPrf", GNUTlsPrfGeneratorImpl.class.getName());
|
put("KeyGenerator.SunTlsPrf", GNUTlsPrfGeneratorImpl.class.getName());
|
||||||
|
|
||||||
|
// Certificate bundle key store.
|
||||||
|
put("KeyStore.CertBundle", CertBundleKeyStoreImpl.class.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,8 +94,54 @@ public final class DiffieHellmanImpl
|
||||||
DHPublicKey pub = (DHPublicKey) incoming;
|
DHPublicKey pub = (DHPublicKey) incoming;
|
||||||
DHParameterSpec s1 = key.getParams();
|
DHParameterSpec s1 = key.getParams();
|
||||||
DHParameterSpec s2 = pub.getParams();
|
DHParameterSpec s2 = pub.getParams();
|
||||||
if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP())
|
|
||||||
|| s1.getL() != s2.getL())
|
/* ICEDTEA LOCAL: This change is not committed to Classpath because
|
||||||
|
it's still waiting a response from Casey Marshall <csm@gnu.org>,
|
||||||
|
the author.
|
||||||
|
|
||||||
|
From: Andrew Haley <aph-gcc@littlepinkcloud.COM>
|
||||||
|
To: Casey Marshall <csm@gnu.org>, classpath-patches@gnu.org
|
||||||
|
CC: Lillian Angel <langel@redhat.com>
|
||||||
|
Subject: Fix DiffieHellmanImpl.java
|
||||||
|
Date: Fri, 3 Aug 2007 18:19:07 +0100
|
||||||
|
|
||||||
|
I came across a problem with GNU Crypto that causes Diffie-Hellman key
|
||||||
|
exchange to fail when running on IcedTea. We're doing what looks to
|
||||||
|
me like an unnecessary check in DiffieHellmanImpl.engineDoPhase()
|
||||||
|
which can fail in some circumstances, and this is triggered when
|
||||||
|
running in IcedTea. The code runs correctly on Sun's Java 1.7, not on
|
||||||
|
the IcedTea version of Java 1.7, which uses GNU Crypto.
|
||||||
|
|
||||||
|
With IcedTea and Classpath we get:
|
||||||
|
|
||||||
|
Exception in thread "main" java.security.InvalidKeyException: Incompatible key
|
||||||
|
at gnu.javax.crypto.jce.DiffieHellmanImpl.engineDoPhase(DiffieHellmanImpl.java:99)
|
||||||
|
at javax.crypto.KeyAgreement.doPhase(KeyAgreement.java:224)
|
||||||
|
at Tt.main(Tt.java:35)
|
||||||
|
|
||||||
|
Here's my patch:
|
||||||
|
|
||||||
|
2007-08-03 Andrew Haley <aph@redhat.com>
|
||||||
|
|
||||||
|
* jce/gnu/javax/crypto/jce/DiffieHellmanImpl.java (engineDoPhase):
|
||||||
|
Don't check the length of q.
|
||||||
|
|
||||||
|
--- gnu/javax/crypto/jce/DiffieHellmanImpl.java~ 2007-07-23 14:15:36.000000000 +0100
|
||||||
|
+++ gnu/javax/crypto/jce/DiffieHellmanImpl.java 2007-08-03 17:49:09.000000000 +0100
|
||||||
|
@@ -94,8 +94,7 @@
|
||||||
|
DHPublicKey pub = (DHPublicKey) incoming;
|
||||||
|
DHParameterSpec s1 = key.getParams();
|
||||||
|
DHParameterSpec s2 = pub.getParams();
|
||||||
|
- if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP())
|
||||||
|
- || s1.getL() != s2.getL())
|
||||||
|
+ if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP()))
|
||||||
|
throw new InvalidKeyException("Incompatible key");
|
||||||
|
if (! lastPhase)
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (! s1.getG().equals(s2.getG()) || ! s1.getP().equals(s2.getP()))
|
||||||
throw new InvalidKeyException("Incompatible key");
|
throw new InvalidKeyException("Incompatible key");
|
||||||
if (! lastPhase)
|
if (! lastPhase)
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
|
|
|
@ -316,6 +316,9 @@ public final class GnuCrypto
|
||||||
gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.TripleDES.class.getName());
|
gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.TripleDES.class.getName());
|
||||||
put("Cipher.PBEWithHMacWhirlpoolAndTwofish",
|
put("Cipher.PBEWithHMacWhirlpoolAndTwofish",
|
||||||
gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Twofish.class.getName());
|
gnu.javax.crypto.jce.cipher.PBES2.HMacWhirlpool.Twofish.class.getName());
|
||||||
|
put("Cipher.PBE",
|
||||||
|
gnu.javax.crypto.jce.cipher.PBE.MD5.DES.class.getName());
|
||||||
|
put("Alg.Alias.Cipher.PBEWithMD5AndDES", "PBE");
|
||||||
|
|
||||||
// Key Wrapping Algorithm cipher
|
// Key Wrapping Algorithm cipher
|
||||||
put("Cipher." + Registry.AES128_KWA,
|
put("Cipher." + Registry.AES128_KWA,
|
||||||
|
@ -348,7 +351,11 @@ public final class GnuCrypto
|
||||||
gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacTiger.class.getName());
|
gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacTiger.class.getName());
|
||||||
put("SecretKeyFactory.PBKDF2WithHMacWhirlpool",
|
put("SecretKeyFactory.PBKDF2WithHMacWhirlpool",
|
||||||
gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacWhirlpool.class.getName());
|
gnu.javax.crypto.jce.PBKDF2SecretKeyFactory.HMacWhirlpool.class.getName());
|
||||||
|
put("SecretKeyFactory.PBEWithMD5AndDES",
|
||||||
|
gnu.javax.crypto.jce.PBESecretKeyFactory.class.getName());
|
||||||
|
|
||||||
|
put("Alg.Alias.AlgorithmParameters.PBEWithMD5AndDES", "PBEWithMD5AndDES");
|
||||||
|
|
||||||
// Simple SecretKeyFactory implementations.
|
// Simple SecretKeyFactory implementations.
|
||||||
put("SecretKeyFactory.Anubis",
|
put("SecretKeyFactory.Anubis",
|
||||||
gnu.javax.crypto.jce.key.AnubisSecretKeyFactoryImpl.class.getName());
|
gnu.javax.crypto.jce.key.AnubisSecretKeyFactoryImpl.class.getName());
|
||||||
|
@ -553,7 +560,7 @@ public final class GnuCrypto
|
||||||
put("KeyFactory.DH",
|
put("KeyFactory.DH",
|
||||||
gnu.javax.crypto.jce.sig.DHKeyFactory.class.getName());
|
gnu.javax.crypto.jce.sig.DHKeyFactory.class.getName());
|
||||||
|
|
||||||
put("Alg.Alias,KeyFactory.DiffieHellman", "DH");
|
put("Alg.Alias.KeyFactory.DiffieHellman", "DH");
|
||||||
|
|
||||||
// Algorithm Parameters -----------------------------------------------
|
// Algorithm Parameters -----------------------------------------------
|
||||||
put("AlgorithmParameters.DH",
|
put("AlgorithmParameters.DH",
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* PBESecretKeyFactory.java --
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is a part of GNU Classpath.
|
||||||
|
|
||||||
|
GNU Classpath is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
your option) any later version.
|
||||||
|
|
||||||
|
GNU Classpath is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GNU Classpath; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
USA
|
||||||
|
|
||||||
|
Linking this library statically or dynamically with other modules is
|
||||||
|
making a combined work based on this library. Thus, the terms and
|
||||||
|
conditions of the GNU General Public License cover the whole
|
||||||
|
combination.
|
||||||
|
|
||||||
|
As a special exception, the copyright holders of this library give you
|
||||||
|
permission to link this library with independent modules to produce an
|
||||||
|
executable, regardless of the license terms of these independent
|
||||||
|
modules, and to copy and distribute the resulting executable under
|
||||||
|
terms of your choice, provided that you also meet, for each linked
|
||||||
|
independent module, the terms and conditions of the license of that
|
||||||
|
module. An independent module is a module which is not derived from
|
||||||
|
or based on this library. If you modify this library, you may extend
|
||||||
|
this exception to your version of the library, but you are not
|
||||||
|
obligated to do so. If you do not wish to do so, delete this
|
||||||
|
exception statement from your version. */
|
||||||
|
|
||||||
|
|
||||||
|
package gnu.javax.crypto.jce;
|
||||||
|
|
||||||
|
import gnu.javax.crypto.key.GnuPBEKey;
|
||||||
|
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.SecretKeyFactorySpi;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
|
||||||
|
public class PBESecretKeyFactory
|
||||||
|
extends SecretKeyFactorySpi
|
||||||
|
{
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
public PBESecretKeyFactory()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PBESecretKeyFactory(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SecretKey engineGenerateSecret(KeySpec spec)
|
||||||
|
throws InvalidKeySpecException
|
||||||
|
{
|
||||||
|
if (! (spec instanceof PBEKeySpec))
|
||||||
|
throw new InvalidKeySpecException("not a PBEKeySpec");
|
||||||
|
return new GnuPBEKey((PBEKeySpec) spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected KeySpec engineGetKeySpec(SecretKey key, Class clazz)
|
||||||
|
throws InvalidKeySpecException
|
||||||
|
{
|
||||||
|
throw new InvalidKeySpecException("not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected SecretKey engineTranslateKey(SecretKey key)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -386,7 +386,7 @@ class CipherAdapter
|
||||||
&& ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
|
&& ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
|
||||||
&& (partLen + inLen) % blockSize == 0)
|
&& (partLen + inLen) % blockSize == 0)
|
||||||
blockCount--;
|
blockCount--;
|
||||||
|
|
||||||
final byte[] out = new byte[blockCount * blockSize];
|
final byte[] out = new byte[blockCount * blockSize];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -406,23 +406,23 @@ class CipherAdapter
|
||||||
return 0;
|
return 0;
|
||||||
final int blockSize = mode.currentBlockSize();
|
final int blockSize = mode.currentBlockSize();
|
||||||
int blockCount = (partLen + inLen) / blockSize;
|
int blockCount = (partLen + inLen) / blockSize;
|
||||||
|
|
||||||
// always keep data for unpadding in padded decryption mode;
|
// always keep data for unpadding in padded decryption mode;
|
||||||
// might even be a complete block
|
// might even be a complete block
|
||||||
if (pad != null
|
if (pad != null
|
||||||
&& ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
|
&& ((Integer) attributes.get(IMode.STATE)).intValue() == IMode.DECRYPTION
|
||||||
&& (partLen + inLen) % blockSize == 0)
|
&& (partLen + inLen) % blockSize == 0)
|
||||||
blockCount--;
|
blockCount--;
|
||||||
|
|
||||||
final int result = blockCount * blockSize;
|
final int result = blockCount * blockSize;
|
||||||
if (result > out.length - outOff)
|
if (result > out.length - outOff)
|
||||||
throw new ShortBufferException();
|
throw new ShortBufferException();
|
||||||
|
|
||||||
if (blockCount == 0) // not enough bytes for even 1 block
|
if (blockCount == 0) // not enough bytes for even 1 block
|
||||||
{
|
{
|
||||||
System.arraycopy(in, inOff, partBlock, partLen, inLen);
|
System.arraycopy(in, inOff, partBlock, partLen, inLen);
|
||||||
partLen += inLen;
|
partLen += inLen;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
final byte[] buf;
|
final byte[] buf;
|
||||||
// we have enough bytes for at least 1 block
|
// we have enough bytes for at least 1 block
|
||||||
if (partLen == 0) // if no cached bytes use input
|
if (partLen == 0) // if no cached bytes use input
|
||||||
|
@ -435,12 +435,14 @@ class CipherAdapter
|
||||||
System.arraycopy(in, inOff, buf, partLen, inLen);
|
System.arraycopy(in, inOff, buf, partLen, inLen);
|
||||||
inOff = 0;
|
inOff = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < blockCount; i++) // update blockCount * blockSize
|
for (int i = 0; i < blockCount; i++) // update blockCount * blockSize
|
||||||
{
|
{
|
||||||
mode.update(buf, inOff, out, outOff);
|
mode.update(buf, inOff, out, outOff);
|
||||||
inOff += blockSize;
|
inOff += blockSize;
|
||||||
outOff += blockSize;
|
outOff += blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
partLen += inLen - result;
|
partLen += inLen - result;
|
||||||
if (partLen > 0) // cache remaining bytes from buf
|
if (partLen > 0) // cache remaining bytes from buf
|
||||||
System.arraycopy(buf, inOff, partBlock, 0, partLen);
|
System.arraycopy(buf, inOff, partBlock, 0, partLen);
|
||||||
|
|
|
@ -0,0 +1,229 @@
|
||||||
|
/* PBE.java --
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is a part of GNU Classpath.
|
||||||
|
|
||||||
|
GNU Classpath is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
your option) any later version.
|
||||||
|
|
||||||
|
GNU Classpath is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with GNU Classpath; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||||
|
USA
|
||||||
|
|
||||||
|
Linking this library statically or dynamically with other modules is
|
||||||
|
making a combined work based on this library. Thus, the terms and
|
||||||
|
conditions of the GNU General Public License cover the whole
|
||||||
|
combination.
|
||||||
|
|
||||||
|
As a special exception, the copyright holders of this library give you
|
||||||
|
permission to link this library with independent modules to produce an
|
||||||
|
executable, regardless of the license terms of these independent
|
||||||
|
modules, and to copy and distribute the resulting executable under
|
||||||
|
terms of your choice, provided that you also meet, for each linked
|
||||||
|
independent module, the terms and conditions of the license of that
|
||||||
|
module. An independent module is a module which is not derived from
|
||||||
|
or based on this library. If you modify this library, you may extend
|
||||||
|
this exception to your version of the library, but you are not
|
||||||
|
obligated to do so. If you do not wish to do so, delete this
|
||||||
|
exception statement from your version. */
|
||||||
|
|
||||||
|
|
||||||
|
package gnu.javax.crypto.jce.cipher;
|
||||||
|
|
||||||
|
import gnu.java.security.Registry;
|
||||||
|
import gnu.javax.crypto.jce.spec.BlockCipherParameterSpec;
|
||||||
|
import gnu.javax.crypto.key.GnuPBEKey;
|
||||||
|
import gnu.javax.crypto.mode.BaseMode;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.AlgorithmParameters;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.Key;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.AlgorithmParameterSpec;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.spec.PBEParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public abstract class PBE
|
||||||
|
extends CipherAdapter
|
||||||
|
{
|
||||||
|
MessageDigest hash;
|
||||||
|
|
||||||
|
protected PBE(String cipherName, String hashName)
|
||||||
|
{
|
||||||
|
super(cipherName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.hash = MessageDigest.getInstance(hashName);
|
||||||
|
}
|
||||||
|
catch (NoSuchAlgorithmException ignored)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(int opmode, Key key, SecureRandom random)
|
||||||
|
throws InvalidKeyException
|
||||||
|
{
|
||||||
|
if (! (key instanceof GnuPBEKey))
|
||||||
|
throw new InvalidKeyException("not a GNU PBE key");
|
||||||
|
GnuPBEKey k = (GnuPBEKey) key;
|
||||||
|
int c1 = k.getIterationCount();
|
||||||
|
byte[] s1 = k.getSalt();
|
||||||
|
PBEPKCS5_V1Params pkcs5 = genParams(c1, s1, k.getPassword());
|
||||||
|
initInternal(opmode, pkcs5.skSpec, pkcs5.ivSpec, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
|
||||||
|
SecureRandom random)
|
||||||
|
throws InvalidKeyException, InvalidAlgorithmParameterException
|
||||||
|
{
|
||||||
|
if (! (key instanceof GnuPBEKey))
|
||||||
|
throw new InvalidKeyException("not a GNU PBE key");
|
||||||
|
GnuPBEKey k = (GnuPBEKey) key;
|
||||||
|
int c1 = k.getIterationCount();
|
||||||
|
byte[] s1 = k.getSalt();
|
||||||
|
if (params != null)
|
||||||
|
{
|
||||||
|
if (! (params instanceof PBEParameterSpec))
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"The algorithm-parameter-spec, when not null, MUST be of type "
|
||||||
|
+ "PBEParameterSpec or one of its subclasses");
|
||||||
|
PBEParameterSpec ps = (PBEParameterSpec) params;
|
||||||
|
// it must share the same salt and iteration count as the secret key
|
||||||
|
int c2 = ps.getIterationCount();
|
||||||
|
if (c1 == 0)
|
||||||
|
c1 = c2;
|
||||||
|
else if (c1 != c2)
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"The algorithm-parameter-spec and the key MUST share the same "
|
||||||
|
+ "iteration count");
|
||||||
|
byte[] s2 = ps.getSalt();
|
||||||
|
// salt may be unspecified
|
||||||
|
if (s1 == null)
|
||||||
|
s1 = s2;
|
||||||
|
else if ((s1 != null && s1.length > 0 && s2 == null)
|
||||||
|
|| (s1 == null && s2 != null && s2.length > 0)
|
||||||
|
|| (s1 != null && s2 != null && !Arrays.equals(s1, s2)))
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"The algorithm-parameter-spec and the key MUST share the same salt");
|
||||||
|
}
|
||||||
|
PBEPKCS5_V1Params pkcs5 = genParams(c1, s1, k.getPassword());
|
||||||
|
initInternal(opmode, pkcs5.skSpec, pkcs5.ivSpec, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
||||||
|
SecureRandom random) throws InvalidKeyException,
|
||||||
|
InvalidAlgorithmParameterException
|
||||||
|
{
|
||||||
|
if (! (key instanceof GnuPBEKey))
|
||||||
|
throw new InvalidKeyException("not a GNU PBE key");
|
||||||
|
GnuPBEKey k = (GnuPBEKey) key;
|
||||||
|
int c1 = k.getIterationCount();
|
||||||
|
byte[] s1 = k.getSalt();
|
||||||
|
if (params != null)
|
||||||
|
throw new InvalidAlgorithmParameterException(
|
||||||
|
"We [MUST] supply our own algorithm-parameter");
|
||||||
|
PBEPKCS5_V1Params pkcs5 = genParams(c1, s1, k.getPassword());
|
||||||
|
initInternal(opmode, pkcs5.skSpec, pkcs5.ivSpec, random);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initInternal(int opmode, SecretKeySpec key,
|
||||||
|
BlockCipherParameterSpec params,
|
||||||
|
SecureRandom random) throws InvalidKeyException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
super.engineInit(opmode, key, params, random);
|
||||||
|
} catch (InvalidAlgorithmParameterException x) {
|
||||||
|
// this should not happen since 'params' is generated by us with
|
||||||
|
// the genParams() method. if it does re-throw as IKE
|
||||||
|
throw new InvalidKeyException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PBEPKCS5_V1Params genParams(int c, byte[] s, char[] password)
|
||||||
|
throws InvalidKeyException
|
||||||
|
{
|
||||||
|
// transform the password's chars into bytes assuming UTF-8
|
||||||
|
byte[] p;
|
||||||
|
try {
|
||||||
|
p = new String(password).getBytes("UTF-8");
|
||||||
|
} catch (UnsupportedEncodingException x) {
|
||||||
|
throw new InvalidKeyException(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = cipher.name();
|
||||||
|
int blockSize = cipher.defaultBlockSize();
|
||||||
|
int keySize = cipher.defaultKeySize();
|
||||||
|
int hashSize = this.hash.getDigestLength();
|
||||||
|
Integer att_ivSize = (Integer) attributes.get(mode.MODE_BLOCK_SIZE);
|
||||||
|
int ivSize = (att_ivSize == null ? blockSize : att_ivSize.intValue());
|
||||||
|
|
||||||
|
// digest once
|
||||||
|
this.hash.update(p);
|
||||||
|
byte[] buffer = s == null ? this.hash.digest() : this.hash.digest(s);
|
||||||
|
|
||||||
|
// and now complete the remaining iterations
|
||||||
|
for (int i = 1; i < c; i++)
|
||||||
|
buffer = this.hash.digest(buffer);
|
||||||
|
|
||||||
|
PBEPKCS5_V1Params result = new PBEPKCS5_V1Params();
|
||||||
|
result.skSpec = new SecretKeySpec(buffer, 0, blockSize, name.substring(0, name.indexOf('-')));
|
||||||
|
byte[] iv = new byte[ivSize];
|
||||||
|
System.arraycopy(buffer, blockSize, iv, 0, hashSize - blockSize);
|
||||||
|
result.ivSpec = new BlockCipherParameterSpec(iv, blockSize, keySize);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PBEPKCS5_V1Params {
|
||||||
|
SecretKeySpec skSpec;
|
||||||
|
BlockCipherParameterSpec ivSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MD5
|
||||||
|
extends PBE
|
||||||
|
{
|
||||||
|
public MD5(String cipher)
|
||||||
|
{
|
||||||
|
super(cipher, "MD5");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DES
|
||||||
|
extends MD5
|
||||||
|
{
|
||||||
|
public DES()
|
||||||
|
{
|
||||||
|
// we really need a DES/CBC/PKCS5 combined padded block cipher
|
||||||
|
super(Registry.DES_CIPHER);
|
||||||
|
|
||||||
|
// the superclass's field 'cipher' has a plain DES-ECB so we need to
|
||||||
|
// change its mode and padding
|
||||||
|
try {
|
||||||
|
this.engineSetMode(Registry.CBC_MODE);
|
||||||
|
} catch (NoSuchAlgorithmException ignored) {
|
||||||
|
ignored.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
this.engineSetPadding(Registry.PKCS5_PAD);
|
||||||
|
} catch (NoSuchPaddingException ignored) {
|
||||||
|
ignored.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,11 +85,12 @@ public class GnuPBEKey
|
||||||
|
|
||||||
public String getFormat ()
|
public String getFormat ()
|
||||||
{
|
{
|
||||||
return "NONE"; // FIXME?
|
return "RAW";
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getEncoded ()
|
public byte[] getEncoded ()
|
||||||
{
|
{
|
||||||
return null; // FIXME?
|
String pass = new String(getPassword());
|
||||||
|
return pass.getBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,8 +91,11 @@ public class PBEKeySpec implements KeySpec
|
||||||
*/
|
*/
|
||||||
public PBEKeySpec(char[] password)
|
public PBEKeySpec(char[] password)
|
||||||
{
|
{
|
||||||
setPassword(password);
|
if (password == null)
|
||||||
|
password = new char[0];
|
||||||
|
|
||||||
|
setPassword(password.clone());
|
||||||
|
|
||||||
// load the default values for unspecified variables.
|
// load the default values for unspecified variables.
|
||||||
salt = null;
|
salt = null;
|
||||||
iterationCount = 0;
|
iterationCount = 0;
|
||||||
|
@ -114,8 +117,12 @@ public class PBEKeySpec implements KeySpec
|
||||||
*/
|
*/
|
||||||
public PBEKeySpec(char[] password, byte[] salt, int iterationCount)
|
public PBEKeySpec(char[] password, byte[] salt, int iterationCount)
|
||||||
{
|
{
|
||||||
setPassword(password);
|
if (password == null)
|
||||||
setSalt(salt);
|
password = new char[0];
|
||||||
|
|
||||||
|
setPassword(password.clone());
|
||||||
|
|
||||||
|
setSalt(salt.clone());
|
||||||
setIterationCount(iterationCount);
|
setIterationCount(iterationCount);
|
||||||
|
|
||||||
// load default values into unspecified variables.
|
// load default values into unspecified variables.
|
||||||
|
@ -140,8 +147,12 @@ public class PBEKeySpec implements KeySpec
|
||||||
public PBEKeySpec(char[] password, byte[] salt, int iterationCount,
|
public PBEKeySpec(char[] password, byte[] salt, int iterationCount,
|
||||||
int keyLength)
|
int keyLength)
|
||||||
{
|
{
|
||||||
setPassword(password);
|
if (password == null)
|
||||||
setSalt(salt);
|
password = new char[0];
|
||||||
|
|
||||||
|
setPassword(password.clone());
|
||||||
|
|
||||||
|
setSalt(salt.clone());
|
||||||
setIterationCount(iterationCount);
|
setIterationCount(iterationCount);
|
||||||
setKeyLength(keyLength);
|
setKeyLength(keyLength);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче