Java tutorial
/* * //****************************************************************** * // * // Copyright 2016 Samsung Electronics All Rights Reserved. * // * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * // * // Licensed under the Apache License, Version 2.0 (the "License"); * // you may not use this file except in compliance with the License. * // You may obtain a copy of the License at * // * // http://www.apache.org/licenses/LICENSE-2.0 * // * // Unless required by applicable law or agreed to in writing, software * // distributed under the License is distributed on an "AS IS" BASIS, * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * // See the License for the specific language governing permissions and * // limitations under the License. * // * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ package org.iotivity.cloud.accountserver.resources.account.credprov.cert; import org.bouncycastle.util.encoders.Base64; import org.iotivity.cloud.accountserver.Constants; import org.iotivity.cloud.accountserver.db.AccountDBManager; import org.iotivity.cloud.accountserver.db.TokenTable; import org.iotivity.cloud.accountserver.resources.account.credprov.crl.CrlResourceTest; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateResource; import org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateStorage; import org.iotivity.cloud.accountserver.resources.credprov.crl.CrlResource; import org.iotivity.cloud.accountserver.util.TypeCastingManager; import org.iotivity.cloud.accountserver.x509.cert.Utility; import org.iotivity.cloud.base.OICConstants; import org.iotivity.cloud.base.device.CoapDevice; import org.iotivity.cloud.base.protocols.IRequest; import org.iotivity.cloud.base.protocols.IResponse; import org.iotivity.cloud.base.protocols.MessageBuilder; import org.iotivity.cloud.base.protocols.coap.CoapResponse; import org.iotivity.cloud.base.protocols.enums.ContentFormat; import org.iotivity.cloud.base.protocols.enums.RequestMethod; import org.iotivity.cloud.base.protocols.enums.ResponseStatus; import org.iotivity.cloud.util.Cbor; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigInteger; import java.security.cert.*; import java.util.*; import java.util.concurrent.CountDownLatch; import static org.iotivity.cloud.accountserver.resources.credprov.cert.CertificateConstants.*; import static org.junit.Assert.*; import static org.mockito.Mockito.mock; public class CertificateResourceTest { private static final String COMMON_NAME = "OU=OCF Device CA, O=Samsung, C=KR, CN=uuid:B371C481-38E6-4D47-8320-7688D8A5B58C"; private static final String CERTIFICATE_URI = OICConstants.CREDPROV_CERT_FULL_URI; private static final String DEVICE_ID = "B371C481-38E6-4D47-8320-7688D8A5B58C"; private CoapDevice mMockDevice = mock(CoapDevice.class); private Cbor<HashMap<String, Object>> mCbor = new Cbor<>(); private IResponse mResponse = null; private CountDownLatch mLatch = new CountDownLatch(1); private static CertificateResource certificateResource = new CertificateResource(); private byte[] csr; private static TypeCastingManager<TokenTable> castingManager = new TypeCastingManager<>(); static void createToken() { TokenTable certificateTable = new TokenTable(); certificateTable.setDid(DEVICE_ID); certificateTable.setUuid("uuid:" + DEVICE_ID); AccountDBManager.getInstance().insertRecord(Constants.TOKEN_TABLE, castingManager.convertObjectToMap(certificateTable)); } @AfterClass public static void after() { KEYSTORE_FILE.delete(); } @BeforeClass public static void setUpBefore() { createToken(); } /** * DERSequence othernameSequence = new DERSequence(new ASN1Encodable[]{ * new ASN1ObjectIdentifier("1.3.6.1.5.5.7.8.5"), new DERTaggedObject(true, 0, new DERUTF8String(subjectAltName))}); * GeneralName othernameGN = new GeneralName(GeneralName.otherName, othernameSequence); * ASN1Encodable[] subjectAlternativeNames = new ASN1Encodable[] * { * othernameGN * <p> * <p> * }; * DERSequence subjectAlternativeNamesExtension = new DERSequence(othernameGN); * return buildOne(Extension.subjectAlternativeName, true, subjectAlternativeNamesExtension, issuerNameBld.build()); */ @Test public void testLoad() { try { Method m = CertificateStorage.class.getDeclaredMethod("load"); m.setAccessible(true); m.invoke(null); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { e.printStackTrace(); } } @Before public void setUp() throws Exception { csr = GenerateCSR.generatePKCS10(COMMON_NAME, false); MockitoAnnotations.initMocks(this); // callback mock Mockito.doAnswer(new Answer<Object>() { @Override public CoapResponse answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); CoapResponse resp = (CoapResponse) args[0]; mResponse = resp; mLatch.countDown(); return null; } }).when(mMockDevice).sendResponse(Mockito.anyObject()); } @Test(expected = AssertionError.class) public void testErrorConstruction() { Constructor<CertificateStorage> constructor; try { constructor = CertificateStorage.class.getDeclaredConstructor(); constructor.setAccessible(true); constructor.newInstance(); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { throw new AssertionError(); } } @Test(expected = AssertionError.class) public void testErrorConstructionUtility() { Constructor<Utility> constructor; try { constructor = Utility.class.getDeclaredConstructor(); constructor.setAccessible(true); constructor.newInstance(); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { throw new AssertionError(); } } @Test(expected = AssertionError.class) public void testErrorConstructionCertificateConstants() { Constructor<CertificateConstants> constructor; try { constructor = CertificateConstants.class.getDeclaredConstructor(); constructor.setAccessible(true); constructor.newInstance(); } catch (NoSuchMethodException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } catch (InvocationTargetException e) { throw new AssertionError(); } } /** * DERUTF8String derDomainName = new DERUTF8String("hello.world"); * DERTaggedObject derTaggedDomainName = new DERTaggedObject(0, derDomainName); * DLSequence otherName = new DLSequence(new ASN1Encodable[]{new ASN1ObjectIdentifier("1.3.6.1.5.5.7.9.3"), derTaggedDomainName}); * GeneralNames generalNames = new GeneralNames(new GeneralName(GeneralName.otherName, otherName)); * * @throws Exception */ @Test public void testCSRIssueDER() throws Exception { getTestMethodName(); IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); Map<String, Object> payloadData = mCbor.parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); assertTrue(hashmapCheck(mResponse, Constants.REQ_DEVICE_ID)); assertTrue(hashmapCheck(mResponse, Constants.CERT)); assertTrue(hashmapCheck(mResponse, Constants.CERT_CHAIN)); Map<String, Object> certMap = (Map<String, Object>) payloadData.get(Constants.CERT); InputStream in = new ByteArrayInputStream((byte[]) certMap.get(Constants.DATA)); X509Certificate personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); personaleCert.verify(CertificateStorage.ROOT_CERTIFICATE.getPublicKey()); assertEquals(COMMON_NAME, personaleCert.getSubjectDN().getName()); String encoding = certMap.get(Constants.ENCODING).toString(); assertEquals(CertificateConstants.DER, encoding); assertEquals(personaleCert.getPublicKey(), GenerateCSR.getPublicKey()); certMap = (Map<String, Object>) payloadData.get(Constants.CERT_CHAIN); encoding = certMap.get(Constants.ENCODING).toString(); assertEquals(CertificateConstants.DER, encoding); in = new ByteArrayInputStream((byte[]) certMap.get(Constants.DATA)); X509Certificate caCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); assertEquals(caCert, CertificateStorage.ROOT_CERTIFICATE); assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); } @Test public void testCSRIssueDERFailed() throws Exception { getTestMethodName(); IRequest request = csrRequestFailed(DEVICE_ID, RequestMethod.POST); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST)); } @Test public void testCSRIssueDERFailedSignature() throws Exception { byte[] csr = GenerateCSR.generatePKCS10(COMMON_NAME, true); getTestMethodName(); IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST)); } Map<String, Object> payloadData; Map<String, Object> crlMap; byte[] data; X509CRL crlX509; @Test public void testReIssueBase64() throws CRLException, CertificateException { IRequest request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); Map<String, Object> payloadData = mCbor.parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); List<BigInteger> serialNumbers = new ArrayList<>(); Map<String, Object> certMap = (Map<String, Object>) payloadData.get(Constants.CERT); InputStream in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA))); X509Certificate personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); serialNumbers.add(personaleCert.getSerialNumber()); serialNumbers.add(personaleCert.getSerialNumber().subtract(BigInteger.ONE)); request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); payloadData = mCbor.parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); certMap = (Map<String, Object>) payloadData.get(Constants.CERT); in = new ByteArrayInputStream(Base64.decode((byte[]) certMap.get(Constants.DATA))); personaleCert = (X509Certificate) CERTIFICATE_FACTORY.generateCertificate(in); serialNumbers.add(personaleCert.getSerialNumber()); request = csrRequest(DEVICE_ID, CertificateConstants.BASE_64, Base64.encode(csr), RequestMethod.POST, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.CHANGED)); getTestMethodName(); request = CrlResourceTest.crlRequest(RequestMethod.GET, CrlResourceTest.CRL_URI, CrlResourceTest.CRL_URI_QUERY); CrlResource crlResource = new CrlResource(); crlResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.CONTENT)); hashmapCheck(mResponse, Constants.ENCODING); hashmapCheck(mResponse, Constants.DATA); if (mResponse.getPayload() != null) { payloadData = mCbor.parsePayloadFromCbor(mResponse.getPayload(), HashMap.class); crlMap = (Map<String, Object>) payloadData.get(Constants.REQ_CRL); data = (byte[]) crlMap.get(Constants.DATA); crlX509 = (X509CRL) CERTIFICATE_FACTORY.generateCRL(new ByteArrayInputStream(data)); } assertEquals(DER, crlMap.get(Constants.ENCODING)); assertNotNull(data); Set<? extends X509CRLEntry> entries = crlX509.getRevokedCertificates(); Iterator<? extends X509CRLEntry> iterator = entries.iterator(); while (iterator.hasNext()) { assertTrue(serialNumbers.contains(iterator.next().getSerialNumber())); } } @Test public void testMethodNotAllowed() { IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.GET, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.METHOD_NOT_ALLOWED)); } @Test public void testBadRequest() { IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, csr, RequestMethod.POST, false); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST)); } @Test public void testBadData() { IRequest request = csrRequest(DEVICE_ID, CertificateConstants.DER, null, RequestMethod.POST, true); certificateResource.onDefaultRequestReceived(mMockDevice, request); assertTrue(methodCheck(mResponse, ResponseStatus.BAD_REQUEST)); } private void getTestMethodName() { StackTraceElement[] stacks = new Throwable().getStackTrace(); StackTraceElement currentStack = stacks[1]; System.out.println("\t---Test Name : " + currentStack.getMethodName()); } private IRequest csrRequestFailed(String deviceId, RequestMethod method) { IRequest request; HashMap<String, Object> payloadData = new HashMap<>(); payloadData.put(Constants.REQ_DEVICE_ID, deviceId); payloadData.put("csr", "csr"); request = MessageBuilder.createRequest(method, CERTIFICATE_URI, null, ContentFormat.APPLICATION_CBOR, mCbor.encodingPayloadToCbor(payloadData)); return request; } private IRequest csrRequest(String deviceId, String encoding, byte[] data, RequestMethod method, boolean isEncoded) { IRequest request; HashMap<String, Object> payloadData = new HashMap<>(); payloadData.put(Constants.REQ_DEVICE_ID, deviceId); CSR csr = new CSR(); if (isEncoded) { csr.setEncoding(encoding); csr.setData(data); payloadData.put("csr", csr); } request = MessageBuilder.createRequest(method, CERTIFICATE_URI, null, ContentFormat.APPLICATION_CBOR, mCbor.encodingPayloadToCbor(payloadData)); return request; } private static class CSR { String encoding; byte[] data; public String getEncoding() { return encoding; } public void setEncoding(String encoding) { this.encoding = encoding; } public byte[] getData() { return data; } public void setData(byte[] data) { this.data = data; } @Override public String toString() { return "CSR{" + "encoding='" + encoding + '\'' + ", data=" + Arrays.toString(data) + '}'; } } private boolean methodCheck(IResponse response, ResponseStatus responseStatus) { if (responseStatus == response.getStatus()) return true; else return false; } private boolean hashmapCheck(IResponse response, String propertyName) { HashMap<String, Object> payloadData = mCbor.parsePayloadFromCbor(response.getPayload(), HashMap.class); if (payloadData.containsKey(propertyName)) return true; else return false; } }