├── .gitignore
├── src
└── test
│ ├── resources
│ ├── keystore.p12
│ ├── sample.pdf
│ └── soap-unsigned.xml
│ └── java
│ └── nl
│ └── craftsmen
│ └── crypto
│ ├── HMACDemo.java
│ ├── BitcoinMiningDemo.java
│ ├── HashingDemo.java
│ ├── SymmetricEncryptionECBDemo.java
│ ├── SimpleSigningDemo.java
│ ├── SymmetricEncryptionCBCDemo.java
│ ├── WalletEncryptionDemo.java
│ ├── ASymmetricEncryptionDemo.java
│ ├── BitcoinTransactionSigningDemo.java
│ ├── HttpsDemo.java
│ ├── CmsSigner.java
│ ├── util
│ ├── Utils.java
│ ├── CryptoToolboxCrypto.java
│ └── SampleKeyStoreFactory.java
│ ├── KeystoreTest.java
│ └── PdfSignDemo.java
├── justright.txt
├── pdf_digital_signature_timestamp.pdf
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | myStore.pkcs12
2 | signed.pdf
3 | *.iml
4 | .idea
5 | target
--------------------------------------------------------------------------------
/src/test/resources/keystore.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichelSchudel/crypto-demo/HEAD/src/test/resources/keystore.p12
--------------------------------------------------------------------------------
/src/test/resources/sample.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichelSchudel/crypto-demo/HEAD/src/test/resources/sample.pdf
--------------------------------------------------------------------------------
/justright.txt:
--------------------------------------------------------------------------------
1 | The Lord of the Rings has been read by many people since it finally appeared in print; and I should like to say it.
--------------------------------------------------------------------------------
/pdf_digital_signature_timestamp.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichelSchudel/crypto-demo/HEAD/pdf_digital_signature_timestamp.pdf
--------------------------------------------------------------------------------
/src/test/resources/soap-unsigned.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/HMACDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import nl.craftsmen.crypto.util.Utils;
4 | import org.junit.Test;
5 |
6 | import javax.crypto.KeyGenerator;
7 | import javax.crypto.Mac;
8 | import java.security.InvalidKeyException;
9 | import java.security.Key;
10 | import java.security.NoSuchAlgorithmException;
11 |
12 | import static org.junit.Assert.assertEquals;
13 |
14 | public class HMACDemo {
15 |
16 | @Test
17 | public void testHMac() throws NoSuchAlgorithmException, InvalidKeyException {
18 |
19 | // make key
20 | KeyGenerator generator = KeyGenerator.getInstance("HMACSha256");
21 | Key key = generator.generateKey();
22 | Utils.printByteArray("hmac key", key.getEncoded());
23 |
24 | // create signature
25 | Mac mac = Mac.getInstance("HMACSha256");
26 | mac.init(key);
27 | byte[] input = "Hello, world!".getBytes();
28 | byte[] signature = mac.doFinal(input);
29 | Utils.printByteArray("Signature", signature);
30 |
31 | // validation of signature on the other end
32 | mac.init(key);
33 | byte[] newSignature = mac.doFinal(input);
34 | Utils.printByteArray("Recomputed signature", newSignature);
35 |
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/BitcoinMiningDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import org.apache.commons.codec.binary.Hex;
4 | import org.junit.Test;
5 |
6 | import java.security.MessageDigest;
7 | import java.security.NoSuchAlgorithmException;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 |
11 | /**
12 | * A small message digest demo.
13 | */
14 | public class BitcoinMiningDemo {
15 |
16 | @Test
17 | public void miningDemo() throws NoSuchAlgorithmException {
18 |
19 | //setup block
20 | String blockData = "whole bunch of transactions";
21 |
22 | MessageDigest digester = MessageDigest.getInstance("SHA-256");
23 |
24 | int number = 0;
25 | String blockWithRandomValue = blockData + number;
26 | while (!(digester.digest(blockWithRandomValue.toString().getBytes())[0] == 0)) {
27 | System.out.println("block" + blockWithRandomValue + " has hash " + Hex.encodeHexString(digester.digest(blockWithRandomValue.toString().getBytes())) + ", not good enough!");
28 | number++;
29 | blockWithRandomValue = blockData + number;
30 | }
31 |
32 | System.out.println("block " + blockWithRandomValue + " has hash " + Hex.encodeHexString(digester.digest(blockWithRandomValue.toString().getBytes())));
33 | System.out.println("block took " + number + " iterations to seal.");
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/HashingDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import nl.craftsmen.crypto.util.Utils;
4 |
5 | import org.junit.Test;
6 |
7 | import java.security.MessageDigest;
8 | import java.security.NoSuchAlgorithmException;
9 |
10 | /**
11 | * A small message digest demo.
12 | */
13 | public class HashingDemo {
14 |
15 | @Test
16 | public void hashingDemo() throws NoSuchAlgorithmException {
17 |
18 | // get a message digest
19 | System.out.println("one way only!");
20 | hashText("The quick brown fox jumped over the lazy dog.");
21 |
22 | //hash it again, deterministic
23 | System.out.println("deterministic");
24 | hashText("The quick brown fox jumped over the lazy dog.");
25 |
26 | // psuedorandom, new digest looks nothing like old digest
27 | System.out.println("psuedorandom");
28 | hashText("The quick brown fox jumped ower the lazy dog.");
29 |
30 | // hash is always fixed length.
31 | System.out.println("fixedlength");
32 | hashText("The quick brown fox jumped ower the lazy dog and a lot more stuff happened after that.");
33 | }
34 |
35 | private void hashText(String data) throws NoSuchAlgorithmException {
36 | System.out.println("Input: " + data);
37 | MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
38 | byte[] digest = messageDigest.digest(data.getBytes());
39 | Utils.printByteArray("Digest", digest);
40 | }
41 |
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/SymmetricEncryptionECBDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import nl.craftsmen.crypto.util.Utils;
4 | import org.junit.Test;
5 |
6 | import javax.crypto.Cipher;
7 | import javax.crypto.KeyGenerator;
8 | import java.security.GeneralSecurityException;
9 | import java.security.Key;
10 |
11 | public class SymmetricEncryptionECBDemo {
12 |
13 | //2. show key generation
14 | //3. create string of 128 bytes, explaining block size of AES is 128
15 | //4. Encrypt, show it's 128 bytes
16 | //5. Decrypt, show end result
17 | //6. Notice pattern in ECB
18 |
19 | @Test
20 | public void testSymmetricEncryption() throws GeneralSecurityException {
21 |
22 | KeyGenerator generator = KeyGenerator.getInstance("AES");
23 | // specify we want a key length of 192 bits, allowed for AES
24 | generator.init(192);
25 | Key key = generator.generateKey();
26 | Utils.printByteArray("key", key.getEncoded());
27 |
28 | byte[] input = "JavaLand".repeat(16).getBytes();
29 | Utils.printText("input", input);
30 |
31 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
32 | cipher.init(Cipher.ENCRYPT_MODE, key);
33 | byte[] encryptedOutput = cipher.doFinal(input);
34 | Utils.printByteArray("ciphertext", encryptedOutput);
35 |
36 | //decryption on the other end
37 | cipher.init(Cipher.DECRYPT_MODE, key);
38 | byte[] decryptedOutput = cipher.doFinal(encryptedOutput);
39 | Utils.printText("decoded input", decryptedOutput);
40 |
41 |
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/SimpleSigningDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import static org.assertj.core.api.Assertions.assertThat;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import nl.craftsmen.crypto.util.Utils;
7 | import org.apache.commons.codec.DecoderException;
8 | import org.junit.Test;
9 |
10 | import java.security.*;
11 |
12 | public class SimpleSigningDemo {
13 |
14 | @Test
15 | public void testAsymmetricSigningWithSignatureClasses() throws GeneralSecurityException, DecoderException {
16 |
17 | KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
18 | kpGen.initialize(1024);
19 | KeyPair keyPair = kpGen.generateKeyPair();
20 | Utils.printByteArray("private key", keyPair.getPrivate().getEncoded());
21 | Utils.printByteArray("public key", keyPair.getPublic().getEncoded());
22 |
23 | String data = "JavaLand is the best!!!";
24 |
25 | Signature signatureAlgorithm = Signature.getInstance("SHA256WithRSA");
26 | signatureAlgorithm.initSign(keyPair.getPrivate());
27 | signatureAlgorithm.update(data.getBytes());
28 |
29 | byte[] signature = signatureAlgorithm.sign();
30 |
31 | Utils.printByteArray("signature", signature);
32 |
33 |
34 |
35 | //verification on the other end
36 | String receivedData = "JavaLand is the worst!!!";
37 |
38 | Signature verificationAlgorithm = Signature.getInstance("SHA256WithRSA");
39 | verificationAlgorithm.initVerify(keyPair.getPublic());
40 | verificationAlgorithm.update(receivedData.getBytes());
41 |
42 | boolean matches = verificationAlgorithm.verify(signature);
43 |
44 | System.out.println("signature matches: " + matches);
45 | assertThat(matches).isTrue();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/SymmetricEncryptionCBCDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import nl.craftsmen.crypto.util.Utils;
4 | import org.junit.Test;
5 |
6 | import javax.crypto.Cipher;
7 | import javax.crypto.KeyGenerator;
8 | import javax.crypto.spec.IvParameterSpec;
9 | import java.security.GeneralSecurityException;
10 | import java.security.Key;
11 | import java.security.SecureRandom;
12 |
13 | public class SymmetricEncryptionCBCDemo {
14 |
15 | //2. show key generation
16 | //3. create string of 128 bytes, explaining block size of AES is 128
17 | //4. Encrypt, show it's 128 bytes
18 | //5. Decrypt, show end result
19 | //6. Notice absence of pattern in CBC
20 |
21 | @Test
22 | public void testSymmetricEncryption() throws GeneralSecurityException {
23 |
24 |
25 | //make key
26 | KeyGenerator generator = KeyGenerator.getInstance("AES");
27 | // specify we want a key length of 192 bits, allowed for AES
28 | generator.init(192);
29 | Key key = generator.generateKey();
30 | Utils.printByteArray("key", key.getEncoded());
31 |
32 | //get IV
33 | Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
34 | SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
35 | byte[] random = new byte[16];
36 | secureRandom.nextBytes(random);
37 | IvParameterSpec ivSpec = new IvParameterSpec(random);
38 | Utils.printByteArray("ivSpec", random);
39 |
40 | //input
41 | byte[] input = "JavaLand".repeat(16).getBytes();
42 | Utils.printText("input", input);
43 |
44 | //encryption
45 | cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
46 | byte[] encryptedOutput = cipher.doFinal(input);
47 | Utils.printByteArray("ciphertext", encryptedOutput);
48 |
49 | //decryption
50 | cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
51 | byte[] decryptedOutput = cipher.doFinal(encryptedOutput);
52 | Utils.printText("decoded input", decryptedOutput);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/WalletEncryptionDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import nl.craftsmen.crypto.util.Utils;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.SecretKeyFactory;
7 | import javax.crypto.spec.IvParameterSpec;
8 | import javax.crypto.spec.PBEKeySpec;
9 | import java.security.Key;
10 | import java.security.NoSuchAlgorithmException;
11 | import java.security.NoSuchProviderException;
12 | import java.security.SecureRandom;
13 | import java.security.spec.InvalidKeySpecException;
14 |
15 | public class WalletEncryptionDemo {
16 |
17 | public static void main(String[] args) throws Exception {
18 | Utils.loadProvider();
19 |
20 | Key passwordKey = getPasswordKey("myPassword");
21 |
22 |
23 | byte[] wallet = "{\"myAccountBalance\": 500}".getBytes();
24 | Utils.printText("Decrypted wallet: ", wallet);
25 |
26 | Cipher encryptingCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
27 | encryptingCipher.init(Cipher.ENCRYPT_MODE, passwordKey);
28 | byte[] cipherText = encryptingCipher.doFinal(wallet);
29 | Utils.printByteArray("Encrypted wallet", cipherText);
30 |
31 | Cipher decryptingCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "BC");
32 | byte[] iv = encryptingCipher.getIV();
33 |
34 | decryptingCipher.init(Cipher.DECRYPT_MODE, passwordKey, new IvParameterSpec(iv));
35 | byte[] plainText2 = decryptingCipher.doFinal(cipherText);
36 | Utils.printText("Decrypted wallet: ", plainText2);
37 |
38 |
39 | }
40 |
41 | private static Key getPasswordKey(String password) throws InvalidKeySpecException, NoSuchProviderException, NoSuchAlgorithmException {
42 | int keyLength = 256;
43 | int saltLength = keyLength / 8; // It's bytes, not bits.
44 | int iterations = 65536;
45 | byte[] salt = new SecureRandom().generateSeed(saltLength);
46 | PBEKeySpec passwordKeySpec = new PBEKeySpec(password.toCharArray(), salt, iterations, keyLength);
47 | SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256", "BC");
48 | Key passwordKey = secretKeyFactory.generateSecret(passwordKeySpec);
49 | return passwordKey;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/ASymmetricEncryptionDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import nl.craftsmen.crypto.util.Utils;
4 |
5 | import org.junit.Test;
6 |
7 | import javax.crypto.BadPaddingException;
8 | import javax.crypto.Cipher;
9 | import javax.crypto.IllegalBlockSizeException;
10 | import javax.crypto.NoSuchPaddingException;
11 | import java.io.IOException;
12 | import java.nio.file.Files;
13 | import java.nio.file.Path;
14 | import java.security.*;
15 |
16 | public class ASymmetricEncryptionDemo {
17 |
18 | @Test
19 | public void encryptSomeShortTextWithRsa() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException, NoSuchProviderException {
20 |
21 | KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
22 | kpGen.initialize(1024);
23 | KeyPair keyPair = kpGen.generateKeyPair();
24 | Utils.printByteArray("private key", keyPair.getPrivate().getEncoded());
25 | Utils.printByteArray("public key", keyPair.getPublic().getEncoded());
26 |
27 |
28 |
29 | byte[] text = "The Lord of the Rings has been read by many people".getBytes();
30 | Utils.printText("plain text", text);
31 |
32 | //encrypt
33 | Cipher cipher = Cipher.getInstance("RSA");
34 |
35 | cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
36 |
37 | byte[] encryptedText = cipher.doFinal(text);
38 | Utils.printByteArray("ciphertext", encryptedText);
39 |
40 |
41 |
42 |
43 | //decrypt
44 | cipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());
45 |
46 | byte[] plainText = cipher.doFinal(encryptedText);
47 | Utils.printText("decoded text", plainText);
48 |
49 | }
50 |
51 | @Test
52 | public void encryptTheFellowshipOfTheRingWithRsa() throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException, BadPaddingException, IllegalBlockSizeException, NoSuchProviderException {
53 |
54 | KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
55 | kpGen.initialize(1024);
56 | KeyPair keyPair = kpGen.generateKeyPair();
57 |
58 |
59 | Cipher cipher = Cipher.getInstance("RSA");
60 | cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
61 |
62 | byte[] text = Files.readAllBytes(Path.of("largefile.txt"));
63 | byte[] encryptedText = cipher.doFinal(text);
64 | }
65 |
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | nl.ordina.crypto
5 | crypto-demo
6 | 0.0.1-SNAPSHOT
7 |
8 |
9 | 11
10 | 11
11 |
12 |
13 |
14 |
15 | org.bouncycastle
16 | bcprov-jdk15on
17 | 1.67
18 |
19 |
20 | org.mockito
21 | mockito-core
22 | 3.0.0
23 |
24 |
25 | org.bouncycastle
26 | bcpkix-jdk15on
27 | 1.63
28 |
29 |
30 | junit
31 | junit
32 | 4.13.1
33 | jar
34 | test
35 |
36 |
37 | org.assertj
38 | assertj-core
39 | 3.13.2
40 | test
41 |
42 |
43 |
44 | org.apache.pdfbox
45 | pdfbox
46 | 2.0.24
47 |
48 |
49 |
50 | org.apache.logging.log4j
51 | log4j-core
52 | 2.11.1
53 |
54 |
55 | wsdl4j
56 | wsdl4j
57 | 1.6.3
58 | jar
59 | compile
60 |
61 |
62 | org.apache.ws.security
63 | wss4j
64 | 1.6.19
65 | compile
66 |
67 |
68 |
69 | commons-codec
70 | commons-codec
71 | 1.11
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/BitcoinTransactionSigningDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import org.apache.commons.codec.DecoderException;
4 | import org.apache.commons.codec.binary.Hex;
5 | import org.junit.Test;
6 |
7 | import java.security.*;
8 | import java.security.spec.InvalidKeySpecException;
9 | import java.security.spec.X509EncodedKeySpec;
10 |
11 | public class BitcoinTransactionSigningDemo {
12 |
13 | class Transaction {
14 |
15 | public Transaction(String from, String to, int amount) {
16 | this.from = from;
17 | this.to = to;
18 | this.amount = amount;
19 |
20 | }
21 |
22 | String from;
23 | String to;
24 | int amount;
25 | String signature;
26 |
27 | @Override
28 | public String toString() {
29 | return "Transaction{" +
30 | "\nfrom='" + from + '\'' +
31 | "\n, to='" + to + '\'' +
32 | "\n, amount=" + amount +
33 | "\n, signature=" + signature +
34 | '}';
35 | }
36 | }
37 |
38 | @Test
39 | public void testAsymmetricSigningWithSignatureClasses() throws GeneralSecurityException, DecoderException {
40 |
41 | KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA");
42 | kpGen.initialize(1024);
43 | KeyPair michelKeyPair = kpGen.generateKeyPair();
44 | KeyPair nlJugKeyPair = kpGen.generateKeyPair();
45 |
46 | Transaction transaction = new Transaction(
47 | Hex.encodeHexString(michelKeyPair.getPublic().getEncoded()),
48 | Hex.encodeHexString(nlJugKeyPair.getPublic().getEncoded()),
49 | 5);
50 |
51 | String data = transaction.from + transaction.to + transaction.amount;
52 |
53 | // create signature
54 | Signature signatureAlgorithm = Signature.getInstance("SHA256WithRSA");
55 | signatureAlgorithm.initSign(michelKeyPair.getPrivate());
56 | signatureAlgorithm.update(data.getBytes());
57 | transaction.signature = Hex.encodeHexString(signatureAlgorithm.sign());
58 |
59 | System.out.println(transaction);
60 |
61 | Hex.decodeHex(transaction.from);
62 | // validation of signature
63 |
64 | Signature verificationAlgorithm = Signature.getInstance("SHA256WithRSA");
65 | verificationAlgorithm.initVerify(constructkey(transaction.from));
66 | verificationAlgorithm.update(data.getBytes());
67 | boolean matches = verificationAlgorithm.verify(Hex.decodeHex(transaction.signature));
68 | System.out.println("signature matches: " + matches);
69 |
70 | }
71 |
72 | private PublicKey constructkey(String keyString) throws NoSuchAlgorithmException, InvalidKeySpecException, DecoderException {
73 | byte[] publicKeyArray = Hex.decodeHex(keyString);
74 | KeyFactory kf = KeyFactory.getInstance("RSA");
75 | X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(publicKeyArray);
76 | return kf.generatePublic(X509publicKey);
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/HttpsDemo.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import javax.net.ssl.HttpsURLConnection;
4 | import javax.net.ssl.SSLPeerUnverifiedException;
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStreamReader;
8 | import java.net.MalformedURLException;
9 | import java.net.URL;
10 | import java.security.cert.Certificate;
11 |
12 | public class HttpsDemo {
13 |
14 |
15 | public static void main(String[] args)
16 | {
17 | new HttpsDemo().testIt();
18 | }
19 |
20 | private void testIt(){
21 |
22 | String https_url = "https://www.google.com/";
23 | URL url;
24 | try {
25 |
26 | url = new URL(https_url);
27 | HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
28 |
29 | //dumpl all cert info
30 | print_https_cert(con);
31 |
32 | //dump all the content
33 | print_content(con);
34 |
35 | } catch (MalformedURLException e) {
36 | e.printStackTrace();
37 | } catch (IOException e) {
38 | e.printStackTrace();
39 | }
40 |
41 | }
42 |
43 | private void print_https_cert(HttpsURLConnection con){
44 |
45 | if(con!=null){
46 |
47 | try {
48 |
49 | System.out.println("Response Code : " + con.getResponseCode());
50 | System.out.println("Cipher Suite : " + con.getCipherSuite());
51 | System.out.println("\n");
52 |
53 | Certificate[] certs = con.getServerCertificates();
54 | for(Certificate cert : certs){
55 | System.out.println("Cert Type : " + cert.getType());
56 | System.out.println("Cert Hash Code : " + cert.hashCode());
57 | System.out.println("Cert Public Key Algorithm : "
58 | + cert.getPublicKey().getAlgorithm());
59 | System.out.println("Cert Public Key Format : "
60 | + cert.getPublicKey().getFormat());
61 | System.out.println("\n");
62 | }
63 |
64 | } catch (SSLPeerUnverifiedException e) {
65 | e.printStackTrace();
66 | } catch (IOException e){
67 | e.printStackTrace();
68 | }
69 |
70 | }
71 |
72 | }
73 |
74 | private void print_content(HttpsURLConnection con){
75 | if(con!=null){
76 |
77 | try {
78 |
79 | System.out.println("****** Content of the URL ********");
80 | BufferedReader br =
81 | new BufferedReader(
82 | new InputStreamReader(con.getInputStream()));
83 |
84 | String input;
85 |
86 | while ((input = br.readLine()) != null){
87 | System.out.println(input);
88 | }
89 | br.close();
90 |
91 | } catch (IOException e) {
92 | e.printStackTrace();
93 | }
94 |
95 | }
96 |
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/CmsSigner.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.OutputStream;
6 | import java.security.PrivateKey;
7 | import java.security.Provider;
8 | import java.security.Security;
9 | import java.security.cert.CertStore;
10 | import java.security.cert.Certificate;
11 | import java.security.cert.CollectionCertStoreParameters;
12 | import java.security.cert.X509Certificate;
13 | import java.util.Arrays;
14 | import java.util.List;
15 |
16 | import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureInterface;
17 | import org.bouncycastle.cert.jcajce.JcaCertStore;
18 | import org.bouncycastle.cms.CMSException;
19 | import org.bouncycastle.cms.CMSProcessable;
20 | import org.bouncycastle.cms.CMSProcessableByteArray;
21 | import org.bouncycastle.cms.CMSSignedData;
22 | import org.bouncycastle.cms.CMSSignedDataGenerator;
23 | import org.bouncycastle.cms.CMSTypedData;
24 | import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
25 | import org.bouncycastle.operator.ContentSigner;
26 | import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
27 | import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
28 |
29 | public class CmsSigner implements SignatureInterface {
30 |
31 | private Provider provider;
32 |
33 | private PrivateKey privKey;
34 |
35 | private Certificate[] cert;
36 |
37 | public CmsSigner(Provider provider, PrivateKey privateKey, Certificate[] certificates) {
38 | this.privKey = privateKey;
39 | this.cert = certificates;
40 | this.provider = provider;
41 | }
42 |
43 | @Override
44 | public byte[] sign(InputStream content) throws IOException {
45 | CMSProcessableInputStream input = new CMSProcessableInputStream(content);
46 | CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
47 | // CertificateChain
48 | List certList = Arrays.asList(cert);
49 |
50 | if (Security.getProvider(provider.getName()) == null) {
51 | Security.addProvider(provider);
52 | }
53 |
54 | CertStore certStore = null;
55 | try {
56 | certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), provider);
57 | ContentSigner sha256Signer = new JcaContentSignerBuilder("SHA256withRSA").setProvider(provider)
58 | .build(privKey);
59 |
60 | JcaCertStore jcaCertStore = new JcaCertStore(certList);
61 | gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider(provider)
62 | .build()).build(sha256Signer, (X509Certificate) certList.get(0)));
63 | gen.addCertificates(jcaCertStore);
64 | gen.addCRLs(jcaCertStore);
65 |
66 | CMSTypedData chainMessage = new CMSProcessableByteArray(content.readAllBytes());
67 | CMSSignedData signedData = gen.generate(chainMessage);
68 |
69 | return signedData.getEncoded();
70 | } catch (Exception e) {
71 | // should be handled
72 | e.printStackTrace();
73 | }
74 | throw new RuntimeException("Problem while preparing signature");
75 | }
76 | }
77 |
78 | class CMSProcessableInputStream implements CMSProcessable {
79 |
80 | InputStream in;
81 |
82 | public CMSProcessableInputStream(InputStream is) {
83 | in = is;
84 | }
85 |
86 | public Object getContent() {
87 | return null;
88 | }
89 |
90 | public void write(OutputStream out) throws IOException, CMSException {
91 | // read the content only one time
92 | byte[] buffer = new byte[8 * 1024];
93 | int read;
94 | while ((read = in.read(buffer)) != -1) {
95 | out.write(buffer, 0, read);
96 | }
97 | in.close();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/util/Utils.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto.util;
2 |
3 | import org.apache.commons.codec.binary.Hex;
4 | import org.apache.ws.security.util.DOM2Writer;
5 | import org.bouncycastle.jce.provider.BouncyCastleProvider;
6 | import org.w3c.dom.Document;
7 | import org.w3c.dom.Node;
8 | import org.xml.sax.SAXException;
9 |
10 | import javax.xml.parsers.DocumentBuilder;
11 | import javax.xml.parsers.DocumentBuilderFactory;
12 | import javax.xml.parsers.ParserConfigurationException;
13 | import java.io.ByteArrayInputStream;
14 | import java.io.IOException;
15 | import java.io.StringWriter;
16 | import java.security.Key;
17 | import java.security.Security;
18 |
19 | /**
20 | * Utility class for parsing DOM documents.
21 | */
22 | public class Utils {
23 |
24 | /**
25 | * Hide default constructor. Constructs a new DOMUtils.
26 | */
27 | private Utils() {
28 | }
29 |
30 | public static String getDocumentAsString(Node node) {
31 | StringWriter stringWriter = new StringWriter();
32 | // omit xml declaration
33 | DOM2Writer.serializeAsXML(node, stringWriter, true);
34 | return stringWriter.getBuffer().toString();
35 |
36 | }
37 |
38 | /**
39 | * Constructs a DOM document from an xml message in string format.
40 | *
41 | * @param xml the xml message.
42 | * @return the xml message as a DOM document.
43 | */
44 | public static Document getDocumentFromString(String xml) {
45 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
46 | factory.setValidating(false);
47 | factory.setNamespaceAware(true);
48 | // Create the builder and parse the xml
49 | DocumentBuilder builder;
50 | try {
51 | builder = factory.newDocumentBuilder();
52 | return builder.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")));
53 | } catch (ParserConfigurationException e) {
54 | throw new RuntimeException(e);
55 | } catch (SAXException e) {
56 | throw new RuntimeException(e);
57 | } catch (IOException e) {
58 | throw new RuntimeException(e);
59 | }
60 |
61 | }
62 |
63 | public static Document getDocument(String filename) throws Exception {
64 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
65 | factory.setValidating(false);
66 | factory.setNamespaceAware(true);
67 | // Create the builder and parse the file
68 | DocumentBuilder builder = factory.newDocumentBuilder();
69 | Document doc = builder.parse(Utils.class.getResourceAsStream(filename));
70 | return doc;
71 |
72 | }
73 |
74 |
75 | public static void printText(String name, byte[] bytes) {
76 | System.out.println(name + ": "+ new String(bytes));
77 | System.out.println(name + "length: " + bytes.length + " bytes, " + bytes.length * 8 + " bits.");
78 | System.out.println("\r\n");
79 | }
80 |
81 | public static void printByteArray(String name, byte[] bytes) {
82 | System.out.println(name + ": "+ Hex.encodeHexString(bytes));
83 | System.out.println(name + " length: " + bytes.length + " bytes, " + bytes.length * 8 + " bits.");
84 | System.out.println("\r\n");
85 | }
86 |
87 | public static String byteArrayToHexString(Key key) {
88 | return byteArrayToHexString(key.getEncoded());
89 | }
90 |
91 | public static String byteArrayToHexString(byte[] b) {
92 | StringBuffer sb = new StringBuffer(b.length * 2);
93 | for (int i = 0; i < b.length; i++) {
94 | int v = b[i] & 0xff;
95 | if (v < 16) {
96 | sb.append('0');
97 | }
98 | sb.append(Integer.toHexString(v));
99 | }
100 | return sb.toString().toUpperCase();
101 | }
102 |
103 | public static void loadProvider() {
104 | Security.addProvider(new BouncyCastleProvider());
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/KeystoreTest.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto;
2 |
3 | import org.bouncycastle.asn1.DERNull;
4 | import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
5 | import org.bouncycastle.asn1.x500.X500Name;
6 | import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
7 | import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
8 | import org.bouncycastle.cert.X509CertificateHolder;
9 | import org.bouncycastle.cert.X509v3CertificateBuilder;
10 | import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
11 | import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
12 | import org.bouncycastle.crypto.util.PrivateKeyFactory;
13 | import org.bouncycastle.operator.ContentSigner;
14 | import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
15 | import org.bouncycastle.operator.OperatorCreationException;
16 | import org.bouncycastle.operator.bc.BcContentSignerBuilder;
17 | import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
18 | import org.junit.Test;
19 |
20 | import java.io.FileOutputStream;
21 | import java.io.IOException;
22 | import java.math.BigInteger;
23 | import java.nio.file.Files;
24 | import java.nio.file.Path;
25 | import java.security.*;
26 | import java.security.cert.Certificate;
27 | import java.security.cert.CertificateException;
28 | import java.security.cert.X509Certificate;
29 | import java.util.*;
30 |
31 | public class KeystoreTest {
32 |
33 |
34 | @Test
35 | public void createKeyStore() throws GeneralSecurityException, IOException, OperatorCreationException {
36 | if (Files.exists(Path.of("myStore.pkcs12"))) {
37 | Files.delete(Path.of("myStore.pkcs12"));
38 | }
39 | KeyStore keyStore = KeyStore.getInstance("PKCS12");
40 | keyStore.load(null, null);
41 | //create keypair
42 | KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
43 | kpg.initialize(2048);
44 | KeyPair kp = kpg.generateKeyPair();
45 | Key pub = kp.getPublic();
46 | Key pvt = kp.getPrivate();
47 | X509Certificate x509Certificate = generateRootCert(kp);
48 | keyStore.setCertificateEntry("myRootCertificate", x509Certificate);
49 | Certificate[] chain = {x509Certificate};
50 | keyStore.setKeyEntry("myPrivateKey", pvt, "password".toCharArray(), chain);
51 | keyStore.store(new FileOutputStream("myStore.pkcs12"), "password".toCharArray());
52 | Enumeration enums = keyStore.aliases();
53 | System.out.println("aliases:");
54 | enums.asIterator().forEachRemaining(System.out::println);
55 | Key key = keyStore.getKey("myPrivateKey", "password".toCharArray());
56 | System.out.println(key.toString());
57 | Certificate certificate = keyStore.getCertificate("myRootCertificate");
58 | System.out.println(certificate.toString());
59 | }
60 |
61 | public X509Certificate generateRootCert(KeyPair pair) throws IOException, OperatorCreationException, CertificateException {
62 | Calendar expiry = Calendar.getInstance();
63 | expiry.add(Calendar.DAY_OF_YEAR, 365);
64 |
65 | //final GeneralNames subjectAltNames = new GeneralNames(new GeneralName(GeneralName.iPAddress, "127.0.0.1"));
66 | //certificateBuilder.addExtension(org.bouncycastle.asn1.x509.Extension.subjectAlternativeName, false, subjectAltNames);
67 |
68 | AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption);
69 | AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(algorithmIdentifier.getAlgorithm(), DERNull.INSTANCE);
70 | final AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
71 | final BcContentSignerBuilder signerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId);
72 | final AsymmetricKeyParameter keyp = PrivateKeyFactory.createKey(pair.getPrivate().getEncoded());
73 | final ContentSigner signer = signerBuilder.build(keyp);
74 |
75 | X509v3CertificateBuilder x509v3CertificateBuilder = new X509v3CertificateBuilder(
76 | new X500Name("CN=Root Certificate"),
77 | BigInteger.ONE,
78 | new Date(),
79 | expiry.getTime(),
80 | Locale.ENGLISH,
81 | new X500Name("CN=Root Certificate"),
82 | SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded())
83 | );
84 | final X509CertificateHolder x509CertificateHolder = x509v3CertificateBuilder.build(signer);
85 | final X509Certificate certificate = new JcaX509CertificateConverter()
86 | .getCertificate(x509CertificateHolder);
87 | return certificate;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/test/java/nl/craftsmen/crypto/util/CryptoToolboxCrypto.java:
--------------------------------------------------------------------------------
1 | package nl.craftsmen.crypto.util;
2 |
3 | import org.apache.logging.log4j.LogManager;
4 | import org.apache.logging.log4j.Logger;
5 | import org.apache.ws.security.WSSecurityException;
6 | import org.apache.ws.security.components.crypto.CredentialException;
7 | import org.apache.ws.security.components.crypto.Merlin;
8 |
9 | import javax.security.auth.x500.X500Principal;
10 | import java.io.IOException;
11 | import java.lang.reflect.Constructor;
12 | import java.lang.reflect.InvocationTargetException;
13 | import java.math.BigInteger;
14 | import java.security.KeyStoreException;
15 | import java.security.cert.Certificate;
16 | import java.security.cert.X509Certificate;
17 | import java.util.Enumeration;
18 | import java.util.Properties;
19 |
20 | /**
21 | * Extension of Merlin class to fix bug WS-218 of WSS4J where the alias lookup based on a serial and issuer fails if
22 | * there are other objects in the keystore besides certificates. TODO remove this class and replace it with Merlin in
23 | * the SOAPSignerImpl when WSS4J 1.5.9 is released, which fixes this bug.
24 | */
25 | public class CryptoToolboxCrypto extends Merlin {
26 |
27 | /** Logger. */
28 | private static final Logger LOG = LogManager.getLogger(CryptoToolboxCrypto.class);
29 |
30 | /** Constant. */
31 | private static final Constructor