Skip to content

Commit a66127d

Browse files
committed
utils: add methods to save and load public and private keys
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent f144081 commit a66127d

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

utils/src/org/apache/cloudstack/utils/auth/SAMLUtils.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,22 @@
7272
import java.math.BigInteger;
7373
import java.net.URLEncoder;
7474
import java.security.InvalidKeyException;
75+
import java.security.KeyFactory;
7576
import java.security.KeyPair;
7677
import java.security.KeyPairGenerator;
7778
import java.security.NoSuchAlgorithmException;
7879
import java.security.NoSuchProviderException;
7980
import java.security.PrivateKey;
81+
import java.security.PublicKey;
8082
import java.security.SecureRandom;
8183
import java.security.Security;
8284
import java.security.Signature;
8385
import java.security.SignatureException;
8486
import java.security.cert.CertificateEncodingException;
8587
import java.security.cert.X509Certificate;
88+
import java.security.spec.InvalidKeySpecException;
89+
import java.security.spec.PKCS8EncodedKeySpec;
90+
import java.security.spec.X509EncodedKeySpec;
8691
import java.util.Date;
8792
import java.util.zip.Deflater;
8893
import java.util.zip.DeflaterOutputStream;
@@ -220,6 +225,70 @@ public static String generateSAMLRequestSignature(String urlEncodedString, Priva
220225
return URLEncoder.encode(Base64.encodeBytes(signature.sign(), Base64.DONT_BREAK_LINES), HttpUtils.UTF_8);
221226
}
222227

228+
public static KeyFactory getKeyFactory() {
229+
KeyFactory keyFactory = null;
230+
try {
231+
Security.addProvider(new BouncyCastleProvider());
232+
keyFactory = KeyFactory.getInstance("RSA", "BC");
233+
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
234+
s_logger.error("Unable to create KeyFactory:" + e.getMessage());
235+
}
236+
return keyFactory;
237+
}
238+
239+
public static String savePublicKey(PublicKey key) {
240+
try {
241+
KeyFactory keyFactory = SAMLUtils.getKeyFactory();
242+
if (keyFactory == null) return null;
243+
X509EncodedKeySpec spec = keyFactory.getKeySpec(key, X509EncodedKeySpec.class);
244+
return new String(org.bouncycastle.util.encoders.Base64.encode(spec.getEncoded()));
245+
} catch (InvalidKeySpecException e) {
246+
s_logger.error("Unable to create KeyFactory:" + e.getMessage());
247+
}
248+
return null;
249+
}
250+
251+
public static String savePrivateKey(PrivateKey key) {
252+
try {
253+
KeyFactory keyFactory = SAMLUtils.getKeyFactory();
254+
if (keyFactory == null) return null;
255+
PKCS8EncodedKeySpec spec = keyFactory.getKeySpec(key,
256+
PKCS8EncodedKeySpec.class);
257+
return new String(org.bouncycastle.util.encoders.Base64.encode(spec.getEncoded()));
258+
} catch (InvalidKeySpecException e) {
259+
s_logger.error("Unable to create KeyFactory:" + e.getMessage());
260+
}
261+
return null;
262+
}
263+
264+
public static PublicKey loadPublicKey(String publicKey) {
265+
byte[] sigBytes = org.bouncycastle.util.encoders.Base64.decode(publicKey);
266+
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(sigBytes);
267+
KeyFactory keyFact = SAMLUtils.getKeyFactory();
268+
if (keyFact == null)
269+
return null;
270+
try {
271+
return keyFact.generatePublic(x509KeySpec);
272+
} catch (InvalidKeySpecException e) {
273+
s_logger.error("Unable to create PrivateKey from privateKey string:" + e.getMessage());
274+
}
275+
return null;
276+
}
277+
278+
public static PrivateKey loadPrivateKey(String privateKey) {
279+
byte[] sigBytes = org.bouncycastle.util.encoders.Base64.decode(privateKey);
280+
PKCS8EncodedKeySpec pkscs8KeySpec = new PKCS8EncodedKeySpec(sigBytes);
281+
KeyFactory keyFact = SAMLUtils.getKeyFactory();
282+
if (keyFact == null)
283+
return null;
284+
try {
285+
return keyFact.generatePrivate(pkscs8KeySpec);
286+
} catch (InvalidKeySpecException e) {
287+
s_logger.error("Unable to create PrivateKey from privateKey string:" + e.getMessage());
288+
}
289+
return null;
290+
}
291+
223292
public static KeyPair generateRandomKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException {
224293
Security.addProvider(new BouncyCastleProvider());
225294
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "BC");

utils/test/org/apache/cloudstack/utils/auth/SAMLUtilsTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
import org.opensaml.saml2.core.NameID;
2727
import org.opensaml.saml2.core.impl.NameIDBuilder;
2828

29+
import java.security.KeyPair;
30+
import java.security.PrivateKey;
31+
import java.security.PublicKey;
32+
2933
public class SAMLUtilsTest extends TestCase {
3034

3135
@Test
@@ -64,4 +68,18 @@ public void testBuildLogoutRequest() throws Exception {
6468
assertEquals(req.getNameID().getValue(), nameIdString);
6569
assertEquals(req.getSessionIndexes().get(0).getSessionIndex(), sessionIndex);
6670
}
71+
72+
@Test
73+
public void testX509Helpers() throws Exception {
74+
KeyPair keyPair = SAMLUtils.generateRandomKeyPair();
75+
76+
String privateKeyString = SAMLUtils.savePrivateKey(keyPair.getPrivate());
77+
String publicKeyString = SAMLUtils.savePublicKey(keyPair.getPublic());
78+
79+
PrivateKey privateKey = SAMLUtils.loadPrivateKey(privateKeyString);
80+
PublicKey publicKey = SAMLUtils.loadPublicKey(publicKeyString);
81+
82+
assertTrue(privateKey.equals(keyPair.getPrivate()));
83+
assertTrue(publicKey.equals(keyPair.getPublic()));
84+
}
6785
}

0 commit comments

Comments
 (0)