TestTraits.java

public interface TestTraits {
    String EMPLOYEE_ID = "1";
    Long EMPLOYEE_ID_LONG = 1L;

    default EmployeeRpy getEmployee(){
        EmployeeRpy objEmpRpy = new EmployeeRpy();
        objEmpRpy.setEmpName("Mugil");
        objEmpRpy.setEmpAge("34");
        return objEmpRpy;

     default EmployeeDetailsResource createMockedEmployeeDetails() 
          throws IOException(){
       EmployeeDetailsResource objEmployeeDetailsResource = 
              new Gson.fromJson(getReader("json-data/EmployeeDetails.json"), EmployeeDetails.class);    
       return objEmployeeDetailsResource; 
     } 

     default Reader getReader(String filePath) throws IOException{
       return new FileReader(new ClassPathResource(filePath).getFile());  
     }
}

EmployeeDetails.json

  {
     "empID" : "101",
     "empName" : "Mugilvannan",
     "empAge" : "30"
  } 

EmployeeMgmtTest.java

 @ExtendWith({MockitoExtension.class})
 class EmployeeMgmtTest implements TestTraits{
    .
    . 
    Code for Testing Goes Here
    .
    .
 }

What @Springbootapplication does?

@SpringBootApplication = @Configuration + @ComponentScan + @EnableAutoConfiguration

  1. @Configuration to enable Java-based configuration
  2. @ComponentScan – This annotation enables component-scanning so that the web controller classes and other components you create will be automatically discovered and registered as beans in Spring’s Application Context. All the@Controller classes you write are discovered by this annotation..
  3. @EnableAutoConfiguration annotation tells Spring Boot to “guess” how you will want to configure Spring, based on the jar dependencies that you have added. For example, If HSQLDB is on your classpath, and you have not manually configured any database connection beans, then Spring will auto-configure an in-memory database.For example, if you add spring-boot-starter-web dependency in your classpath, it automatically configures Tomcat and Spring MVC.
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

What @springboottest annotation should do?

  1. Should check whether Java-based configuration are loaded
  2. Should do component scan and create beans.
  3. Should assign appropriate beans by resolving

@SpringBootTest annotation is used to bootstrap the entire container. The annotation works by creating the ApplicationContext that will be utilized in our tests. @SpringBootTest annotation works by creating the ApplicationContext used in our tests through SpringApplication.It starts the embedded server, creates a web environment and then enables @Test methods to do integration testing.

  1. Below we have two class DBConfig.java and DBProperties.java.
  2. DBConfig loads DBProperties bean. DBProperties bean gets its value from application.yml
  3. In the below integration test we are going to check whether all the classes are properly getting loaded into application context.
  4. Classes loaded using @SpringBootTest would be available only in the context of the class in which it is used. Just because you add the list of classes in TestConfigApplicationTests.java it wont be available in other test classes(DatasourceConfigTest.java, ExampleConfigurationTest.java)

DBProperties.java

package com.mugil.org.configs;

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.ArrayList;
import java.util.List;

@ConfigurationProperties(prefix = "spring.datasource")
public class DBProperties {   
    private String userName;
    private String password;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

DBConfig.java

@Configuration
@EnableConfigurationProperties(DBProperties.class) // Tells from which class is needed for creation of Beans
public class DBConfig {

    @Bean
    public DBProperties dbProperties(){
        DBProperties objDBProperties = new DBProperties();
        return objDBProperties;
    }
}

application.yml

spring:
  profiles:
    active: dev
---
spring:
  config:
    activate:
      on-profile: dev
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    password: root
    url: jdbc:mysql://localhost:3306/db
    username: root
  servers:
    - www.abc.test.com
    - www.xyz.test.com

---
spring:
  config:
    activate:
      on-profile: production
  datasource:
    driver-class-name: org.h2.Driver
    password: sa
    url: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
    username: sa
  servers:
    - www.abc.com
    - www.xyz.com

TestConfigApplication.java

package com.mugil.org;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestConfigApplication {
	public static void main(String[] args) {
		SpringApplication.run(TestConfigApplication.class, args);
	}
}

@SpringBootTest loads the DBConfig.java and creates DBProperties bean by reading values from application.yml file. The SpringBootTest ensures that all loading of beans defined in configuration file and all the values needed from application.yml and application.properties are available without any issue.

In case if you want to have any class to be autowired in @SpringBootTest class, the same should be defined in @SpringBootTest(classes = DBConfig.class) annotation.

The below @SpringBootTest takes classes which should be available by the time the application is bootstrapped. So we are expecting the properties to be read from application.yml and the bean gets created. Incase there is a problem the test case would fail below.

TestConfigApplication.java

package com.mugil.org;

import com.mugil.org.configs.DBConfig;
import com.mugil.org.configs.DBProperties;
import com.mugil.org.configs.ExampleConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(classes = {DBConfig.class})
class TestConfigApplicationTests {
	@Autowired
	DBProperties dbProperties;

	@Test
	void contextLoads() {
		System.out.println(dbProperties.getUserName());
	}
}

Below is a test which check if the value are loaded from yaml and is not null.
DatasourceConfigTest.java

package com.mugil.org.configs;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@SpringBootTest(classes = DBConfig.class)
class DatasourceConfigTest{

    //This is same as using context.run method where the beans would be initialized
    //context.run method in our case is invoked because of @SpringBootTest defined class
    @Autowired
    DBProperties dbProperties;

    @Test
    public void dbConfigTest() throws Exception {
        final String name = dbProperties.getUserName();

        //We can check whether the property is getting loaded and its not null only not null
        assertNotNull(name);
    }
}
  1. The @SpringBootTest annotation tells Spring Boot to look for a main configuration class (one with @SpringBootApplication , for instance) and use that to start a Spring application context.
  2. Spring Boot Integration Testing is running an application in ApplicationContext and run tests.spring-boot-starter-test which will internally use spring-test and other dependent libraries
  3. @SpringBootTest annotation works by creating the ApplicationContext used in our tests through SpringApplication.It starts the embedded server, creates a web environment and then enables @Test methods to do integration testing.

ExampleConfiguration.java

package com.mugil.org.configs;

import com.mugil.org.services.ExampleService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ExampleConfiguration {

    @Bean
    ExampleService exampleService() {
        ExampleService exampleService = new ExampleService();
        return exampleService;
    }
}

Below is the testing of the same functionality in a different way. Instead of using @SpringBootTest we are loading the class with help of ApplicationContextRunner and checking whether the loaded class – ExampleConfiguration.java dependencies – ExampleService.java in turn gets loaded

How to check if bean from particular configuration is loaded
ExampleConfigurationTest.java

package com.mugil.org.configs;

import com.mugil.org.services.ExampleService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

import static org.assertj.core.api.Assertions.assertThat;

class ExampleConfigurationTest {

    /*
     * I setup a context runner with the class ExampleConfiguration
     * in it. For that, I use ApplicationContextRunner#withUserConfiguration()
     * methods to populate the context.
     */
    ApplicationContextRunner context = new ApplicationContextRunner()
            .withUserConfiguration(ExampleConfiguration.class);

    @Test
    public void should_check_presence_of_example_service() {
        /*
         * We start the context, and we will be able to trigger
         * assertions in a lambda receiving a
         * AssertableApplicationContext
         */

        context.run(it -> {
            /*
             * I can use assertThat to assert on the context
             * and check if the @Bean configured is present
             * (and unique)
             */
            assertThat(it).hasSingleBean(ExampleService.class);
        });
    }
}

new ApplicationContextRunner() creates a new context and creates the bean by loading the configuration

For further reference check the code in the Link

Below is a static util class which can be used to check the list of beans available in the application context

ExampleConfigurationTest.java

package com.mugil.org.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

@Service
public class SpringUtils implements ApplicationContextAware {
    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        ctx = appContext;
    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}

} Below is a static util class that can be used to check the list of beans available in the application context

ExampleConfigurationTest.java

package com.mugil.org.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

@Service
public class SpringUtils implements ApplicationContextAware {
    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext appContext)
            throws BeansException {
        ctx = appContext;
    }

    public static ApplicationContext getApplicationContext() {
        return ctx;
    }
}

SomeRandomClass.java

class SomeRandomClass
{
    @Autowired
    SpringUtils springUtils;

    
    public void getBeans() 
    {  
        String[] beans = springUtils.getApplicationContext().getBeanDefinitionNames();
        Arrays.sort(beans);
        for (String bean : beans)
        {
            System.out.println(bean + " of Type :: " + springUtils.getApplicationContext().getBean(bean).getClass());
        }
}
}

Output

DBConfig of Type :: class com.mugil.org.configs.DBConfig$$EnhancerBySpringCGLIB$$d32ee4ac
dbProperties of Type :: class com.mugil.org.configs.DBProperties
spring.datasource-com.mugil.org.configs.DBProperties of Type :: class com.mugil.org.configs.DBProperties
springUtils of Type :: class com.mugil.org.utils.SpringUtils

In case if you don’t want to create a separate class and wanted to access beans in the context you can implement the ApplicationContextAware interface and specify the for loop in overridden setApplicationContext method.

How to load a single class into ApplicationContext

.
.
ApplicationContextRunner context = new ApplicationContextRunner().withUserConfiguration(ExampleConfiguration.class);
.
.

When the client communicates with the server over HTTPS either browser or REST call, the server doesn’t care who the client is, as long as they have the correct credentials. This is what happens in Login forms(Asymmetric communication followed by Symmetric Communication).

Two-way SSL is used for places where you only want the server to accept connections from a restricted number of users. It helps to mitigate the risk of fraud in online transactions. Two-way SSL authentication (also known as “mutual authentication”, or “TLS/SSL with client certificates”) where two parties authenticate
each other through verifying provided digital certificates, so that both parties are assured of the other’s identity.

In One-way SSL, where the browser (the client) establishes an SSL connection to a secure web site and the server’s certificate is checked, creating SSL authentication in RESTful web services. The browser either relies on itself or the operating system providing a list of certs that have been designated as trusted Certificate Authorities (CA).

In context to java, Java Key Store is used to store the certs and keys.It must be password protected and entries in it must have an “alias” that is unique. If an alias is not specified, “mykey” is used by default.

KeyStores provide credentials, TrustStores verify credentials.Clients will use certificates stored in their TrustStores to verify identities of servers. They will present certificates stored in their KeyStores to servers requiring them.

The JDK ships with a tool called Keytool. It manages a JKS of cryptographic keys, X.509 certificate chains, and trusted certificates.

//Importing a truststore which could be used by client for server certificate verification
>> keytool -import -v -trustcacerts -keystore client_truststore.jks -storepass apassword -alias server -file foo.snaplogic.com.cert

//Importing a keystore which could be used by client when server asks of identity certificate
>> keytool -importkeystore -srckeystore client-certificate.p12 -srcstoretype pkcs12 -destkeystore client_keystore.jks -deststoretype jks -deststorepass apassword

// Viewing list of servcer certificates in Client Truststore  
>> keytool -list -v -keystore client_truststore.jks

We can now complete configuration of the REST SSL Account by uploading our client_truststore.jks and client_keystore.jks KeyStore files

One way SSL

  1. Client requests for some protected data from the server on HTTPS protocol. This initiates SSL/TLS handshake process.
  2. Server returns its public certificate to the client along with server hello message.
  3. Client validates/verifies the received certificate. Client verifies the certificate through certification authority (CA) for CA signed certificates.
  4. SSL/TLS client sends the random byte string that enables both the client and the server to compute the secret key to be used for encrypting subsequent message data. The random byte string itself is encrypted with the server’s public key.
  5. After agreeing on this secret key, client and server communicate further for actual data transfer by encrypting/decrypting data using this key.

Two way SSL

  1. Client requests a protected resource over HTTPS protocol and the SSL/TSL handshake process begins.
  2. Server returns its public certificate to the client along with server hello.
  3. Client validates/verifies the received certificate. Client verifies the certificate through certification authority (CA) for CA signed certificates.
  4. If Server certificate was validated successfully, client will provide its public certificate to the server.
  5. Server validates/verifies the received certificate. Server verifies the certificate through certification authority (CA) for CA signed certificates.
  6. After completion of handshake process, client and server communicate and transfer data with each other encrypted with the secret keys shared between the two during handshake.

When Creating a certificate the first thing we do is creating a public and private keys. The Keys generated using java keytool or either by using keystore comes with a self signed certificate which could not be verified with CA. To win third party trust we get our public key signed with someone who is in common between thirdparty and data provider(server). This common entity is nothing but Certificate Authority(CA). To Apply for certificate we should create a CSR Request along with organization name, common name (domain name), locality, and country details.

Certificate Signing Request
A CSR or Certificate Signing request is a block of encoded text that is given to a Certificate Authority when applying for an SSL Certificate. It is usually generated on the server where the certificate will be installed and contains information that will be included in the certificate such as the organization name, common name (domain name), locality, and country. It also contains the public key that will be included in the certificate. A private key is usually created at the same time that you create the CSR, making a key pair. A certificate authority will use a CSR to create your SSL certificate, but it does not need your private key. You need to keep your private key secret. The certificate created with a particular CSR will only work with the private key that was generated with it. So if you lose the private key, the certificate will no longer work.

The CSR is signed by the applicant’s private key.This proves to the CA that the applicant has control of the private key that corresponds to the public key included in the CSR.

How does a CSR looks like?

-----BEGIN CERTIFICATE REQUEST-----
MIIC5jCCAc4CAQAwcTELMAkGA1UEBhMCSU4xEjAQBgNVBAgTCXRhbWlsbmFkdTEQMA4GA1UEBxMH
Y2hlbm5haTESMBAGA1UEChMJbXVnaWwub3JnMRIwEAYDVQQLEwltdWdpbC5vcmcxFDASBgNVBAMT
C211Z2lsdmFubmFuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9alda8sBOwSPXBOV
IyWD2bgn96RkCcoP1hNE7wsV1sus6mGFpptcF9qu6NZib+7acjRRjFnC5yTgzVOBLse0c3/EQ8H4
KZ+AAgye2++kFmdfwCjeoPeylUaYL2hEdb/cfSIJD4tulpuuocQf1N/X6+Z7W2ojzz9KpCkVhxYv
iuk+V2/zE5Z+kTwDVEPw/t9FKYTkf4+Viv+AGnyZHI3ZjgfLhccLaVL/kxJ8Y62wBC/muFK4CN92
xotBoTj3u7eQyoKb+NsaEvvQK+8+CYacjwMrsrMSPEmyHEAjmfWFkBi/4ZBF1vWhL9tBYZaXqjk5
0npE8fZTEOexO+hNeZVUQwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUV9G4Cp5/
QslDtFRjFOXcjj5kYRkwDQYJKoZIhvcNAQELBQADggEBAAejlSzDMUuAbqSe3zNxOADSTJCqhsJU
FE+0F0lxJlkKB6cDcxSvujoDoCuARk0RF0yLfnQz54qUPjWcPWnawLs9nZF/nzFf/ylF3J41fgVX
VveyKPc7TG40S5zGI5R1Y0zpW0hE/O2vZ4kdD1ZaO7UaUmFPZUcGhJWdf2QJh7enEhK6Z+FM19B/
RTySjmDIYKyMAgh65IDqutJD89FcrQx0UcAK0WCe6xR5dylg0FNiEw4GDorJF+HlMp2YXkUuYHNZ
RAZBvjqoic4CyZ60/HhXUruStn7ElB1hga10HyfGanclmfX2+vU5W+ulkhj1xvo4JHJC4AlmKdFZ
fm69MwU=
-----END CERTIFICATE REQUEST-----

Certificate Authority
Whether it is one-way SSL or two-way SSL, certificate-based communication starts through a handshake mechanism that works on the principles of mutual trust. This trust is rooted at the top level with a root CA who is a certified, highly regulated authority that is trusted and authorized to issue and sign digital certificates.

There are multiple layers of CA with the top-most Certificate Authority known as Root CA which is the most trusted body which can issue Root Certificates and is considered as the primary authority to be trusted. Under Root CA, there can be n number of Intermediate CAs which are themselves trusted by Root CA and are eligible and authorized to issue certificates.

Typically, your web browsers store Root CAs certificates in the trust store, and whenever any secure website is accessed, SSL handshake mechanism works by utilizing this trust store to validate any subsequent intermediate or leaf certificates.

//Generate a Keystore with public and Pricate key along with selfsigned certificate
>>keytool -genkey -alias mugilcert2 -keyalg RSA -keystore “D:\mugil2.jks”

//Exporting a self signed certificate which came along in above step(which is are of no use)
>>keytool -export -alias mugilcert2 -file “D:\mugil2jks.cer” -keystore “D:\mugil2.jks”

//Generate a CSR request to be sent to CA
>>keytool -certreq -alias server -file csr.txt -keystore “D:\mugil2.jks”

Self-Signed Certificate
A self-signed SSL certificate is an SSL Certificate that is issued by the individual using it. It’s issued with software that the user has and controls. This can be good for testing environments but it’s got some major drawbacks, but essentially what you need to know is that when a browser receives an SSL Certificate it’s looking for it to be issued by a party it trusts(CA). When you sign your own certificate you’re essentially vouching for your own identity. The primary operational difference between a self-signed certificate and a CA certificate is that with self-signed, a browser will generally give some type of error, warning that the certificate is not issued by a CA.

Root Certificate, Intermediate Certificate and Leaf (Server) Certificate
Root Certificates are available in the trust-store or root store and a certificate validity is confirmed only if its chain of trust reaches to a trusted CA.Below are the list of companies that holds Root to certificate and could offer intermediate certificates.

  1. IdenTrust
  2. DigiCert
  3. GoDaddy

The above companies has tie-up with companies like google or mozilla which install trust store or root store in users systems.. Root CA is a Certificate Authority that owns one or more trusted roots. That means that they have roots in the trust stores of the major browsers. Intermediate CAs or Sub CAs are Certificate Authorities that issue off an intermediate root. They do not have roots in the browser’s trust stores, instead, their intermediate roots chain back to a trusted third-party root. This is sometimes called cross-signing.

Intermediate Certificates are in turn trusted by a Root Certificate by chain of Trust. CAs issue digital certificates to its clients (usually intermediate CAs).
Server Certificate (also known as Leaf Certificate) is a certificate that has been issued to a server by a intermediate CA. A certificate issued to a server is usually by an intermediate CA and a chain of certificates in the form of certificate bundles gets linked to the Root CA to build a trust chain.

In the above example DigiCert is root CA and Digicert2 extended validation server is Intermeidate CA.

Root Store
A root store contains list of trusted root CA certificates.A public-facing root store is usually maintained under the authority of a major software provider, which distributes their root store along with software which depends upon it to determine trust. Many providers of browsers and operating systems operate their own root store programs, and CAs may apply to be accepted into a root store using the criteria of that program. The device will use whatever root store is native to its OS, otherwise it might use a third-party root store via an app like a web browser. There are several major root programs of note:

  1. Microsoft
  2. Apple
  3. Google
  4. Mozilla

CAs do not issue directly from their roots. They add layers of security by issuing intermediates and then signing certificates with those. This helps to minimize and compartmentalize damage in the event of a mis-issuance or security event. Rather than revoke the root certificate and literally every certificate that it signed by extension, you just revoke the intermediate, which only causes the group of certificates issued off that intermediate to get distrusted.

Google and the other browsers recently distrusted Symantec CA brand SSL certificates. They just removed all of Symantec CA’s roots from their trust stores. Now any certificate that is supposed to chain back to those roots fails and is distrusted

Simple Pipeline

 Build -> Tests(QA) -> Deployment(Prod)

Trigger – One which starts an action. On Commit it should trigger a pipeline
Stage – Pipeline contains multiple stages. Stages are logical boundaries. Build, Test and Deployment above are all stages
Job – Stage contains multiple jobs. Build stage contains multiple jobs like asking for VM agent, Copying Target file to drop location
Steps – Job contains multiple steps. Steps can be a task or script which would be run.

Agents would be used to build artifacts in the pipeline. Agents may be based on windows, Linux or mac images which would be available on the fly when the build stage is started during pipeline execution

trigger:
- master

pool:
  vmImage: ubuntu-latest

stages:
- stage: Build
  jobs:
  - job: build
    steps:
    - script: 
        echo Displayed from Script
    - task: Npm@1
      inputs:
        command: 'install'    

Stages

stages:
- stage: string  # name of the stage, A-Z, a-z, 0-9, and underscore
  displayName: string  # friendly name to display in the UI
  dependsOn: string | [ string ]
  condition: string
  pool: string | pool
  variables: { string: string } | [ variable | variableReference ] 
  jobs: [ job | templateReference]

A digital signature in its simplest description is a hash (SHA1, MD5, etc.) of the data (file, message, etc.) that is subsequently encrypted with the signer’s private key. Since that is something only the signer has (or should have) that is where the trust comes from. EVERYONE has (or should have) access to the signer’s public key.

So, to validate a digital signature, the recipient

  1. Calculates a hash of the same data (file, message, etc.),
  2. Decrypts the digital signature using the sender’s PUBLIC key, and
  3. Compares the 2 hash values.

Sender – Alice is sending a digitally signed but not encrypted message to Receiver – Bob

  1. Sender generates a message digest of the original plaintext message using a secure hash function like SHA3-512.
  2. Sender then encrypts the message digest using her private key. The output is the digital signature.
  3. Sender appends the digital signature to the plaintext message.
  4. Sender then sends the appended message to Receiver. Sender sends digital signature + Plain Text Message + Certificate with Public Key
  5. Receiver removes the digital signature from the appended message and decrypts it with the public key of Sender.
  6. Receiver calculates the hash of the plaintext message with SHA3-512.
  7. Receiver then compares the decrypted message digest he received from Sender with the message digest Receiver computed. If the two digests match, he can be assured that the message he received was sent by Sender.

The digital signature process does not provide any privacy by itself. It only ensures that the cryptographic goals of authentication, integrity, and nonrepudiation are met. If Sender wants to ensure the privacy of her message to Receiver, she could encrypt the appended message generated in step 3 with the public key of Receiver. Receiver then would need to first decrypt the encrypted message with his private key before continuing with step 5.

What Sender Does?

Note: In the above step the hash is encrypted digitally signed using private key.In the side of the receiver public key should be used to decrypt hash for verification

What Receiver Does?

Encryption vs Digital Signature

In Encryption we use receivers public key to encrypt the message whereas when we digitally sign we use senders private to encrypt the hashed text(which is nothing again message we would like to send)

Encryption
Encryption is the act of converting plain text to cipher text. Cipher text is basically text that has been scrambled into non-readable format using an algorithm – called a cipher.

Public key encryption uses public/private key pairs. If you want me to send you an encrypted message, you send me your public key, which I import into my encryption software. I encrypt the message with your public key. When you receive the message, you decrypt it with your private key. Even though your public key can be freely distributed and used to encrypt messages addressed to you, these encrypted messages can only be decrypted with your own private key. This private key must always be kept secret. Data encrypted with the public key can only be decrypted with its corresponding private key. This is what happens in Brower Server Communication

Digital Signature
Message signing, on the other hand, uses the sender’s private key to sign the message, and his public key is used to read the signature. Message signing helps ensure data integrity, message authentication, and non-repudiation. For example, if John wants to digitally sign a message to Bob, he uses his private key to sign the message, and sends it (along with his public key if it hasn’t already been sent) to Bob. John’s public key is the only key that can verify the message signature.

In RSA crypto, when you generate a key pair, it’s completely arbitrary which one you choose to be the public key, and which is the private key. If you encrypt with one, you can decrypt with the other – it works in both directions. It is fairly simple to see how you can encrypt a message with the receiver’s public key so that the receiver can decrypt it with their private key.

A signature is proof that the signer has a private key that matches some public key. To do this, it would be enough to encrypt the message with that sender’s private key and include the encrypted version alongside the plaintext version. To verify the sender, decrypt the encrypted version, and check that it is the same as the plaintext.

Of course, this means that your message is not secret. Anyone can decrypt it because the public key is well known. But when they do so, they have proved that the creator of the ciphertext has the corresponding private key.

However, this means doubling the size of your transmission – plaintext, and ciphertext together (assuming you want people who aren’t interested in verifying the signature, to read the message). So instead, typically a signature is created by creating a hash of the plaintext. Fake hashes can never be created, so cryptographic hash algorithms such as SHA-2 are used.

  • To generate a signature, make a hash from the plaintext, encrypt it with your private key, include it alongside the plaintext.
  • To verify a signature, make a hash from the plaintext, decrypt the signature with the sender’s public key, check that both hashes are the same.

Encryption and Decryption
Encrytion and Decryption could use same key as in symmetric algorithm or could use different one. Below are the steps for Asymmetric encrytion.

  1. Alice wants to send a message to Bob which no one should be able to read.
    1. Alice encrypts the message with Bob’s public key and sends it over.
    2. Bob receives the message and decrypts it using his private Key.
    Note that if A wants to send a message to B, A needs to use the Public key of B (which is publicly available to anyone) and neither public nor private key of A comes into the picture here.
    

So if you want to send a message to me you should know and use my public key which I provide to you and only I will be able to decrypt the message since I am the only one who has access to the corresponding private key.

Digitally Signing Message

  1. Alice wants to send a message to Bob again. The problem of encrypting the data is solved using the above method.
  2. But what if I am sitting between Alice and Bob, introducing myself as ‘Alice’ to Bob and sending my own message to Bob instead of forwarding the one sent by Alice. Even though I can not decrypt and read the original message sent by Alice(that requires access to Bob’s private key) I am hijacking the entire conversation between them.
  3. Is there a way Bob can confirm that the messages he is receiving are actually sent by Alice?
  4. Alice signs the message with her private key and sends it over. (In practice, what is signed is a hash of the message, e.g. SHA-256 or SHA-512.)
    Bob receives it and verifies it using Alice’s public key. Since Alice’s public key successfully verified the message, Bob can conclude that the message has been signed by Alice.

What is JWT?
JSON Web Tokens (JWT) is a security mechanism to transfer information between two parties by using JSON-format tokens that are self-signed. Consumer of JWT can perform JWT signature verification, which is a cryptographic process to verify the authenticity of the information contained in the token, as well as validations of the information within the token payload.

The JWT will have the following components – Header, Payload/body,Signature

  xxxx.yyyy.zzzz

ie

  Base64URLencode(Header).Base64URLencode(body).Base64URLencode(signature)

Signature will have the following pseudo-code

  RSASHA256(Base64URLencode(Header).Base64URLencode(body), Secret)

JWT consists of three parts

  1. Header – Javascript Object Signing and Encryption (JOSE) Header. This part of the token provides details about the encryption mechanisms that must be applied to verify the token signature to confirm the authenticity of the information (claims) contained in the token.

    When working with JWKS, JOSE header will specify the following attributes:

    • Encryption algorithm – alg Declared with value “RS256” (asymmetric encryption algorithm, described at this specification)
    • Key id – kid This attribute contains the identifier for the public key that must be used to perform signature verification.
  2. Token payload – It consists on a set of key-value attributes commonly referred to as “Claims”, where the attribute name and value are called “Claim Name” and “Claim value”. Claims are ultimately the lowest level of information contained in the JWT, and can be used by the resource owners to determine any kind of information about the user who owns the token (access level, identity, authorization, etc.).
  3. Token signature – JWS. From the security standpoint, this is the most important part of a JWT, as it contains the token signature that must be used to perform the verification of the token. Token signature is the result of taking the token payload and apply RS256 encryption using the private key of the RSA key pair.

Token Signature = RS256 Encryption of Header, Payload signed with Secret

What are basic security goals?
Integrity is about making sure that some piece of data has not been altered from some “reference version”
Authenticity is about making sure that a given entity (with whom you are interacting) is who you believe it to be.
Non-repudiation It is the inability to refute responsibility. For example, if you take a pen and sign a (legal) contract your signature is a nonrepudiation device.Digital signature in this case.

What is the difference between Hash, MAC, and Digital Signature?
Hash – A (unkeyed) hash of the message, if appended to the message itself, only protects against accidental changes to the message (or the hash itself), as an attacker who modifies the message can simply calculate a new hash and use it instead of the original one. So this only gives integrity.
Message Authentication Code MAC – also known as keyed hash, protects against message forgery by anyone who doesn’t know the secret key (shared by sender and receiver). This means that the receiver can forge any message – thus we have both integrity and authentication (as long as the receiver doesn’t have a split personality), but not non-repudiation. MACs can be created from unkeyed hashes (e.g. with the HMAC construction), or created directly as MAC algorithms.
Digital Signature – A (digital) signature is created with a private key, and verified with the corresponding public key of an asymmetric key-pair. Only the holder of the private key can create this signature, and normally anyone knowing the public key can verify it. So this provides all of integrity, authentication, and non-repudiation.

Hash MAC(HMAC + SHA256) Digital Signature(RSA, PKCS1)
Integrity Yes Yes Yes
Authentication No Yes Yes
Non-repudiation No No Yes
Kind of keys None Symmetric Asymmetric

Does JWT is both Hashed and Signed?

JWT is both hashed and signed. Hashing algorithm used is specified in the Header. To make hashing stronger we use salt which is sometime refered as secret. However, using this secret is sometime confused with signing of JWT. Signing is a process where only the signer knows the key with which the payload is signed. As far the resource and authorization server are same usgae of the term signing and hashing holds true. Incase if resource and authorization server are different and symmetric key is used, signing payload should no longer used since signature is unique to entity but in above case there are two entities which holds the same signature.

Sometimes JWT is both hashed and signed. Most realtime implementation of JWT uses this methodology to make JWT more secure.

Why we do base64 encoding in JWT?
JWT is actually not Base64, instead, it’s Base64Url Encoded. It’s just like Base64, but there are a couple of characters different so that we can easily send a JWT as part of a Url parameter. All three parts of the JWT are Base64Url encoded, which makes the JWT URL-encoded, which means it can be shared between two or more parts using HTTP.

What are two common ways of implementation of JWT?

  1. Method 1 – Using asymmetric algorithm using public and private key. Implementing JWT using this method helps in authorization by Resource Server
  2. Method 2 – Using symmetric algorithm using same key for Signing. In this case only the server which has issued can authorize the user. The same copy of the key could be shared to resource server but at cost of compromising security scale.

Do we always need Public and Private Key?
No. It depends on the implementation. When the Authorization and the Resource server is same then we dont need two different keys. In this case the key is referred to as secret and secret is used for signing payload. But when Authorization and the Resource server are different then we need private key to sign the resource and public key to read the signature.

Symmetric Signing uses HS256 algorithm for signing. The same would be seen in header field.

{
   "typ":"JWT",
   "alg":"HS256"
}

Asymmetric signing uses RS256 algorithm for signing.

{
   "typ":"JWT",
   "alg":"RS256"
}

What is the difference between RS256 and HS256?
RS256 (RSA Signature with SHA-256) – is an asymmetric algorithm, and it uses a public/private key pair: the identity provider has a private (secret) key used to generate the signature, and the consumer of the JWT gets a public key to validate the signature. Since the public key, as opposed to the private key, doesn’t need to be kept secured, most identity providers make it easily available for consumers to obtain and use (usually through a metadata URL).

HS256 (HMAC with SHA-256) – on the other hand, involves a combination of a hashing function and one (secret) key that is shared between the two parties used to generate the hash that will serve as the signature. Since the same key is used both to generate the signature and to validate it, care must be taken to ensure that the key is not compromised.

If you will be developing the application consuming the JWTs, you can safely use HS256, because you will have control on who uses the secret keys. If, on the other hand, you don’t have control over the client, or you have no way of securing a secret key, RS256 will be a better fit, since the consumer only needs to know the public (shared) key exposed by JWK URL.

Why we need JWK Endpoints?
In Asymmetric signing public key should be exposed so who ever uses it could decrypt to read the signature. Validation will happen in the following steps

  1. Retrieve the JWKS from JWKS endpoint
  2. Get JWT and decode it.
  3. Grab the kid property from the header of the decoded JWT.
  4. Search the key with the matching kid property in retrieve keysets.
  5. Build a (public)certificate using the corresponding keyset
  6. Use the certificate to verify the JWT’s signature.

JSON Web Key & JSON Web Key Set
JWK consists on a JSON data structure that represents a cryptographic key. The members of the object represent properties of the key, including its value. A JWK Set is simply JSON data structure that represents a set of JWKs.

There are attributes that are mandatory within JWK, regardless on the signing algorithm

  1. kid (Key ID) Parameter is used to identify a key, with the purpose to choose among a set of keys within a JWK Set during key rollover. kid parameter is utilized to lookup the appropriate public key, as it is also included in the JWT JOSE header.
  2. kty (Key Type) Parameter. This attribute identifies the cryptographic algorithm family used with the key, such as “RSA” or “EC”.
  3. use (Public Key Use) Parameter. This parameter identifies the intended use of the public key. The “use” parameter is employed to indicate whether a public key is used for encrypting data or verifying the signature on data.
    Values defined by this specification are:

    1. sig (signature)
    2. enc (encryption)
  4. exp (Expiration) Parameter. Although “exp” is not mentioned in the JWK specification, it is widely used in the same way as described in the JWT specification, which can be found here. Its purpose is to define the expiration time for the given JWK. “exp” MUST be a number containing a NumericDate value.
  5. alg – parameter identifies the algorithm intended for use with the key.eg in RSA, we can have RSA256 or RSA512

JWT are used for authorization and not authentication. So a JWT will be created only after the user has been authenticated by the server by specifying the credentials. Once JWT has been created for all future interactions with the server JWT can be used. So JWT tells that server that this user has been authenticated, let him access the particular resource if he has the role.

Posted in JWT.

In JWT both Header and Payload is encoded to make it URL Safe but not encrypted. So any one can see the content after decoding the Header and Payload. We cannot send any sensitive data using JWT.The signature is created using the header, the payload, and the secret that is saved on the server.

   Signature = Header + Payload + Secret

The above process is Signing the JSON Web Token. The signing algorithm takes the header, the payload, and the secret to creating a unique signature. So only this data plus the secret can create this signature. Together with the header and the payload, these signature forms the JWT, which then gets sent to the client.

Once the server receives a JWT to grant access to a protected route, it needs to verify it in order to determine if the user really is who he claims to be. In other words, it will verify if no one changed the header and the payload data of the token. So again, this verification step will check if no third party actually altered either the header or the payload of the JSON Web Token.

The signature is an HMAC, which uses a particular type of cryptographic function. Such an HMAC algorithm is indicated with the “HS” prefix, as shown in the sample token above. The HMAC takes the header, the payload, and a secret key as input, and returns a unique signature over all three inputs. Service uses the same secret key to calculate the HMAC of the JWT. If the resulting HMAC is the same as the signature in the token, the service knows that all three inputs to the HMAC function were the same as before.

{
   "typ":"JWT",
   "alg":"HS256"
}

How Verification is Carried to check whether payload has been changed?

Once the JWT is received, the verification will take its header and payload, and together with the secret that is still saved on the server, basically create a test signature.

The original signature that was generated when the JWT was first created is still in the token which is the key to this verification. We have to compare the test signature with the original signature. And if the test signature is the same as the original signature, then it means that the payload and the header have not been modified. If they had been modified, then the test signature would have to be different. Therefore in this case where there has been no alteration of the data, we can then authenticate the user. And of course, if the two signatures are actually different, well, then it means that someone tampered with the data. Usually by trying to change the payload. Third party manipulating the payload does not have access to the secret(Private key used to sign), so they cannot sign the JWT. So the original signature will never correspond to the manipulated data. And therefore, the verification will always fail in this case.

Limitations of Symmetric Signatures
This signature scheme is straightforward. It is also the typical scheme used to explain JWTs to developers. Unfortunately, symmetric signatures prevent the sharing of the JWT with another service. To verify the JWT’s integrity, all services would need to have access to the same secret key. However, possession of the secret key is enough to generate arbitrary JWTs with a valid signature.

Sharing the HMAC secret with a third-party service creates a significant vulnerability. Even sharing the secret between different services within a single architecture is not recommended. If all services share the same key, the compromise of a single service immediately becomes an architecture-wide problem.

Instead of sharing the secret HMAC key, you can opt for using asymmetric signatures

Note: The above could be helpful of the Authorization Server and Resource Server is same.

Link to Repo

Posted in JWT.