Extremely Serious

Category: Security (Page 2 of 4)

Generating a Self-signed CA Certificate for JSON Web Token (JWT) in Java

In the world of secure communication and authentication, JSON Web Tokens (JWTs) play a crucial role. They are often used to verify the authenticity of clients and servers, ensuring secure data transmission. In this guide, we will walk you through the steps to generate a self-signed CA certificate for JWTs in Java.

Prerequisites

Before we get started, make sure you have the necessary tools and binaries installed. If you're using Windows, you can download the OpenSSL binaries from slproweb.com.

Step 1: Generate an RSA Private Key

The first step is to generate an RSA private key, which will be used to create the self-signed certificate. Open your terminal or command prompt and run the following command:

openssl genrsa -aes256 -out jwt.private.pem 2048

This command generates an encrypted PEM private key. If you wish to generate a decrypted PEM based on it, you can use the following command:

openssl rsa -in jwt.private.pem -out decrypted.jwt.private.pem

Step 2: Generate a Public Key (Optional)

Generating a public key is optional in the context of creating a self-signed CA certificate for JWTs in Java. However, if you want to generate one, use the following command:

openssl rsa -pubout -in jwt.private.pem -out jwt.public.pem

The public key generation is not used in the Java keystores, but it can be useful for other purposes.

Step 3: Generate a Self-signed CA Certificate

Now, it's time to create the self-signed CA certificate using the private key you generated earlier. This certificate will be valid for one year. Customize the template by replacing the placeholder values with your own information. Run the following command:

openssl req -key jwt.private.pem -new -x509 -sha256 -days 365 -subj "/C=<2_LETTER_COUNTRY_CODE>/ST=<STATE_NAME>/L=<CITY_NAME>/O=<ORGANIZATION_NAME>/OU=<ORGANIZATIONAL_UNIT>/CN=<YOUR_NAME>/emailAddress=<YOUR_EMAIL_ADDR>" -out jwt.cert.pem

Here's a breakdown of the fields you need to replace:

  • <2_LETTER_COUNTRY_CODE>: The two-letter code of your country.
  • <STATE_NAME>: The name of your state.
  • <CITY_NAME>: The name of your city.
  • <ORGANIZATION_NAME>: The name of your organization.
  • <ORGANIZATIONAL_UNIT>: The name of your section in the organization.
  • <YOUR_NAME>: Your full name.
  • <YOUR_EMAIL_ADDR>: Your email address.

For example:

openssl req -key jwt.private.pem -new -x509 -sha256 -days 365 -subj "/C=NZ/ST=Wellington/L=Wellington/O=RnE/OU=IT/CN=Ronaldo Webb/emailAddress=ron@ronella.xyz" -out jwt.cert.pem

Step 4: Generate a PKCS12 File

Now, create a PKCS12 file by combining the generated private key and certificate. Give it the "selfsigned" alias using the following command:

openssl pkcs12 -export -in jwt.cert.pem -inkey jwt.private.pem -out jwt.pfx -name "selfsigned"

Step 5: Store the PKCS12 Content in a Java Keystore

Java applications often use keystores for certificate management. To store the content of the PKCS12 file in a Java keystore, use the following command:

"%JAVA_HOME%\bin\keytool" -importkeystore -destkeystore jwt-ks.jks -deststorepass password -deststoretype PKCS12 -srckeystore jwt.pfx -srcstoretype PKCS12 -srcstorepass password

Replace "%JAVA_HOME%" with the path to your Java installation directory and customize the keystore name and password as needed.

Step 6: Store the Certificate in a Java Truststore

In Java, truststores are used to store certificates that are trusted for secure communication. Store the certificate you generated earlier in a Java truststore with the "selfsigned" alias using the following command:

"%JAVA_HOME%\bin\keytool" -import -file jwt.cert.pem -keystore jwt-ts.jks -storetype PKCS12 -storepass password -alias selfsigned

Again, make sure to adjust the paths, keystore name, password, and alias according to your requirements.

By following these steps, you can generate a self-signed CA certificate for JWTs in Java, ensuring secure authentication and data transmission in your applications.

Related Topics

For further information on working with JWTs in Java, you can explore these related topics.

Generating a Self-signed CA Certificate for Java Keystores

Creating the java keystore and truststore with private key and certificate pair

  1. Download OpenSSL binaries from the following link if you are using windows:

    https://slproweb.com/products/Win32OpenSSL.html

  2. Create an openssl configuration (i.e. openssl.cnf) file using the following template:

    [ req ]
    default_bits        = 2048
    default_keyfile     = privkey.pem
    distinguished_name  = subject
    req_extensions      = req_ext
    x509_extensions     = x509_ext
    string_mask         = utf8only
    
    # The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
    #   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
    [ subject ]
    countryName         = Country Name (2 letter code)
    countryName_default     = <2_LETTER_COUNTRY_CODE>
    
    stateOrProvinceName     = State or Province Name (full name)
    stateOrProvinceName_default = <STATE_NAME>
    
    localityName            = Locality Name (eg, city)
    localityName_default        = <CITY_NAME>
    
    organizationName         = Organization Name (eg, company)
    organizationName_default    = <ORGANIZATION_NAME>
    
    organizationalUnitName   = Organizational Unit
    organizationalUnitName_default = <ORGANIZATIONAL_UNIT>
    
    # Use a friendly name here because it's presented to the user. The server's DNS
    #   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
    #   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
    #   must include the DNS name in the SAN too (otherwise, Chrome and others that
    #   strictly follow the CA/Browser Baseline Requirements will fail).
    commonName          = Common Name (e.g. server FQDN or YOUR name)
    commonName_default      = <YOUR_NAME>
    
    emailAddress            = Email Address
    emailAddress_default        = <YOUR_EMAIL_ADDRESS>
    
    # Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
    [ x509_ext ]
    
    subjectKeyIdentifier        = hash
    authorityKeyIdentifier    = keyid,issuer
    
    # You only need digitalSignature below. *If* you don't allow
    #   RSA Key transport (i.e., you use ephemeral cipher suites), then
    #   omit keyEncipherment because that's key transport.
    basicConstraints        = CA:FALSE
    keyUsage            = digitalSignature, keyEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "OpenSSL Generated Certificate"
    
    # RFC 5280, Section 4.2.1.12 makes EKU optional
    #   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
    #   In either case, you probably only need serverAuth.
    # extendedKeyUsage    = serverAuth, clientAuth
    
    # Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
    [ req_ext ]
    
    subjectKeyIdentifier        = hash
    
    basicConstraints        = CA:FALSE
    keyUsage            = digitalSignature, keyEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "OpenSSL Generated Certificate"
    
    # RFC 5280, Section 4.2.1.12 makes EKU optional
    #   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
    #   In either case, you probably only need serverAuth.
    # extendedKeyUsage    = serverAuth, clientAuth
    
    [ alternate_names ]
    
    DNS.1       = <DNS_1>
    
    # Add more DNS by incrementing the DNS.<SUFFIX> like the following.
    # DNS.2       = <DNS_2>
    # DNS.3       = <DNS_3>
    # DNS.4       = <DNS_4>
    
    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    
    # IPv6 localhost
    # DNS.8     = ::1
    
    # IP address using the following:
    # IP.1       = 127.0.0.1

    Replace the following fields on the template:

    Field Name Description
    2_LETTER_COUNTRY_CODE The two letter code of your country.
    STATE_NAME The name of your state.
    CITY_NAME The name of your city.
    ORGANIZATION_NAME The name of your organization.
    ORGANIZATIONAL_UNIT The name of your section in the organization.
    YOUR_NAME Your full name.
    YOUR_EMAIL_ADDR Your email address.
    DNS.<INDEX> Your DNS name.

    Example:

    [ req ]
    default_bits        = 2048
    default_keyfile     = privkey.pem
    distinguished_name  = subject
    req_extensions      = req_ext
    x509_extensions     = x509_ext
    string_mask         = utf8only
    
    # The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
    #   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
    [ subject ]
    countryName         = Country Name (2 letter code)
    countryName_default     = NZ
    
    stateOrProvinceName     = State or Province Name (full name)
    stateOrProvinceName_default = Wellington
    
    localityName            = Locality Name (eg, city)
    localityName_default        = Wellington
    
    organizationName         = Organization Name (eg, company)
    organizationName_default    = My Organization
    
    organizationalUnitName   = Organizational Unit
    organizationalUnitName_default = IT Department
    
    # Use a friendly name here because it's presented to the user. The server's DNS
    #   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
    #   by both IETF and CA/Browser Forums. If you place a DNS name here, then you
    #   must include the DNS name in the SAN too (otherwise, Chrome and others that
    #   strictly follow the CA/Browser Baseline Requirements will fail).
    commonName          = Common Name (e.g. server FQDN or YOUR name)
    commonName_default      = Ronaldo Webb
    
    emailAddress            = Email Address
    emailAddress_default        = ron@ronella.xyz
    
    # Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
    [ x509_ext ]
    
    subjectKeyIdentifier        = hash
    authorityKeyIdentifier    = keyid,issuer
    
    # You only need digitalSignature below. *If* you don't allow
    #   RSA Key transport (i.e., you use ephemeral cipher suites), then
    #   omit keyEncipherment because that's key transport.
    basicConstraints        = CA:FALSE
    keyUsage            = digitalSignature, keyEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "OpenSSL Generated Certificate"
    
    # RFC 5280, Section 4.2.1.12 makes EKU optional
    #   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
    #   In either case, you probably only need serverAuth.
    # extendedKeyUsage    = serverAuth, clientAuth
    
    # Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
    [ req_ext ]
    
    subjectKeyIdentifier        = hash
    
    basicConstraints        = CA:FALSE
    keyUsage            = digitalSignature, keyEncipherment
    subjectAltName          = @alternate_names
    nsComment           = "OpenSSL Generated Certificate"
    
    # RFC 5280, Section 4.2.1.12 makes EKU optional
    #   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
    #   In either case, you probably only need serverAuth.
    # extendedKeyUsage    = serverAuth, clientAuth
    
    [ alternate_names ]
    
    DNS.1       = www.ronella.xyz
    
    # Add more DNS by incrementing the DNS.<SUFFIX> like the following.
    # DNS.2       = <DNS_2>
    # DNS.3       = <DNS_3>
    # DNS.4       = <DNS_4>
    
    # Add these if you need them. But usually you don't want them or
    #   need them in production. You may need them for development.
    # DNS.5       = localhost
    # DNS.6       = localhost.localdomain
    
    # IPv6 localhost
    # DNS.8     = ::1
    
    # IP address using the following:
    # IP.1       = 127.0.0.1
  3. Save the openssl.cnf on your desired location.

  4. Generate the private key and certificate with 1yr validity using the following command:

    openssl req -config openssl.cnf -new -x509 -sha256 -newkey rsa:2048 -keyout privkey.pem -days 365 -out cert.pem
  5. Generate a pkcs12 file from the generated private key and certificate with the selfsigned alias using the following command:

    openssl pkcs12 -export -in cert.pem -inkey privkey.pem -out cert.pfx -name selfsigned
  6. Store the pfx file to a java keystore using the following command:

    "%JAVA_HOME%\bin\keytool" -importkeystore -destkeystore keystore.jks -deststorepass password -deststoretype PKCS12 -srckeystore cert.pfx -srcstoretype PKCS12 -srcstorepass password
  7. Store the certificate to a java truststore using the following command:

    "%JAVA_HOME%\bin\keytool" -import -file cert.pem -keystore truststore.jks -storetype PKCS12 -storepass password -alias selfsigned

Simple Java Keystore Management

Importing a certificate to a keystore

keytool -importcert -alias <ALIAS> -v -keystore <KEYSTORE_FILE> -file <INPUT_FILE> -storepass <KEYSTORE_PASSWORD>

Listing the certificates from a keystore

keytool -list -v -keystore <KEYSTORE_FILE> -storepass <KEYSTORE_PASSWORD>

Include the -a <ALIAS> parameter to just display a single certificate

Delete a certificate from a keystore

keytool -delete -v -alias <ALIAS> -keystore <KEYSTORE_FILE> -storepass <KEYSTORE_PASSWORD>

Deleting an Entry from a Java Keystore

Use the following command to delete an entry of a Java keystore:

The keytool is normally found in $JAVA_HOME/jre/bin (i.e. the $JAVA_HOME variable is where you’ve installed JDK).

keytool -delete -v -alias <ALIAS> -keystore <KEYSTORE_FILE> -storepass <KEYSTORE_PASSWORD>
Token Description
ALIAS The alias used upon importing the certificate.
KEYSTORE_FILE The target key store file (e.g. cacerts found in $JAVA_HOME/jre/lib/security)
KEYSTORE_PASSWORD The password for accessing the keystore (i.e. the default is changeit)

Requesting for Certificate with certbot-auto

Requesting for certificate

certbot-auto certonly -m <EMAIL_NAME> --webroot -w <WEBROOT_PATH> -d <DOMAIN_NAMES>

Example

certbot-auto certonly -m admin@example.com --webroot -w /usr/share/nginx/www -d www.example.com

Expanding your certificates

certbot-auto certonly --webroot --agree-tos -w <WEBROOT_PATH> --expand -d <DOMAIN_NAMES>

Example

certbot-auto certonly --webroot --agree-tos -w /usr/share/nginx/blog --expand -d blog.example.com

Display information about certificates you have from Certbot

certbot-auto certificates

Finding out the Banned IPs of Fail2Ban

Use the following command to find out the active jail names:

sudo fail2ban-client status

Use the following command to find out the banned IP by jail name:

sudo fail2ban-client status <JAIL_NAME>

Where:

JAIL_NAME The name of the jail.

Example:

Use the following command to find out all the banned IPs of an sshd jail name:

sudo fail2ban-client status sshd

Importing a PKCS12 Key Store to Java Keystore

Use the following command in importing a pkcs12 keystore to Java keystore:

The keytool is normally found in $JAVA_HOME/jre/bin (i.e. the $JAVA_HOME variable is where you've installed JDK).

keytool -importkeystore -v -srckeystore <SRC_KEYSTORE_FILE> -srcstoretype pkcs12 -destkeystore <DEST_KEYSTORE_FILE> -deststoretype JKS -storepass <KEYSTORE_PASSWORD>
Token Description
SRC_KEYSTORE_FILE The source keystore file (i.e. normally with the extension pfx) of type pkcs12.
DEST_KEYSTORE_FILE The destination keystore file (i.e. normally with the extension jks) of type jks.
KEYSTORE_PASSWORD The password for accessing the DEST_KEYSTORE_FILE

Template of Using SSL with JavaMail API

Gradle dependency

compile group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'

Import to the Class File

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;

The Template

// Recipient's email ID needs to be mentioned.
String to = <RECIPIENTS_EMAIL>;

//Sender's email ID needs to be mentioned
String from = <SENDERS_EMAIL>;

//The subject of the email.
String subject = <EMAIL_SUBJECT>;

//The body of the email.
String body = <EMAIL_BODY>;

//SMTP Server
final String host = <SMTP_SERVER>;

//SMTP Port
final String port = <SMTP_PORT>;

//SMTP Username
final String username = <USERNAME>;

//SMTP Password
final String password = <PASSWORD>;

try {
    //SMTP Configuration
    Properties props = new Properties();
    props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.host", host);
    props.put("mail.smtp.port", port);

    // Create a session object.
    Session session = Session.getInstance(props,
        new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        }
    );

    // Create a message object.
    Message message = new MimeMessage(session);

    // Set From: header field of the header.
    message.setFrom(new InternetAddress(from));

    // Set To: header field of the header.
    message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));

    // Set Subject: header field
    message.setSubject(subject);

    // Now set the actual message
    message.setText(body);

    // Send message
    Transport.send(message);

    System.out.println("Sent message successfully....");

} catch (MessagingException e) {
    throw new RuntimeException(e);
}

Blocking/Unblocking IP in Ubuntu

Pre-requisite

Install the iptables-persistent package to automatically load saved iptables rules.

sudo apt-get install iptables-persistent

Lists the rules in a chain or all chains

sudo iptables -L [CHAIN]

Where CHAIN sample value could be one of the following: INPUT, FORWARD or OUTPUT. If this is not provided all the chains will be listed.

Blocking an IP Address

sudo iptables -A INPUT -s <IP_ADDR> -j DROP
sudo sh -c "iptables-save > /etc/iptables/rules.v4"

Where IP_ADDR is the IP address to be blocked.

Unblocking an IP Address

sudo iptables -D INPUT -s <IP_ADDR> -j DROP
sudo sh -c "iptables-save > /etc/iptables/rules.v4"

Where IP_ADDR is the IP address to be unblocked if you use the preceding blocking procedure.

Java 6 to use TLS 1.2 by using BouncyCastle

  1. Download the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6. (i.e. if the link is already dead then download this instead jce_policy-6.)
  2. Extract the downloaded archive and follow the installation procedure found in the README.txt.
  3. Download the following Bouncy Castle libraries:
  4. Place the downloaded libraries into ${JAVA_HOME}/jre/lib/ext directory.
  5. Update the java.security (i.e. found in ${JAVA_HOME}/jre/lib/security directory.) file to have the following as the priority:
    security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider
    security.provider.2=org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
    

    Adjust the other security.provider to start from 3 like the following:

    security.provider.3=sun.security.provider.Sun
    security.provider.4=sun.security.rsa.SunRsaSign
    security.provider.5=com.sun.net.ssl.internal.ssl.Provider
    security.provider.6=com.sun.crypto.provider.SunJCE
    security.provider.7=sun.security.jgss.SunProvider
    security.provider.8=com.sun.security.sasl.Provider
    security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    security.provider.10=sun.security.smartcardio.SunPCSC
    security.provider.11=sun.security.mscapi.SunMSCAPI
    
  6. Try the following Java code:
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.ProtocolException;
    import java.net.URL;
    
    public class Main {
    
        public static void main(String[] args) {
            try {
                URL url = new URL("https://www.nist.gov/");
                System.out.println(url);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setDoOutput(true);
                System.out.println(connection.getResponseCode());
                StringBuilder response = new StringBuilder();
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    
                try {
                    String line = reader.readLine();
                    while (line != null) {
                        response.append(line);
                        line = reader.readLine();
                    }
                } finally {
                    reader.close();
                }
    
                System.out.println(response.toString());
            }
            catch(ProtocolException exception) {
                exception.printStackTrace();
            }
            catch(IOException exception) {
                exception.printStackTrace();
            }
        }
    }

    You should be able to access it without any SSL handshake error.

    Alternatively, you can opt to use the official JDK 6u121 via the Java SE 6 Advanced and Java SE 6 Support if you have availed of it.

« Older posts Newer posts »