/**
* WS-Attacker - A Modular Web Services Penetration Testing Framework Copyright
* (C) 2013 Juraj Somorovsky
*
* This program 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.
*
* This program 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
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package wsattacker.library.signatureFaking.helper;
import java.io.*;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
import java.util.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateAlgorithmId;
import sun.security.x509.CertificateIssuerName;
import sun.security.x509.CertificateSerialNumber;
import sun.security.x509.CertificateSubjectName;
import sun.security.x509.CertificateValidity;
import sun.security.x509.CertificateVersion;
import sun.security.x509.CertificateX509Key;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CertInfo;
import wsattacker.library.signatureFaking.exceptions.CertificateHandlerException;
/**
* @author Juraj Somorovsky - juraj.somorovsky@rub.de
* @version 0.1
*/
public class CertificateHandler
{
private X509Certificate certificate;
private PublicKey originalPublicKey;
private X509CertImpl fakedCertificate;
private KeyPair fakedKeyPair;
private CertificateFactory certFactory;
Logger log = Logger.getLogger( CertificateHandler.class );
public CertificateHandler( final String cert )
throws CertificateHandlerException
{
try
{
certFactory = CertificateFactory.getInstance( "X.509" );
certificate =
(X509Certificate) certFactory.generateCertificate( new ByteArrayInputStream( Base64.decodeBase64( cert ) ) );
originalPublicKey = certificate.getPublicKey();
}
catch ( CertificateException e )
{
throw new CertificateHandlerException( e );
}
}
public void createFakedCertificate()
throws CertificateHandlerException
{
try
{
log.debug( "Faking the found certificate" );
// TODO: implement this with bouncy castle
KeyPairGenerator kpg = KeyPairGenerator.getInstance( originalPublicKey.getAlgorithm() );
kpg.initialize( ( (RSAPublicKey) certificate.getPublicKey() ).getModulus().bitLength() );
fakedKeyPair = kpg.generateKeyPair();
X509CertInfo info = new X509CertInfo();
CertificateValidity interval =
new CertificateValidity( certificate.getNotBefore(), certificate.getNotAfter() );
// TODO: new SecureRandom().generateSeed(64) is very slow! Replace
// it?
// BigInteger sn = new BigInteger(new
// SecureRandom().generateSeed(64));
BigInteger sn = new BigInteger( 64, new Random() );
X500Name owner = new X500Name( certificate.getSubjectDN().getName() );
X500Name issuer = new X500Name( certificate.getIssuerDN().getName() );
info.set( X509CertInfo.VALIDITY, interval );
info.set( X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber( sn ) );
// API Change in Java7 vs Java8
try
{
info.set( X509CertInfo.SUBJECT, new CertificateSubjectName( owner ) );
info.set( X509CertInfo.ISSUER, new CertificateIssuerName( issuer ) );
}
catch ( Exception e )
{
info.set( X509CertInfo.SUBJECT, owner );
info.set( X509CertInfo.ISSUER, issuer );
}
info.set( X509CertInfo.KEY, new CertificateX509Key( fakedKeyPair.getPublic() ) );
info.set( X509CertInfo.VERSION, new CertificateVersion( CertificateVersion.V3 ) );
AlgorithmId algo = new AlgorithmId( new ObjectIdentifier( certificate.getSigAlgOID() ) );
info.set( X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId( algo ) );
// Sign the cert to identify the algorithm that's used.
fakedCertificate = new X509CertImpl( info );
fakedCertificate.sign( fakedKeyPair.getPrivate(), certificate.getSigAlgName() );
}
catch ( CertificateException e )
{
throw new CertificateHandlerException( e );
}
catch ( IOException e )
{
throw new CertificateHandlerException( e );
}
catch ( InvalidKeyException e )
{
throw new CertificateHandlerException( e );
}
catch ( NoSuchAlgorithmException e )
{
throw new CertificateHandlerException( e );
}
catch ( NoSuchProviderException e )
{
throw new CertificateHandlerException( e );
}
catch ( SignatureException e )
{
throw new CertificateHandlerException( e );
}
}
public PublicKey getOriginalPublicKey()
{
return originalPublicKey;
}
public void setOriginalPublicKey( PublicKey originalPublicKey )
{
this.originalPublicKey = originalPublicKey;
}
public X509CertImpl getFakedCertificate()
{
return fakedCertificate;
}
public void setFakedCertificate( X509CertImpl fakedCertificate )
{
this.fakedCertificate = fakedCertificate;
}
public KeyPair getFakedKeyPair()
{
return fakedKeyPair;
}
public void setFakedKeyPair( KeyPair fakedKeyPair )
{
this.fakedKeyPair = fakedKeyPair;
}
public String getFakedCertificateString()
throws CertificateHandlerException
{
try
{
return new String( Base64.encodeBase64( fakedCertificate.getEncoded() ) );
}
catch ( CertificateEncodingException e )
{
throw new CertificateHandlerException( e );
}
}
}