Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 18b2e13

Browse files
FAB-4454 Increase test coverage for sdk.security
. Increased test coverage for CryptoPrimitives . Added new methods to TestUtils . Minor changes to main code to facilitate unit tests . Fixed minor issue with Config ExtraLogLevel . Set ExtraLogLevel to 10 in cirun.sh to help ensure logger output is covered Change-Id: I75e507b41339cbaffe4ba21206153883ccb9f75d Signed-off-by: Chris Murphy <chrism@fast.au.fujitsu.com>
1 parent 44b97b6 commit 18b2e13

File tree

5 files changed

+216
-22
lines changed

5 files changed

+216
-22
lines changed

src/main/java/org/hyperledger/fabric/sdk/helper/Config.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ public boolean extraLogLevel(int val) {
287287
extraLogLevel = Integer.parseInt(getProperty(EXTRALOGLEVEL));
288288
}
289289

290-
return val < extraLogLevel;
290+
return val <= extraLogLevel;
291291

292292
}
293293
}

src/main/java/org/hyperledger/fabric/sdk/security/CryptoPrimitives.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -249,10 +249,15 @@ public KeyStore getTrustStore() throws CryptoException {
249249
*/
250250
public void addCACertificateToTrustStore(File caCertPem, String alias) throws CryptoException, InvalidArgumentException {
251251

252+
if (caCertPem == null) {
253+
throw new InvalidArgumentException("The certificate cannot be null");
254+
}
255+
252256
if (alias == null || alias.isEmpty()) {
253-
throw new InvalidArgumentException("You must assign an alias to a certificate when adding to the trust store.");
257+
throw new InvalidArgumentException("You must assign an alias to a certificate when adding to the trust store");
254258
}
255259

260+
256261
BufferedInputStream bis;
257262
try {
258263

@@ -304,9 +309,8 @@ public void loadCACertificates(Collection<Certificate> certificates) throws Cryp
304309
addCACertificateToTrustStore(cert, Integer.toString(cert.hashCode()));
305310
}
306311
} catch (InvalidArgumentException e) {
307-
String emsg = "Unable to add certificate to trust store. Error: " + e.getMessage();
308-
logger.error(emsg, e);
309-
throw new CryptoException(emsg, e);
312+
// Note: This can currently never happen (as cert<>null and alias<>null)
313+
throw new CryptoException("Unable to add certificate to trust store. Error: " + e.getMessage(), e);
310314
}
311315
}
312316

@@ -361,9 +365,6 @@ boolean validateCertificate(Certificate cert) {
361365

362366
try {
363367
KeyStore keyStore = getTrustStore();
364-
if (keyStore == null) {
365-
throw new CryptoException("Crypto does not have a trust store. No certificate can be validated", null);
366-
}
367368

368369
PKIXParameters parms = new PKIXParameters(keyStore);
369370
parms.setRevocationEnabled(false);
@@ -708,11 +709,10 @@ public void init() throws CryptoException, InvalidArgumentException {
708709
private Digest getHashDigest() {
709710
if (this.hashAlgorithm.equalsIgnoreCase("SHA3")) {
710711
return new SHA3Digest();
711-
} else if (this.hashAlgorithm.equalsIgnoreCase("SHA2")) {
712+
} else {
713+
// Default to SHA2
712714
return new SHA256Digest();
713715
}
714-
715-
return new SHA256Digest(); // default Digest?
716716
}
717717

718718
// /**
@@ -795,15 +795,17 @@ public Properties getProperties() {
795795

796796
public byte[] certificateToDER(String certificatePEM) {
797797

798+
byte[] content = null;
799+
798800
try (PemReader pemReader = new PemReader(new StringReader(certificatePEM))) {
799801
final PemObject pemObject = pemReader.readPemObject();
800-
return pemObject.getContent();
802+
content = pemObject.getContent();
801803

802804
} catch (IOException e) {
803805
// best attempt
804806
}
805-
return null;
806807

808+
return content;
807809
}
808810

809811
}

src/test/cirun.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export ORG_HYPERLEDGER_FABRIC_SDKTEST_INTEGRATIONTESTS_CA_TLS=--tls.enabled
1515

1616
export ORG_HYPERLEDGER_FABRIC_SDK_LOGLEVEL=TRACE
1717
export ORG_HYPERLEDGER_FABRIC_CA_SDK_LOGLEVEL=TRACE
18+
export ORG_HYPERLEDGER_FABRIC_SDK_LOG_EXTRALOGLEVEL=10
1819

1920
cd $WD/src/test/fixture/sdkintegration
2021
./fabric.sh restart >dockerlogfile.log 2>&1 &

src/test/java/org/hyperledger/fabric/sdk/security/CryptoPrimitivesTest.java

Lines changed: 145 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import java.io.FileInputStream;
2121
import java.io.FileReader;
2222
import java.io.IOException;
23+
import java.nio.file.Files;
24+
import java.nio.file.Path;
25+
import java.nio.file.Paths;
2326
import java.security.KeyFactory;
2427
import java.security.KeyPair;
2528
import java.security.KeyStore;
@@ -44,14 +47,19 @@
4447
import org.bouncycastle.openssl.PEMParser;
4548
import org.bouncycastle.operator.OperatorCreationException;
4649
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
50+
import org.bouncycastle.util.encoders.Hex;
4751
import org.hyperledger.fabric.sdk.exception.CryptoException;
4852
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
4953
import org.hyperledger.fabric.sdk.helper.Config;
54+
import org.hyperledger.fabric.sdk.testutils.TestUtils;
5055
import org.junit.Assert;
5156
import org.junit.Before;
5257
import org.junit.BeforeClass;
5358
import org.junit.Ignore;
59+
import org.junit.Rule;
5460
import org.junit.Test;
61+
import org.junit.rules.ExpectedException;
62+
import org.junit.rules.TemporaryFolder;
5563

5664
import static java.nio.charset.StandardCharsets.UTF_8;
5765
import static org.junit.Assert.assertEquals;
@@ -64,6 +72,15 @@
6472

6573
public class CryptoPrimitivesTest {
6674

75+
@Rule
76+
public ExpectedException thrown = ExpectedException.none();
77+
78+
// Create a temp folder to hold temp files for various file I/O operations
79+
// These are automatically deleted when each test completes
80+
@Rule
81+
public final TemporaryFolder tempFolder = new TemporaryFolder();
82+
83+
6784
// run End2EndIT test and copy from first peer ProposalResponse ( fabric at
6885
// commit level 230f3cc )
6986
public static final String PLAIN_TEXT_HEX = "0A205E87B04D3B137E4F2BD2B7E435C96D86E62F3DA5147863A2051F39803AB519BD12E60F0AE30F02046C636363010D6578616D706C655F63632E676F00010D6578616D706C655F63632E676F009D0F0A0D6578616D706C655F63632E676F1201301A880F0A2B0801120F120D6578616D706C655F63632E676F1A160A04696E69740A01610A033130300A01620A03323030120708B2B4FFAF9D2B1ACF0E1F8B08000000000000FFED586D73DA4610CE57F42BB69A26869420C0A49E71EB0F603B2D93165C709A64624FE610075C2D24727702D34EFE7B77EF2410183B4E4CD2990E3B9380B8BBBD67DF9E5DF924F2AFB81C88803FFA6A52AE94CB3FD66A50B6B2FE59AE1E54A0B25FAE552BFBD5F2F30328572ACF0F6A8FA0FCF5202D25569AC947E507DFB56EDC16A07D0B79D169FF0EA3F984CB80F7875C7A03D693C27FE6FB3C9C3A8072DC3E7B0B25F8FE97F659FDFC574F49DFEBC522E83FF3474C847ED4E79ED9F7BADD7979D2ECA41BCD6F9D572D18462042747210C0DA3980274F603C5DA8EE89705DF5CA1ABF66E349C0DFFB7E6918FDD78EFB9FC8B7F0E9DDF55FA9D69E574DFD570EF66BCF0FF6B1FEABD5DAC1AEFEBF85784F9DE36832976238D2D06CFC0EC7919C94A05AAEFC08752CD90E2D28E870C5E594F74B8EF39B406A50BC0F71D8E712F488437DC27CFC48568AF027974A4421544B65C8D3063759720B3F39F32886319B4318698815470542013520E0D73E9F68640BF0234C4AC1429FC34CE891B924515172DE260AA29E46960086BB27F834C8EE02A61D27978391D69343CF9BCD66256640962239F402BB4979BF358F4F5BDDD36708D4715E8501570A24FF100B89F6F5E6C02608C3673D0417B0194412D850725CD3446A3093428B705804150DF48C49EEF485D252F462BDE29F14141A9ADD801E6221B8F52E34BB2E34EADD66B7E8BC6E9EFFDA7E750EAFEB9D4EBD75DE3CED42BB8324DC3A699E37DB2D7C7A01F5D65B78D96C9D1481A377F0127E3D91841D010AF21C05AACBF9CAE583C8825113EE8B81F0D1A27018B32147869E7219A221806D602C14C54E21B4BE1388B1D04C9BE71BE6949CA79EE3A057AF48C91863E1380E5E1F490D7927E7722923A95CFC36186BFA40CBFD289CBA18197788C0E35E0903EDDDEC3E9E1F49EE2DFB8B1A89B1EB141CC7F3A04B06F2E3458348080C94F91D960BE679CC438BDFD178CB8DC38828F635FCE37C749C411CFA98ADF0746D53019AA1D079A5E31E1090D262A58B3F35438DE313F3715BFEDD656FAE31FD8DE105D49A7B5F0426870A0E8F80CE977EE1FA055E4380EA61FF8C4936E6785EE50B4E6ECA24D48BD02050140B1434F734D498635C25EB5316E016FC1FD34FD37A5D29AE6114057D3C93ECC2FB2D0674B41840C0C33CA128C0774750235839C9752C43084590A055A5169FE5DD26DA2525479784F1B887E1C6AAC2A331B95195E0F41A7387321E6A2E2246A7E51002B947B040FC6DF36D11362757872363FFBBF2253E18EC848D9C6132A154D79130D8DE552E0B062CAD234C447627D02512F403C7CC01D41EDB24675997589CB9468AA48A481A7722D9FFBA48B0164A6718603DC8BBE412C4F0B89FC494BE5E846E3113E782F5F16B641AEB5E6C57F42D320FB66A9C5C6A0BA6D859ACBBB4258FB96413329FDAD8D411CB93EA42E13E26DA006F52DDD8ACBAF199AAB33FE27F7717E11F3197F32FABC25B63F72ABC0AA359082A9E106B2125FB38A662A03E1AAA39972C54CC542BD2DB15573061732A052A8B374888023BE3404663A853401A7752C834BAE25F067F9030C667708909417A8EE2E00A03C0BD973B1607136F9860AD10C9CF50DD0E8F308D5A99D250CDDC9350061C21EE3E0FD02A8B1B4372621EA9390127669C5BFF53204C612C31E9923D6A7C6E5DB7F9860F94588B0BE849AC5C7043EF87452666D4AE6B1D634FFD22D474F086F24F458C250982038E7F65986120247A35F57911C638E7428FE3CCC129187BD6397B45D833E6E017E4AB3DBA7CCFE6FFEDB9BC4078572627C9FAEED276B38D898D9E4961A1676C866EB30FBE318B0B59AB6843D3DFAE61169765358882209AD909B30A21D6AD99B6A06231A595B0E89E95CBD506663C87E59FE907269FB21D818C6D9FB40F717EA6176F8ED07DD336466C8AEEA6E338DE1B3A37654E4BE959F22EC54AD92699219CA4B37C56837CC170B63713F310211BB8EEA264165751D17CB2D5DADAA117874184E368A2C626C3FBF5666ED327BFB8A140ADB4F109D31ADB33ADB105D31A779AD658310D237E86B517499B08FC9AFBB1997C736FB636EC601BC3410F2DCED4111B23606418BE24F5D551281326C4603E9EC11B6B1CFE603E7EA01FB6331AF51851E0FF613EF2BCF50929DD976827877527198F1DA5FE2277AD3AABB098B16E6F48B619DDCEFC998EFA50EE5FA7D9CA7668B6B224CFC3257B3ACB266CD2E28ACF978C69B306DFE6B3C99212031E7A18E7599765B961E3DC8BF8CC806BB8D864B0E4F44A4FD141B308A7E9D3C6F0CC2BD6EDB1FA70AF79F91EA14A3A6EDA8E6FF4E2BB9AE796A6446A91E91F782638E222EBA06BEDE0B6A159DEA73F7E598FFB0BAFEE7035A1FDEE3F17EE295973E11E5E6C6A05E615D0456AABE33FF7C2FDE8DEEE8B54F17244DDD8196FBFBF853B2C133FE0DA75F52DF4BBD19E5157BC70EBE69EC5C28D46BBBC37CBE836BF497D142A7EF858193ACF2048306622937D29A4BF2FE50D75A4F1A2ACC660499D0FD194F502D818BF2C1EE33B8A94343966CF2F4BEB101E2BD738CB38E7A3F35FFFA576273BD9C94E76B2939DEC64273BD9C94E1E26FF02F35EC2D1002800000D6578616D706C655F63632E676F000201610003313030016200033230300A0744454641554C54129A072D2D2D2D2D424547494E202D2D2D2D2D0A4D4949436A444343416A4B6741774942416749554245567773537830546D7164627A4E776C654E42427A6F4954307777436759494B6F5A497A6A3045417749770A667A454C4D416B474131554542684D4356564D78457A415242674E5642416754436B4E6862476C6D62334A7561574578466A415542674E564241635444564E680A62694247636D467559326C7A59323878487A416442674E5642416F54466B6C7564475679626D5630494664705A47646C64484D7349456C75597934784444414B0A42674E564241735441316458567A45554D4249474131554541784D4C5A586868625842735A53356A623230774868634E4D5459784D5445784D5463774E7A41770A5768634E4D5463784D5445784D5463774E7A4177576A426A4D517377435159445651514745774A56557A45584D4255474131554543424D4F546D3979644767670A5132467962327870626D45784544414F42674E564241635442314A68624756705A326778477A415A42674E5642416F54456B6835634756796247566B5A3256790A49455A68596E4A70597A454D4D416F474131554543784D44513039514D466B77457759484B6F5A497A6A3043415159494B6F5A497A6A304441516344516741450A4842754B73414F34336873344A4770466669474D6B422F7873494C54734F766D4E32576D77707350485A4E4C36773848576533784350517464472F584A4A765A0A2B433735364B457355424D337977355054666B7538714F42707A43427044414F42674E56485138424166384542414D4342614177485159445652306C424259770A464159494B7759424251554841774547434373474151554642774D434D41774741315564457745422F7751434D414177485159445652304F42425945464F46430A6463555A346573336C746943674156446F794C66567050494D42384741315564497751594D4261414642646E516A32716E6F492F784D55646E3176446D6447310A6E4567514D43554741315564455151654D427943436D31356147397A6443356A62323243446E6433647935746557687663335175593239744D416F47434371470A534D343942414D43413067414D4555434944663948626C34786E337A3445774E4B6D696C4D396C58324671346A5770416152564239374F6D56456579416945410A32356144505148474771324176684B54307776743038635831475447434962666D754C704D774B516A33383D0A2D2D2D2D2D454E44202D2D2D2D2D0A";
@@ -129,6 +146,29 @@ public void setUp() throws Exception {
129146
pem.close();
130147
}
131148

149+
// Tests initializing with an invalid certificate format
150+
@Test
151+
public void testInitInvalidCertFormat() throws Exception {
152+
153+
thrown.expect(CryptoException.class);
154+
155+
String oldVal = null;
156+
157+
try {
158+
// Set the cert format to something invalid
159+
oldVal = TestUtils.setConfigProperty(Config.CERTIFICATE_FORMAT, "abc123");
160+
161+
CryptoPrimitives crypto = new CryptoPrimitives();
162+
crypto.init();
163+
164+
} finally {
165+
166+
// Reset the property for subsequent tests
167+
TestUtils.setConfigProperty(Config.CERTIFICATE_FORMAT, oldVal);
168+
}
169+
}
170+
171+
132172
@Test
133173
public void testGetSetProperties() {
134174
CryptoPrimitives testCrypto = new CryptoPrimitives();
@@ -225,15 +265,42 @@ public void testSetTrustStoreDuplicateCert() {
225265
}
226266
}
227267

268+
@Test
269+
public void testSetTrustStoreDuplicateCertUsingFile() {
270+
try {
271+
// Read the certificate data
272+
java.net.URL certUrl = this.getClass().getResource("/ca.crt");
273+
String certData = org.apache.commons.io.IOUtils.toString(certUrl, "UTF-8");
274+
275+
// Write this to a temp file
276+
File tempFile = tempFolder.newFile("temp.txt");
277+
Path tempPath = Paths.get(tempFile.getAbsolutePath());
278+
Files.write(tempPath, certData.getBytes());
279+
280+
crypto.addCACertificateToTrustStore(tempFile, "ca"); //KeyStore overrides existing cert if same alias
281+
} catch (Exception e) {
282+
fail("testSetTrustStoreDuplicateCert should not have thrown Exception. Error: " + e.getMessage());
283+
}
284+
}
285+
228286
@Test (expected = InvalidArgumentException.class)
229-
public void testAddCACertificateToTrustStoreNoAlias() throws InvalidArgumentException {
287+
public void testAddCACertificateToTrustStoreNullAlias() throws InvalidArgumentException {
230288
try {
231289
crypto.addCACertificateToTrustStore(new File("something"), null);
232290
} catch (CryptoException e) {
233291
fail("testAddCACertificateToTrustStoreNoAlias should not throw CryptoException. Error: " + e.getMessage());
234292
}
235293
}
236294

295+
@Test (expected = InvalidArgumentException.class)
296+
public void testAddCACertificateToTrustStoreBlankAlias() throws InvalidArgumentException {
297+
try {
298+
crypto.addCACertificateToTrustStore(new File("something"), "");
299+
} catch (CryptoException e) {
300+
fail("testAddCACertificateToTrustStoreNoAlias should not throw CryptoException. Error: " + e.getMessage());
301+
}
302+
}
303+
237304
@Test (expected = InvalidArgumentException.class)
238305
public void testAddCACertificateToTrustStoreEmptyAlias() throws InvalidArgumentException {
239306
try {
@@ -243,6 +310,26 @@ public void testAddCACertificateToTrustStoreEmptyAlias() throws InvalidArgumentE
243310
}
244311
}
245312

313+
@Test
314+
public void testAddCACertificateToTrustStoreBadStore() throws Exception {
315+
316+
thrown.expect(CryptoException.class);
317+
thrown.expectMessage("Unable to add");
318+
319+
// Create an uninitialized key store
320+
KeyStore tmpKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
321+
322+
// Ensure that crypto is using that store
323+
KeyStore saveKeyStore = (KeyStore) TestUtils.setField(crypto, "trustStore", tmpKeyStore);
324+
325+
try {
326+
crypto.addCACertificateToTrustStore(testCACert, "alias");
327+
} finally {
328+
// Ensure we set it back so that subsequent tests will not be affected
329+
TestUtils.setField(crypto, "trustStore", saveKeyStore);
330+
}
331+
}
332+
246333
@Test (expected = CryptoException.class)
247334
public void testAddCACertificateToTrustStoreNoFile() throws CryptoException {
248335
try {
@@ -270,9 +357,29 @@ public void testAddCACertificateToTrustStoreNoCert() throws InvalidArgumentExcep
270357
}
271358
}
272359

360+
// Tests addCACertificateToTrustStore passing a certificate and null for alias
361+
@Test
362+
public void testAddCACertificateToTrustStoreCertNullAlias() throws Exception {
363+
364+
thrown.expect(InvalidArgumentException.class);
365+
thrown.expectMessage("You must assign an alias");
366+
367+
crypto.addCACertificateToTrustStore(testCACert, null);
368+
}
369+
370+
// Tests addCACertificateToTrustStore passing a certificate and an empty string for alias
371+
@Test
372+
public void testAddCACertificateToTrustStoreCertEmptyAlias() throws Exception {
373+
374+
thrown.expect(InvalidArgumentException.class);
375+
thrown.expectMessage("You must assign an alias");
376+
377+
crypto.addCACertificateToTrustStore(testCACert, "");
378+
}
379+
273380
@Test (expected = InvalidArgumentException.class)
274-
public void testAddCACertsNullInput() throws Exception {
275-
crypto.addCACertificateToTrustStore((File) null, null);
381+
public void testAddCACertificateToTrustStoreNullFile() throws Exception {
382+
crypto.addCACertificateToTrustStore((File) null, "test");
276383
}
277384

278385
@Test (expected = CryptoException.class)
@@ -370,8 +477,6 @@ public void testValidateNotSignedCertificate() {
370477

371478
@Test
372479
public void testValidateInvalidCertificate() throws IOException, CertificateException {
373-
BufferedInputStream pem = new BufferedInputStream(new ByteArrayInputStream(invalidPemCert));
374-
375480
assertFalse(crypto.validateCertificate(invalidPemCert));
376481
}
377482

@@ -486,6 +591,17 @@ public void testKeyGen() throws CryptoException {
486591
Assert.assertSame(KeyPair.class, crypto.keyGen().getClass());
487592
}
488593

594+
// Try to generate a key without initializing crypto
595+
@Test
596+
public void testKeyGenBadCrypto() throws CryptoException {
597+
598+
thrown.expect(CryptoException.class);
599+
thrown.expectMessage("Unable to generate");
600+
601+
CryptoPrimitives tmpCrypto = new CryptoPrimitives();
602+
tmpCrypto.keyGen();
603+
}
604+
489605
@Test
490606
public void testGenerateCertificateRequest() throws CryptoException, OperatorCreationException {
491607
KeyPair testKeyPair = crypto.keyGen();
@@ -508,4 +624,28 @@ public void testCertificateToDER() throws CryptoException, OperatorCreationExcep
508624

509625
Assert.assertTrue(crypto.certificateToDER(pemGenCert).length > 0);
510626
}
627+
628+
@Test
629+
public void testHashSHA2() throws Exception {
630+
631+
byte[] input = "TheQuickBrownFox".getBytes(UTF_8);
632+
String expectedHash = "cd0b1763383f460e94a2e6f0aefc3749bbeec60db11c12d678c682da679207ad";
633+
634+
crypto.setHashAlgorithm("SHA2");
635+
byte[] hash = crypto.hash(input);
636+
Assert.assertEquals(expectedHash, Hex.toHexString(hash));
637+
}
638+
639+
@Test
640+
public void testHashSHA3() throws Exception {
641+
642+
byte[] input = "TheQuickBrownFox".getBytes(UTF_8);
643+
String expectedHash = "feb69c5c360a15802de6af23a3f5622da9d96aff2be78c8f188cce57a3549db6";
644+
645+
crypto.setHashAlgorithm("sha3");
646+
byte[] hash = crypto.hash(input);
647+
Assert.assertEquals(expectedHash, Hex.toHexString(hash));
648+
}
649+
650+
511651
}

0 commit comments

Comments
 (0)