-
Notifications
You must be signed in to change notification settings - Fork 235
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updating all BouncyCastle references to newer library
Github issue #168
- Loading branch information
1 parent
4d4bab2
commit 56850b8
Showing
12 changed files
with
506 additions
and
145 deletions.
There are no files selected for viewing
36 changes: 36 additions & 0 deletions
36
...irement_docs/com/microsoft/azure/sdk/iot/deps/util/pemutilities_requirements.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# PemUtilities Requirements | ||
|
||
## Overview | ||
|
||
Utility class for converting PEM formatted strings into public X509 certificates and private keys. | ||
|
||
## References | ||
|
||
## Exposed API | ||
|
||
```java | ||
public final class PemUtilities | ||
{ | ||
public static PrivateKey parsePrivateKey(String privateKeyString) throws CertificateException; | ||
public static X509Certificate parsePublicKey(String publicKeyCertificateString) throws CertificateException; | ||
} | ||
``` | ||
|
||
### parsePrivateKey | ||
```java | ||
public static PrivateKey parsePrivateKey(String privateKeyString) throws CertificateException; | ||
``` | ||
|
||
**SRS_PEMUTILITIES_21_001: [**This function shall return a Private Key instance created by the provided PEM formatted privateKeyString.**]** | ||
|
||
**SRS_PEMUTILITIES_21_002: [**If any exception is encountered while attempting to create the private key instance, this function shall throw a CertificateException.**]** | ||
|
||
|
||
### parsePublicKeyCertificate() | ||
```java | ||
public static X509Certificate parsePublicKeyCertificate(String publicKeyCertificateString) throws CertificateException; | ||
``` | ||
|
||
**SRS_PEMUTILITIES_21_003: [**This function shall return an X509Certificate instance created by the provided PEM formatted publicKeyCertificateString.**]** | ||
|
||
**SRS_PEMUTILITIES_21_004: [**If any exception is encountered while attempting to create the public key certificate instance, this function shall throw a CertificateException.**]** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
deps/src/main/java/com/microsoft/azure/sdk/iot/deps/util/PemUtilities.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright (c) Microsoft. All rights reserved. | ||
* Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
*/ | ||
|
||
package com.microsoft.azure.sdk.iot.deps.util; | ||
|
||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | ||
import org.bouncycastle.openssl.PEMException; | ||
import org.bouncycastle.openssl.PEMKeyPair; | ||
import org.bouncycastle.openssl.PEMParser; | ||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; | ||
import org.bouncycastle.util.io.pem.PemObject; | ||
import org.bouncycastle.util.io.pem.PemReader; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.StringReader; | ||
import java.security.PrivateKey; | ||
import java.security.Security; | ||
import java.security.cert.CertificateException; | ||
import java.security.cert.CertificateFactory; | ||
import java.security.cert.X509Certificate; | ||
|
||
public class PemUtilities | ||
{ | ||
public static PrivateKey parsePrivateKey(String privateKeyString) throws CertificateException | ||
{ | ||
try | ||
{ | ||
// Codes_SRS_PEMUTILITIES_21_001: [This function shall return a Private Key instance created by the provided PEM formatted privateKeyString.] | ||
Security.addProvider(new BouncyCastleProvider()); | ||
PEMParser privateKeyParser = new PEMParser(new StringReader(privateKeyString)); | ||
Object possiblePrivateKey = privateKeyParser.readObject(); | ||
PEMKeyPair ukp = (PEMKeyPair) possiblePrivateKey; | ||
return getPrivateKey(ukp); | ||
} | ||
catch (Exception e) | ||
{ | ||
// Codes_SRS_PEMUTILITIES_21_002: [If any exception is encountered while attempting to create the private key instance, this function shall throw a CertificateException.] | ||
throw new CertificateException(e); | ||
} | ||
} | ||
|
||
public static X509Certificate parsePublicKeyCertificate(String publicKeyCertificateString) throws CertificateException | ||
{ | ||
try | ||
{ | ||
// Codes_SRS_PEMUTILITIES_21_003: [This function shall return an X509Certificate instance created by the provided PEM formatted publicKeyCertificateString.] | ||
Security.addProvider(new BouncyCastleProvider()); | ||
PemReader publicKeyCertificateReader = new PemReader(new StringReader(publicKeyCertificateString)); | ||
PemObject possiblePublicKeyCertificate = publicKeyCertificateReader.readPemObject(); | ||
CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); | ||
return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(possiblePublicKeyCertificate.getContent())); | ||
} | ||
catch (Exception e) | ||
{ | ||
// Codes_SRS_PEMUTILITIES_21_004: [If any exception is encountered while attempting to create the public key certificate instance, this function shall throw a CertificateException.] | ||
throw new CertificateException(e); | ||
} | ||
} | ||
|
||
private static PrivateKey getPrivateKey(PEMKeyPair ukp) throws PEMException | ||
{ | ||
return new JcaPEMKeyConverter().setProvider("BC").getKeyPair(ukp).getPrivate(); | ||
} | ||
} |
148 changes: 148 additions & 0 deletions
148
deps/src/test/java/tests/unit/com/microsoft/azure/sdk/iot/deps/util/PemUtilitiesTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* Copyright (c) Microsoft. All rights reserved. | ||
* Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
*/ | ||
|
||
package tests.unit.com.microsoft.azure.sdk.iot.deps.util; | ||
|
||
import com.microsoft.azure.sdk.iot.deps.util.PemUtilities; | ||
import mockit.Deencapsulation; | ||
import mockit.Mocked; | ||
import mockit.NonStrictExpectations; | ||
import org.bouncycastle.openssl.PEMKeyPair; | ||
import org.bouncycastle.openssl.PEMParser; | ||
import org.bouncycastle.util.io.pem.PemObject; | ||
import org.bouncycastle.util.io.pem.PemReader; | ||
import org.junit.Test; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.IOException; | ||
import java.io.StringReader; | ||
import java.security.KeyPair; | ||
import java.security.PrivateKey; | ||
import java.security.cert.CertificateException; | ||
import java.security.cert.CertificateFactory; | ||
import java.security.cert.X509Certificate; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
|
||
/** | ||
* Unit Tests for PemUtilities.java | ||
* Methods: 66% | ||
* Lines: 93% | ||
* Notes: One of the three methods (getPrivateKey(...)) is uncovered because one of the | ||
* Bouncycastle objects (JcaPEMKeyConverter) cannot be mocked. As such, it could not be unit tested. | ||
*/ | ||
public class PemUtilitiesTest | ||
{ | ||
private static final String expectedPrivateKeyString = "some private key string"; | ||
private static final String expectedPublicKeyCertificateString = "some public key certificate string"; | ||
|
||
@Mocked PrivateKey mockPrivateKey; | ||
@Mocked X509Certificate mockX509Certificate; | ||
@Mocked PEMKeyPair mockPEMKeyPair; | ||
@Mocked PEMParser mockPEMParser; | ||
@Mocked PemObject mockPemObject; | ||
@Mocked PemReader mockPemReader; | ||
@Mocked StringReader mockStringReader; | ||
@Mocked KeyPair mockKeyPair; | ||
@Mocked CertificateFactory mockCertificateFactory; | ||
|
||
// Tests_SRS_PEMUTILITIES_21_001: [This function shall return a Private Key instance created by the provided PEM formatted privateKeyString.] | ||
@Test | ||
public void parsePrivateKeySuccess() throws CertificateException, IOException | ||
{ | ||
//arrange | ||
final PemUtilities pemUtilities = new PemUtilities(); | ||
new NonStrictExpectations(pemUtilities) | ||
{ | ||
{ | ||
new StringReader(expectedPrivateKeyString); | ||
result = mockStringReader; | ||
|
||
new PEMParser(mockStringReader); | ||
result = mockPEMParser; | ||
|
||
mockPEMParser.readObject(); | ||
result = mockPEMKeyPair; | ||
|
||
//Doing this instead of just mocking JCA converter because trying to mock the JCA converter causes strange errors to be thrown. | ||
Deencapsulation.invoke(pemUtilities, "getPrivateKey", new Class[] {PEMKeyPair.class}, mockPEMKeyPair); | ||
result = mockPrivateKey; | ||
} | ||
}; | ||
|
||
//act | ||
PrivateKey actualPrivateKey = PemUtilities.parsePrivateKey(expectedPrivateKeyString); | ||
|
||
//assert | ||
assertEquals(mockPrivateKey, actualPrivateKey); | ||
} | ||
|
||
// Tests_SRS_PEMUTILITIES_21_002: [If any exception is encountered while attempting to create the private key instance, this function shall throw a CertificateException.] | ||
@Test (expected = CertificateException.class) | ||
public void parsePrivateKeyExceptionsWrappedInCertificateException() throws CertificateException, IOException | ||
{ | ||
//arrange | ||
final PemUtilities pemUtilities = new PemUtilities(); | ||
new NonStrictExpectations(pemUtilities) | ||
{ | ||
{ | ||
new StringReader(expectedPrivateKeyString); | ||
result = new IOException(); | ||
} | ||
}; | ||
|
||
//act | ||
PrivateKey actualPrivateKey = PemUtilities.parsePrivateKey(expectedPrivateKeyString); | ||
} | ||
|
||
// Tests_SRS_PEMUTILITIES_21_003: [This function shall return an X509Certificate instance created by the provided PEM formatted publicKeyCertificateString.] | ||
@Test | ||
public void parsePublicKeyCertificateSuccess() throws CertificateException, IOException | ||
{ | ||
//arrange | ||
new NonStrictExpectations() | ||
{ | ||
{ | ||
new PemReader(new StringReader(expectedPublicKeyCertificateString)); | ||
result = mockPemReader; | ||
|
||
mockPemReader.readPemObject(); | ||
result = mockPemObject; | ||
|
||
CertificateFactory.getInstance("X.509"); | ||
result = mockCertificateFactory; | ||
|
||
mockCertificateFactory.generateCertificate(new ByteArrayInputStream(mockPemObject.getContent())); | ||
result = mockX509Certificate; | ||
} | ||
}; | ||
|
||
//act | ||
X509Certificate actualPublicKeyCertificate = PemUtilities.parsePublicKeyCertificate(expectedPublicKeyCertificateString); | ||
|
||
//assert | ||
assertEquals(mockX509Certificate, actualPublicKeyCertificate); | ||
} | ||
|
||
// Tests_SRS_PEMUTILITIES_21_004: [If any exception is encountered while attempting to create the public key certificate instance, this function shall throw a CertificateException.] | ||
@Test (expected = CertificateException.class) | ||
public void parsePublicKeyCertificateExceptionsWrappedInCertificateException() throws CertificateException, IOException | ||
{ | ||
//arrange | ||
new NonStrictExpectations() | ||
{ | ||
{ | ||
new PemReader(new StringReader(expectedPublicKeyCertificateString)); | ||
result = new IOException(); | ||
} | ||
}; | ||
|
||
//act | ||
X509Certificate actualPublicKeyCertificate = PemUtilities.parsePublicKeyCertificate(expectedPublicKeyCertificateString); | ||
|
||
//assert | ||
assertEquals(mockX509Certificate, actualPublicKeyCertificate); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.