org.xwiki.crypto.x509.DefautX509CryptoServiceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.xwiki.crypto.x509.DefautX509CryptoServiceTest.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.xwiki.crypto.x509;

import java.security.GeneralSecurityException;
import java.security.cert.CertificateExpiredException;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.xwiki.configuration.ConfigurationSource;
import org.xwiki.crypto.internal.BouncyCastleJcaProvider;
import org.xwiki.crypto.internal.UserDocumentUtils;
import org.xwiki.crypto.passwd.internal.DefaultPasswordCryptoService;
import org.xwiki.crypto.passwd.internal.DefaultPasswordCryptoServiceConfiguration;
import org.xwiki.crypto.x509.internal.DefaultX509CryptoService;
import org.xwiki.test.annotation.BeforeComponent;
import org.xwiki.test.annotation.ComponentList;
import org.xwiki.test.mockito.MockitoComponentManagerRule;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;

@ComponentList({ BouncyCastleJcaProvider.class, DefaultPasswordCryptoServiceConfiguration.class,
        DefaultPasswordCryptoService.class, DefaultX509CryptoService.class })
public class DefautX509CryptoServiceTest {
    @Rule
    public final MockitoComponentManagerRule componentManager = new MockitoComponentManagerRule();

    private X509CryptoService service;

    @BeforeComponent
    public void initializeMocks() throws Exception {
        componentManager.registerMockComponent(ConfigurationSource.class);
        UserDocumentUtils documentUtils = componentManager.registerMockComponent(UserDocumentUtils.class);
        when(documentUtils.getCurrentUser()).thenReturn("xwiki:XWiki.Me");
        when(documentUtils.getUserDocURL(any(String.class))).thenReturn("http://www.my.web.id");
    }

    @Before
    public void configure() throws Exception {
        service = componentManager.getInstance(X509CryptoService.class);
    }

    /** Storing a single keypair for as many tests as possible because they take a long time to generate. */
    private static XWikiX509KeyPair keyPair;

    private XWikiX509KeyPair getKeyPair() throws GeneralSecurityException {
        if (keyPair == null) {
            keyPair = service.newCertAndPrivateKey(1, SampleTestData.PASSWORD);
        }
        return keyPair;
    }

    @Test
    public void testNewCertAndPrivateKeyWithCorrectPassword() throws GeneralSecurityException {
        Assert.assertNotNull("Private key is null", getKeyPair().getPrivateKey(SampleTestData.PASSWORD));
    }

    @Test
    public void testNewCertAndPrivateKeyWithWrongPassword() {
        try {
            Assert.assertNotNull("Private key is null", getKeyPair().getPrivateKey("asdf"));
        } catch (GeneralSecurityException exception) {
            Assert.assertTrue(exception.getMessage()
                    .contains("Could not decrypt private key, " + "wrong password or corrupted file."));
        }
    }

    @Test
    public void testNewCertIsValid() throws GeneralSecurityException {
        XWikiX509Certificate cert = getKeyPair().getCertificate();
        cert.checkValidity();
        cert.verify(cert.getPublicKey());
    }

    @Test(expected = CertificateExpiredException.class)
    public void testNewCertIsExpired() throws GeneralSecurityException {
        XWikiX509KeyPair keyPair = service.newCertAndPrivateKey(0, "bla");
        XWikiX509Certificate cert = keyPair.getCertificate();
        cert.verify(cert.getPublicKey());
        cert.checkValidity();
    }

    @Test
    public void testCertFromPEM() throws GeneralSecurityException {
        XWikiX509Certificate cert = service.certFromPEM(SampleTestData.CERT_PEM);
        Assert.assertEquals("Imported certificate has incorrect fingerprint", SampleTestData.CERT_SHA1,
                cert.getFingerprint());
    }

    @Test
    public void testKeyPairFromBase64() throws Exception {
        XWikiX509KeyPair imported = service.keyPairFromBase64(SampleTestData.KEY_PAIR_EXPORTED_AS_BASE_64);
        Assert.assertNotNull(imported.getPrivateKey(SampleTestData.PASSWORD));
        XWikiX509Certificate cert = imported.getCertificate();
        Assert.assertEquals("Certificate from the imported KP has not the correct Fingerprint",
                SampleTestData.CERTIFICATE_FINGERPRINT, cert.getFingerprint());
        Assert.assertEquals("Certificate from the imported KP does not have the correct author UID",
                "xwiki:XWiki.Me", cert.getAuthorUID());
        Assert.assertEquals("The imported public key does not match the certificate", cert.getPublicKey(),
                imported.getPublicKey());
        Assert.assertEquals("The key pair reported fingerprint does not match the certificate",
                cert.getFingerprint(), imported.getFingerprint());
    }

    @Test
    public void testKeyPairExportImportReciprocity() throws Exception {
        XWikiX509KeyPair keyPair = getKeyPair();

        final String exported = keyPair.serializeAsBase64();
        final XWikiX509KeyPair imported = service.keyPairFromBase64(exported);

        Assert.assertEquals("Private keys mismatch", keyPair.getPrivateKey(SampleTestData.PASSWORD),
                imported.getPrivateKey(SampleTestData.PASSWORD));
        Assert.assertEquals("Public keys mismatch", keyPair.getPublicKey(), imported.getPublicKey());
        Assert.assertEquals("Certificates mismatch", keyPair.getCertificate(), imported.getCertificate());
        Assert.assertEquals("KeyPairs mismatch", keyPair, imported);
        Assert.assertEquals("Serialized keypairs mismatch", keyPair.serializeAsBase64(),
                imported.serializeAsBase64());
    }

    @Test
    public void testSignTextAndVerifySameText() throws GeneralSecurityException {
        XWikiX509KeyPair keyPair = getKeyPair();
        String signature = service.signText("hello world", keyPair, SampleTestData.PASSWORD);
        XWikiX509Certificate cert = service.verifyText("hello world", signature);
        Assert.assertNotNull("Signtext/verifyText, failed when they should have succeeded.", cert);
        Assert.assertTrue("Signtext/verifytext returning incorrect certificate.",
                cert.getFingerprint().equals(keyPair.getCertificate().getFingerprint()));
        Assert.assertTrue("XWikiX509Certificate.equals returns false when fingerprints are the same.",
                cert.equals(keyPair.getCertificate()));
    }

    @Test
    public void testSignTextAndVerifyWrongText() throws GeneralSecurityException {
        XWikiX509KeyPair keyPair = getKeyPair();
        String signature = service.signText("hello world", keyPair, SampleTestData.PASSWORD);
        XWikiX509Certificate cert = service.verifyText("Wrong Text", signature);
        Assert.assertNull("Signtext/verifyText, succeeded with wrong text!", cert);
    }

    @Test
    public void verifyTextSignedInBrowser() throws GeneralSecurityException {
        XWikiX509Certificate cert = service.certFromPEM(SampleTestData.BROWSER_CERT);
        XWikiX509Certificate verifyResponse = service.verifyText(SampleTestData.BROWSER_SIGNED_TEXT,
                SampleTestData.BROWSER_SIGNATURE);
        Assert.assertTrue("Signtext/verifytext returning incorrect certificate.",
                cert.getFingerprint().equals(verifyResponse.getFingerprint()));
        Assert.assertTrue("XWikiX509Certificate.equals returns false when fingerprints are the same.",
                cert.equals(verifyResponse));
    }

    @Test
    public void testCertsFromSpkacTest() throws Exception {
        XWikiX509Certificate[] certs = service.certsFromSpkac(SampleTestData.SPKAC_SERIALIZATION, 1);

        // verify client
        certs[0].checkValidity();
        certs[0].verify(certs[1].getPublicKey());

        // verify authority
        certs[1].checkValidity();
        certs[1].verify(certs[1].getPublicKey());

        // read Basic Constraints to check second certificate is a CA
        DEROctetString obj = (DEROctetString) new ASN1InputStream(certs[1].getExtensionValue("2.5.29.19"))
                .readObject();
        ASN1Sequence seq = (ASN1Sequence) new ASN1InputStream(obj.getOctets()).readObject();
        BasicConstraints constraints = BasicConstraints.getInstance(seq);
        Assert.assertTrue("Second certificate should be a CA certificate", constraints.isCA());
    }
}