Cryptography and Cryptanalysis in Java Creating and Programming Advanced Algorithms With Java SE 17 LTS and Jakarta EE 10
Cryptography and Cryptanalysis in Java Creating and Programming Advanced Algorithms With Java SE 17 LTS and Jakarta EE 10
Cryptanalysis in Java
Creating and Programming Advanced
Algorithms with Java SE 17 LTS and
Jakarta EE 10
—
Stefania Loredana Nita
Marius Iulian Mihailescu
Cryptography and
Cryptanalysis in Java
Creating and Programming Advanced
Algorithms with Java SE 17 LTS
and Jakarta EE 10
Chapter 1: Introduction�������������������������������������������������������������������������������������������� 1
Cryptography and Cryptanalysis��������������������������������������������������������������������������������������������������� 3
Book Structure������������������������������������������������������������������������������������������������������������������������������ 4
Conclusion������������������������������������������������������������������������������������������������������������������������������������ 6
References������������������������������������������������������������������������������������������������������������������������������������ 6
v
Table of Contents
vi
Table of Contents
Conclusion���������������������������������������������������������������������������������������������������������������������������������� 97
References���������������������������������������������������������������������������������������������������������������������������������� 97
vii
Table of Contents
Index��������������������������������������������������������������������������������������������������������������������� 223
viii
About the Authors
Stefania Loredana Nita, PhD, is a lecturer at “Ferdinand I” Military Technical Academy
of Bucharest and a software developer and researcher at the Institute for Computers. Her
PhD thesis was on advanced cryptographic schemes using searchable encryption and
homomorphic encryption. At the Military Technical Academy, she teaches the Formal
Languages and Translators and Database Application Development courses. She worked
for more than two years as an assistant lecturer at the University of Bucharest where
she taught courses on subjects such as advanced programming techniques, simulation
methods, and operating systems. Her research activity is in the cryptography field, with
a focus on searchable encryption and homomorphic encryption. She is also interested
in blockchain, quantum cryptography, machine learning, and artificial intelligence.
At the Institute for Computers, she is working on research and development projects
that involve cloud computing security, the Internet of Things, and big data. She has
authored or co-authored more than 28 papers at conferences and for journals and has
co-authored five books. Also, she holds an MSc in software engineering and two BSc
degrees in computer science and mathematics.
Marius Iulian Mihailescu, PhD, has worked in the academic and industry sector
for more than 15 years. Currently, he is an associate professor (senior lecturer) of
engineering and computer science at “Spiru Haret” University, Romania, and as a side
job he is a project manager at the Institute for Computers where he is managing different
projects using different technologies, such as DevOps, Scrum, Agile, C#, Microsoft
SQL Server, Syncfusion, ASP.NET, and VUE. At the university, he has taught several
key computer science courses about information security, functional programming,
Interne of Things, blockchain, software development methods (Microsoft Azure,
Entity Framework, NHibernate, LINQ-to-SQL, UX with DevExpress controls, etc.), and
development web applications (HTML 5, CSS 3, Bootstrap, JavaScript, AJAX, NodeJS,
VUE, Laravel, mRabbit, ASP.NET, PHP). He has authored or co-authored more than
ix
About the Authors
30 articles in conference proceedings, 25 articles in journals, and six books. For three
years he worked as an IT officer at Royal Caribbean Cruises Ltd. where he dealt with IT
infrastructures, data security, and satellite communications systems. He received his
PhD in 2014, and his thesis was on applied cryptography over biometrics data. He holds
two MSc degrees in information security and software engineering, from “Ferdinand I”
Military Technical Academy and the University of Bucharest, Romania.
x
About the Technical Reviewer
Doug Holland is a software engineer and architect at Microsoft Corporation. He
holds a master’s degree in software engineering from the University of Oxford. Before
joining Microsoft, he was honored with the Microsoft MVP and Intel Black Belt
Developer awards.
xi
CHAPTER 1
Introduction
In the last decade, technology has rapidly evolved. Statistics show that 64.2 zettabytes of
data were generated in 2020 (1 zettabyte is equivalent to 1021 bytes or 1012 gigabytes), and
it is predicted that by 2025, the digital data generated will reach 181 zettabytes [1, 2].
Electronic communication has become an essential part of our lives, and due to its
rapid evolution, all manner of security issues have arisen. Because digital messages,
in all of their forms, are sent daily over public networks across the world, the need
for secure channels and security mechanisms has also increased. Digital devices and
communications should have digital signatures that make them easy to authenticate.
Modern cryptography provides solutions for all these requirements.
The era in which we are living is considered the “zettabytes era,” in which technology
allows humans and electronic devices to generate and send information instantly, at
any time and any place. Advanced technologies, such as the Internet of Things, fog
computing, edge computing, smart vehicles, drones, smart houses, and many other
complex software (desktop/web/mobile) solutions or architectures, are evolving so
quickly that it is difficult to keep up with security requirements. For example, at the time
of this book’s writing, there are 160,974 records of vulnerabilities registered on the CVE
platform [3]. However, lessons can be learned even from failures, so by analyzing such
vulnerabilities, security solutions can be improved.
One of the most important aspects considered when complex systems are
designed and implemented is knowledge. In antiquity, the Latins said Scientia
potentia est, meaning “Knowledge is power” [4]. In the 21s century, this is even more
true; information falling into the wrong hands can lead to huge business losses and
catastrophic outcomes. Cryptography and information security provide security
1
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_1
Chapter 1 Introduction
mechanisms that can protect information shared between senders and recipients over
insecure channels, so that unauthorized users cannot access or alter the transmitted
information. Over time, there were encryption systems that were broken by attackers by
exploiting vulnerabilities of the systems.
The word cryptography comes from the Greek words kryptos and graphein, meaning
“hidden” and “writing,” respectively. As its name suggests, the purpose of cryptography
is to hide messages from unauthorized individuals and to keep their integrity. Although
the study of cryptography has been around only about 100 years, it was used in different
forms from ancient times. However, over time there have been various primary methods
of hiding secret messages, starting with hieroglyphs, continuing with Caesar's famous
cipher, followed by the Vigenère cipher, Hebern’s rotor machine, and the famous
Enigma machine. Nevertheless, hiding messages was not the only occupation close
to cryptography or, rather, information security. Another example is authentication or
identity verification; this was often done through seals.
Cryptography is considered an art, especially in its primary phases. The history of
cryptography began in ancient Egypt, alongside the art of writing, during a time when
humans started organizing in different social groups. This organization led to a natural
need of transmitting information only to certain individuals, with the same group, tribe,
etc. Early forms of cryptography were hieroglyphs, which started to be used about 4,000
ago by Egyptians—only they recognized the symbols and their meaning. An inscription
carved circa 1900 BC contains the first known evidence of cryptography (in some kind).
It is located in Egypt nobleman Khnumhotep II’s tomb, in the main chamber [5]. In this
inscription, some symbols have a different form than usual, and the scribe’s intent was
not necessary to hide a message; rather, he wanted the symbols to look nobler than usual
according to the social status of the deceased. Although the inscription does not hide
a message, it contains an altered/transformed form of the original symbols, being the
oldest proof of such an approach. Then, cryptography in the ancient world moved to a
substitution approach, in which every symbol of an alphabet was replaced by another
symbol based on a secret rule. This was happening around 500–600 BC. The next notable
cipher was Caesar’s cipher. Caesar was a Roman emperor who was communicating
with his army generals with encoded messages, using a substitution within the Roman
alphabet. Each letter was shifted a certain number of positions in the alphabet, usually
three. For example, the correspondent of A was D, of B was E, and so on. This is an
important historical cipher that is mentioned often in cryptography literature. The next
important achievement in cryptography was in the Middle Ages by Leon Battista Alberti,
who implemented polyalphabetic substitution. Two rotating copper disks were used that
2
Chapter 1 Introduction
C
ryptography and Cryptanalysis
When working with information security and data protection, the concepts of
cryptology, cryptography, and cryptanalysis should be clear. These are defined here, as
presented in [8, 9]:
3
Chapter 1 Introduction
B
ook Structure
This book contains 15 chapters, in which the main aspects of classical and modern
cryptography are presented. Generally, the chapters will cover the foundation of the
presented concept/mechanism/technique from a mathematical perspective and then a
practical implementation or use cases in Java. The following chapters are detailed here:
• Chapter 2, “JDK 17: New Features”: This chapter will cover the new
features of Java 17 and will show some practical examples.
• Chapter 3, “Roadmap and Vision for Jakarta EE10”: This chapter
will present the basic usage of Jakarta EE and explain how security
mechanisms can be integrated.
4
Chapter 1 Introduction
the purpose of cryptography and its basic rules. For each classic
algorithm, the mathematical description will be presented followed
by the implementation in Java.
5
Chapter 1 Introduction
C
onclusion
This first chapter covered the objectives of the book and highlighted the need
for cryptography and information security. Then it explained what cryptology,
cryptography, and cryptanalysis mean. Finally, the chapter described each upcoming
chapter so you can find information of interest quickly.
References
[1]. Volume of data/information created, captured, copied, and
consumed worldwide from 2010 to 2025, https://www.statista.
com/statistics/871513/worldwide-data-created/
6
Chapter 1 Introduction
7
CHAPTER 2
9
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_2
Chapter 2 JDK 17: New Features
Deprecations:
Note that in the following examples, the Eclipse environment should be configured
for use with Java 17. We’ll now elaborate on the JEPs of interest to the field of
cryptography.
JEP306, “Restore Always-Strict Floating-Point Semantics.” This new feature
brings back the semantics before introducing the strict and default floating-point
modes in Java SE 1.2. The purpose of this modification is to make it easy to work with
libraries for numeric usages, such as java.lang.Math or java.lang.StrictMath. The
variations of the types of calculations (strict, strict floating-point) were due to hardware
constraints in that some processors suffered from overheating issues while performing
strict computations. However, nowadays processors have overcome such constraints;
therefore, strict computations can be used safely without restrictions. You can learn
more about JEP306 at [8].
JEP356, “Enhanced Pseudorandom Number Generators.” This one is of
interest for cryptography use. This new feature includes new interface types and new
implementations for pseudorandom number generators (PRNGs), which are included
in the java.util.random package. The new implementations contain jumpable
PRNGs and a completely new class for splittable PRNGs, called LXM. The purpose of
this feature is to make it easier to use PRNGs and to eliminate two weaknesses in the
SplittableRandom class discovered in 2016.
10
Chapter 2 JDK 17: New Features
In Listing 2-1 are printed available PRNGs with some information about them:
their type (arbitrary jumpable, hardware, jumpable, leapable, splittable, statistical,
stochastic, or streamable) and the number of bits used to maintain the state of the seed.
After that, lines 28 and 29 show how PRNGs are instantiated in the new Java 17, while
line 31 shows the old instantiation of the Random class. Lines 33, 34, and 36 show the
default representation for the new implementations and the shortcut for the default
representation, respectively. Figure 2-1 shows the results.
1 import java.util.Random;
2 import java.util.random.RandomGenerator;
3 import java.util.random.RandomGeneratorFactory;
4 import java.util.stream.Stream;
5
6 public class JEP356Example {
7
8 public static void main(String[] args) {
9
10 Stream<RandomGeneratorFactory<RandomGenerator>> allPRNGs =
RandomGeneratorFactory.all();
11 allPRNGs.map(prng -> prng.name() + " [ Group: " + prng.
group() + "; "
12 + (prng.isArbitrarilyJumpable() ? " arbitrary-
jump" : "")
13 + (prng.isHardware()? " hardware" : "")
14 + (prng.isJumpable() ? " jump" : "")
15 + (prng.isLeapable()? " leap" : "")
16 + (prng.isSplittable() ? " split" : "")
17 + (prng.isStatistical()? " statistical" : "")
18 + (prng.isStochastic()? " stochastic" : "")
19 + (prng.isStreamable() ? " stream" : "")
20 + "; noOfBits: "+ prng.stateBits()
21 + "]"
22 ).sorted().forEach(System.out::println);
23
11
Chapter 2 JDK 17: New Features
24 System.out.println("\n*****\n");
25
26 RandomGenerator prng1 = RandomGeneratorFactory.
of("Random").create(45);
27 System.out.println("prng1 - " + prng1.getClass());
28 RandomGenerator prng2 = new Random(45);
29 System.out.println("prng2 - " + prng2.getClass());
30 RandomGenerator prng3 = RandomGeneratorFactory.
getDefault().create(45);
31 System.out.println("prng3 - " + prng3.getClass());
32 RandomGenerator prng4 = RandomGenerator.getDefault();
33 System.out.println("prng4 - " + prng4.getClass());
34 }
35 }
12
Chapter 2 JDK 17: New Features
In Figure 2-1, the Legacy category is for the old implementation of PRNGs, while LXM
and Xoroshiro are newly introduced. Note that the new implementations are not thread-
safe; namely, the same instance can be shared between more threads (although this is
not a common practice while developing applications). Instead, java.util.Random and
java.security.SecureRandom are thread-safe. You can learn more about JEP 356 at [9].
JEP403, “Strongly Encapsulate JDK Internals.” This is one of the features that
enhances the security of the JDK, as the internal APIs cannot be accessed with
the --illegal-access option at the command line anymore; this is because in JDK 17
all internal elements are now strongly encapsulated. The exceptions are crucial APIs,
such as sun.misc.Unsafe. The purpose of this feature is to encourage developers to
use standard APIs instead of internal APIs. This change increases the security and
the maintainability of the JDK. On the official page of this JEP, the developers give
some examples of pieces of code that will not work anymore in JDK 17 and provide
explanations for each example. You can learn more about JEP 403 at [10].
JEP406, “Pattern Matching for switch (Preview).” By far, using pattern matching
in switch expressions and statements will be easier and more elegant. In addition, this
will save a lot of lines of code. Listing 2-2 is an example of pattern matching for switch
that can be used in cryptography. Consider three classes that implement the RSA, AES,
and ElGamal algorithms (lines 1–11); the user should introduce only the secret key or the
pair of the secret key and public key corresponding to the chosen encryption system’s
type. Note that for the following example, the usage of preview language features should
be enabled in order to work properly.
1 class RSA {
2
3 }
4
5 class AES {
6
7 }
8
9 class ElGamal {
10
11 }
13
Chapter 2 JDK 17: New Features
12
13 public class JEP406Example {
14
15 static void TypeOfKeys(Object o) {
16 if (o instanceof RSA ) {
17 System.out.println("Two keys needed. Type the secret on
the first line. Type the public key on the second line.");
18 } else if (o instanceof AES) {
19 System.out.println("One key needed. Type the secret
key on the first line.");
20 } else if (o instanceof ElGamal) {
21 System.out.println("Two keys needed. Type the secret on
the first line. Type the public key on the second line.");
22 }
23 }
24
25 static void TypeOfKeysPatternSwitch(Object o) {
26 if(o == null)
27 throw new NullPointerException();
28 else
29 {
30 switch (o.getClass().toString()) {
31 case null -> throw new NullPointerException();
32 case "RSA2" -> System.out.println("Two keys
needed. Type the secret on the first line. Type
the public key on the second line.");
33 case "AES2" -> System.out.println("One key
needed. Type the secret key on the first line.");
34 case "ElGamal2" -> System.out.println("Two keys
needed. Type the secret on the first line. Type
the public key on the second line.");
35 default -> System.out.println("Pick an
encryption system");
36 }
37 }
38 }
14
Chapter 2 JDK 17: New Features
39
40 public static void main(String[] args) {
41 TypeOfKeys(new RSA());
42 TypeOfKeysPatternSwitch(new RSA());
43
44 System.out.println("\n***\n");
45
46 TypeOfKeys(new AES());
47 TypeOfKeysPatternSwitch(new AES());
48 }
49 }
In Listing 2-2, two approaches were used to print the message for the user: the
regular one, in the function TypeOfKeys (lines 16–27), and the version with pattern
matching for the switch statement (lines 29–45). Note that the result should be the same
for the same type of object that is passed to the two functions. You can check the result in
Figure 2-2, and you can learn more about JEP 406 at [11].
15
Chapter 2 JDK 17: New Features
However, superclasses should be widely accessible but not widely extensible. Sealed
classes were introduced to give more control over how extensibility and implementation
are used. The previous example can be modified by using sealed classes as shown in
Listing 2-5.
16
Chapter 2 JDK 17: New Features
9 else
10 throw new RuntimeException("Unknown instance
of Cryptosystem.");
11
12 }
13 public static void main(String[] args) {
14 AES_Cryptosystem aes = new AES_Cryptosystem();
15 RSA_Cryptosystem rsa = new RSA_Cryptosystem();
16
17 Test(aes);
18 Test(rsa);
19 }
20 }
In Listing 2-5, three classes are used: Cryptosystem, AES_Cryptosystemn, and RSA_
Cryptosystem. Note that to use them as sealed classes and classes that extend the sealed
class, each class must be defined in its own file. To prevent further extensions, the classes
that extend the sealed class should be declared as final. Here is the definition for the
three classes used in the example:
17
Chapter 2 JDK 17: New Features
For example, Matlab code can be used for mathematical functions or algorithms that
are already implemented, such as statistical functions. Using the foreign code is safe and
efficient. You can learn more about JEP412 at [13].
JEP414, “Vector API (Second Incubator).” Using this feature achieves better
performance and implementation for vector instructions compared to equivalent scalar
computations. The improved API provides features such as translating byte vectors to
Boolean arrays, or vice versa. You can learn more about JEP412 at [14].
JEP415, “Context-Specific Deserialization Filters.” This is another example of
a feature that is great for cryptographic purposes. The motivation behind this feature
lies in the fact that data that is received from different sources is untrusted because in
the world of the Internet, often the source is unknown, untrusted, or unauthenticated.
Therefore, when untrusted data is deserialized, it can be dangerous. For example, an
attacker can exploit the vulnerabilities behind serialized/deserialized data injecting
malicious behavior. With this feature, a filter factory for Java Virtual Machine (JVM)
was introduced that can be configured. When it is instantiated as an object of the
ObjectInputStream type, the JVM filter factory is invoked, and the result is used to
initialize each filter per stream. You can learn more about JEP415 at [15].
C
onclusion
This chapter presented the main features added in Java 17. By far one of the most
exciting added features is the new pseudorandom generator implementations and
pattern matching for switch instructions. The chapter presented some use cases for
cryptography.
References
[1]. Java SE at a Glance, https://www.oracle.com/ro/java/
technologies/java-se-glance.html
18
Chapter 2 JDK 17: New Features
[6]. Java® Platform, Standard Edition & Java Development Kit Version
17 API Specification, https://docs.oracle.com/en/java/
javase/17/docs/api/index.html
[7]. JDK 17.0.1 General-Availability Release, https://jdk.
java.net/17/
[13]. JEP 412: Foreign Function & Memory API (Incubator), https://
openjdk.java.net/jeps/412
[14]. JEP 414: Vector API (Second Incubator), https://openjdk.java.
net/jeps/414
19
CHAPTER 3
Starting with Java EE 8, Jakarta Security is a new API with three authentication
procedures: Basic, Form, and an extension of Form that perfectly suits the process of
implementation within Java Server Faces (JSF).
With Jakarta EE 10, the goal is to add new authentication mechanisms. The first
mechanism on the list is represented by Client-Cert and Digest. In this way, Jakarta
Security will provide a total replacement of the authentication mechanisms that are
supported by Java Servlet. Another goal is to offer support for OpenID, OAuth, and JSON
Web Token (JWT). JWT is an interesting topic that is currently under discussion due to
the process of adding it to the MicroProfile project.
Jakarta Security supports different annotations, such as @RolesAllowed and @RunAs,
with support for further extensions. At the moment, @RolesAllowed is supported only
by EJB in Jakarta EE. The annotation will throw an exception if access is denied by a
bean method.
Related to the authentication mechanisms, @RolesAllows will trigger an
authentication mechanism when access is denied by a Jakarta REST resource method.
21
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_3
Chapter 3 Roadmap and Vision for Jakarta EE 10
The Jakarta EE 10 platform will include a serious set of components; Table 3-1 shows
their status.
22
Chapter 3 Roadmap and Vision for Jakarta EE 10
• Jakarta Debugging Support for Other Languages 2.0 (feature for Web Profile)
23
Chapter 3 Roadmap and Vision for Jakarta EE 10
• Jakarta RESTful Web Services 3.1 (updated feature for Web Profile)
1 import java.io.UnsupportedEncodingException;
2 import java.security.KeyPair;
3 import java.security.KeyPairGenerator;
4 import java.security.NoSuchAlgorithmException;
24
Chapter 3 Roadmap and Vision for Jakarta EE 10
5 import java.security.NoSuchProviderException;
6 import java.security.PrivateKey;
7 import java.security.PublicKey;
8 import java.security.SecureRandom;
9
10 @ApplicationScoped
11 public class ApressAuthorizationModule {
12
13 @Inject
14 SecurityConstraints apressSecurityConstraints
15
16 @Inject
17 ApressService apressService;
18
19 @PostAuthenticate
20 @PreAuthorize
21 @ByRole
22 public Boolean appressLogic(
23 Caller apressCaller, Permission apressReqPermission) {
24
25
return apressSecurityConstraints.getRequiredRoles(apressReq
Permission)
26 .stream()
27
.anyMatch(apressAccessRole -> apressService.
isInRole(apressCaller, apressAccessRole));
28 }
29
30 }
Jakarta CDI represents the main component model within the platform, and many
components are being aligned with it already. The important components include the
following:
25
Chapter 3 Roadmap and Vision for Jakarta EE 10
• Jakarta Security will have two annotations that will need to deal
with it: @RolesAllowed and @RunAs.
• Jakarta Batch
• Jakarta Concurrency
26
Chapter 3 Roadmap and Vision for Jakarta EE 10
Next, looking at the future of Jakarta EE 10, there are new challenges, but they will
not be covered. Most of the components provide experimentation together with analysis
and development. Those features are summarized as follows:
• Jakarta MVC
• Java Secure Socket Extension (JSSE): One of the most important data
protocols is represented by the Secure Sockets Layer (SSL), which
provides data integrity by providing encryption. JSSE has a standard
interface and proper implementation for the SSL protocol.
Good references specialized for Jakarta EE are [1-3] and generally for Java are [4-7].
C
onclusion
In this chapter, we provided a short overview of the main components and challenges
covered by the new Jakarta EE 10 and how these components will impact the developing
process of the software applications and the implementation of security mechanisms.
27
Chapter 3 Roadmap and Vision for Jakarta EE 10
References
[1]. Juneau, Josh. Jakarta EE Recipes: A Problem-Solution Approach,
Apress, 2020.
[2]. Manelli, Luciano, and Giulio Zambon. Beginning Jakarta EE Web
Development: Using JSP, JSF, MySQL, and Apache Tomcat for
Building Java Web Applications. Apress, 2020.
[7]. Sierra, Kathy, and Bert Bates. Head First Java. 2nd ed,
O’Reilly, 2005.
28
CHAPTER 4
Java Cryptography
Architecture
The Java Cryptography Architecture (JCA) framework offers capabilities for working with
cryptography algorithms and offers methods for a variety of cryptography primitives.
The cryptography algorithms and methods are implemented and offered through the
java.security package.
The Java platform is designed in such a way that the most important aspects and
components that characterize security are included in an easy and modern approach for
developers. The following are the most important components:
• Secure communication
• Language safety
• Authentication
• Access control
JCA represents only a small part of the entire Java platform, which has a provider
and a set of APIs for different cryptography primitives, such as digital signatures, hash
functions, validation of certificates, encryption algorithms/primitives, cryptography key
generation functions, key management, and algorithms for generating random numbers.
The provider was designed as architecture with respect for the following principles:
29
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_4
Chapter 4 Java Cryptography Architecture
• javax.crypto
• javax.crypto.spec
• javax.crypto.interfaces
• SunRsaSign
• SunJCE
30
Chapter 4 Java Cryptography Architecture
• Cipher class
• KeyPairGenerator class
• KeyFactory class
• MessageDigest class
• Signature class
Another question that will come up is, how is independence implemented? The
Cryptographic Service Provider (CSP) represents a package or a set of packages that
provides implementations for a variety of cryptographic services, such as digital
signatures algorithms, hash algorithms, and key management algorithms. Simply stated,
interoperability in information security is the ability of different implementations to
achieve their goals by working with each other, exchanging cryptography keys between
them, or being able to check each other’s cryptography keys.
The final question is, what is the importance and meaning of algorithm extensibility?
The answer relies in the simplicity of how the engine classes are added in a very easy and
modern way.
31
Chapter 4 Java Cryptography Architecture
The base class java.security.Provider comprises all the security providers. For
each CSP we will have an instance of this class. The class will offer the following:
• A list with all the security algorithms and security services that are
implemented
To use JCA, you simply specify the request for a certain object and its type. With
every JDK that you install, one or more providers will be installed and set by default.
Let’s see an example of JCA in action. The first thing you need to do is to make a
simple request for a certain type of object, such as MessageDigest, and to invoke or call a
certain algorithm/service, such as the SHA-512 algorithm.
message_hash = MessageDigest.getInstance("SHA-512");
message_hash = MessageDigest.getInstance("SHA-384",
"ImplementedProvider1");
Note that the previous lines of code are just an example snippet. In real use,
ImplementedProvider1 should be replaced with a valid provider. For example, a provider
for SHA-384 is SUN. Java enables users to determine the providers available by using the
following code:
Figure 4-1 and Figure 4-2 show the requesting process for the SHA-512 algorithm
to hash a message. The ordering process shows three different ways of how a hash
algorithm is invoked and how a provider can be used as a source of the implementation.
Based on the architectures shown in Figure 4-1 and Figure 4-2, the developers can add
any other components (e.g., services, interfaces, third-party functions, etc.) and develop
new architectures based on them.
Returning to the independence of the algorithms, their definition will achieve the
proper goal of providing the implementation of providers that are compliant with the
defined interfaces. This is known as an application programming interface (API), and
it will guarantee that all applications will use it to access a specific type of service.
32
Chapter 4 Java Cryptography Architecture
33
Chapter 4 Java Cryptography Architecture
34
Chapter 4 Java Cryptography Architecture
• Objects: The objects contain the encrypted data and have the
capability to move them to certain and upper abstraction layers. Such
examples include certificates or cryptography key containers.
You can find a comprehensive list with examples and case studies at [1]. Table 4-1
lists the most important ones.
KeyPairGenerator This generates a pair of public and private keys for a certain algorithm.
KeyGenerator For an algorithm, the class will generate new secret keys.
KeyAgreement The instance of the class is used by one or two parties to establish a
cryptographic key to be used within a specific cryptographic operation.
Cipher The class will use the keys (generated for encryption and decryption
data). The class provides a set of various algorithms, such as
asymmetric encryption, symmetric encryption, and password-based
encryption.
MessageDigest This provides functionalities for computing the hash value for a certain
message.
SecureRandom This provides functionalities for generating random numbers.
35
Chapter 4 Java Cryptography Architecture
Provider This generates a pair of public and private keys for a certain algorithm.
Security For an algorithm, this class will generate new secret keys.
MessageDigest An instance of this class is used by one or two parties for establishing a
cryptographic key to be used within a specific cryptographic operation.
Cipher This class will use the keys (generated for encryption and decryption
data). The class provides a set of various algorithms, such as
asymmetric encryption, symmetric encryption, and password-based
encryption.
KeyAgreement This provides functionalities for computing the hash value for a certain
message.
CertificateFactory This provides functionalities for generating random numbers.
Key This provides functionalities for working with keys.
D
ata Encryption
To work with data encryption, the Cipher class offers the right tools (e.g., functions,
methods, etc.). The Cipher class is part of the javax.crypto package.
The workflow is straightforward to follow, as shown here and in Listing 4-1:
36
Chapter 4 Java Cryptography Architecture
5. Create an instance for the cipher object. To achieve this goal, the
method getInstance() is used.
6. Using the init() method, you will initialize the cipher object.
7. Provide the data to the cipher object for which you will provide
the encryption.
1 import java.security.KeyPair;
2 import java.security.KeyPairGenerator;
3 import java.security.Signature;
4
5 import javax.crypto.Cipher;
6
7 public class DataEncryption {
8 public static void main(String args[]) throws Exception{
9
10 //create an instance for signature
11 Signature mySignature = Signature.getInstance("SHA256withRSA");
12 System.out.println("\n The signature instance -> " +
mySignature);
13
14 //crere an instance as generator for a pair key
15 KeyPairGenerator key_pair_gen = KeyPairGenerator.
getInstance("RSA");
16 System.out.println("\n The key pair generator -> " +
key_pair_gen);
17
18 //specify the size
19 key_pair_gen.initialize(2048);
37
Chapter 4 Java Cryptography Architecture
38
Chapter 4 Java Cryptography Architecture
H
ash Functions
To use hash functions (Listing 4-2 and Figure 4-4), the process is simple and generally is
composed of three steps, as follows:
1 import java.security.MessageDigest;
2 import java.util.Scanner;
3
4 public class Hashing {
5 public static void main(String args[]) throws Exception
6 {
7 //add some text that we will use it for encryption
8 String message = "Welcome to Appress and enjoy learning
cryptography";
9 System.out.println("\n The text for which we will provide the
digest (hash) is -> " + message);
10
39
Chapter 4 Java Cryptography Architecture
40
Chapter 4 Java Cryptography Architecture
Signatures
Creating and working with signatures in Java represents an interesting approach
compared with other programming languages. Digital signatures give you the ability to
verify different aspects to make certain a message is genuine, such as the following:
Generating Signatures
The implementation process of generating signatures involves eight steps, as follows:
41
Chapter 4 Java Cryptography Architecture
Listing 4-3 shows how the steps listed are implemented, with an explanation of each
step. Figure 4-5 shows the result.
1 import java.security.*;
2 import java.util.Scanner;
3
4 public class GeneratingSignature
5 {
6 public static void main(String args[]) throws Exception {
7 //the message that will be signed
8 String data_message = "Welcome to Apress and enjoy learning
cryptography";
9 System.out.println("The message that will be sign is -> " +
data_message);
10
11 //Step 1 - Declare an instance of KeyPairGenerator class
12 KeyPairGenerator generatorKeyPair = KeyPairGenerator.
getInstance("DSA");
13
14 //Step 2 - Providing the proper initialization for the instance
15 generatorKeyPair.initialize(2048);
16
17 //Step 3 - Obtaining the key pair using the
generateKeyPair() method
18 KeyPair cryptographyKeyPair = generatorKeyPair.
generateKeyPair();
19
20 //Step 4. Extract the private key from the pair using the
getPrivate() method
21 PrivateKey private_key = cryptographyKeyPair.getPrivate();
22
23 //Step 5. Declare an instance as a signature object
24 Signature signatureForMessage = Signature.getInstance
("SHA256withDSA");
42
Chapter 4 Java Cryptography Architecture
25
26 //Step 6. Initialize the signature object
27 signatureForMessage.initSign(private_key);
28 byte[] theBytesRepresentation = "msg".getBytes();
29
30 //Step 7. Provide the data for the signature object
31 signatureForMessage.update(theBytesRepresentation);
32
33 //Step 8. Compute the signature
34 byte[] signature = signatureForMessage.sign();
35
36 //Showing the result as output
37 System.out.println("Obtained digital signature for the provided
text -> "+new String(signature, "UTF8"));
38 }
39 }
43
Chapter 4 Java Cryptography Architecture
Listing 4-4 shows how the steps are implemented, and it points out the main
differences between the generating process and the verifying process. Figure 4-6 shows
the results.
44
Chapter 4 Java Cryptography Architecture
45
Chapter 4 Java Cryptography Architecture
50 else
51 {
52 System.out.println("The signature has been failed");
53 }
54 }
55 }
C
onclusion
This chapter covered some of the main classes specific to the Java Cryptography
Architecture. The chapter explained the basic concepts of JCA, and how understanding
how the JCA architecture was designed plays an important role in developing
professional software applications.
You should now understand the basic process for implementing regular
cryptography operations using JCA, including the following:
• Data encryption
• Hash functions
References
[1]. Java Cryptography Architecture (JCA) Reference Guide, https://
docs.oracle.com/javase/8/docs/technotes/guides/security/
crypto/CryptoSpec.html#Design
46
CHAPTER 5
Classical Cryptography
Humans have been hiding messages from the very first moment they started sending
messages. In the early ages, messages were sent between leaders, emperors, conquerors,
kings, and so on, in the form of verbal messages through a human messenger. Although
unspoken rules protected the human messengers, sometimes this rule was not followed,
and the messenger was caught by enemies. At that point, all the enemy needed to do was
send an altered message to the rightful receiver. This is a real-life example of a man-in-
the-middle attack.
In the years that followed, humans started hiding the actual content of the message
in specific ways so that if the enemy took possession of the message, its meaning could
not be understood. In this way, an early form of cryptography was born.
Methods of encrypting messages are as limitless as the human imagination.
However, in practice, only some of them work well due to some natural constraints. For
example, the sender and the receiver should both know how to encrypt and decrypt
the messages, and the encryption technique should be strong enough such that if the
encrypted message gets into the wrong hands, it cannot be decrypted. These two simple
facts haunt all encryption schemes even nowadays. In this chapter, some historical
ciphers will be presented, as follows: Caesar cipher, Vigenère cipher, and Hill cipher.
All these classical ciphers fall into the category of symmetric cryptography, in which
just one type of key is used for both encryption and decryption, namely, the secret key
(we’ll discuss symmetric cryptography more in Chapter 9). Although all these classical
ciphers are not used anymore, they are important as an introduction to cryptography so
you can understand the basic concepts and the purpose behind cryptography. Also, they
are easy to understand from a technical perspective, which makes them again a great
47
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_5
Chapter 5 Classical Cryptography
introduction to cryptography, especially for beginners in this field. You can find more
background information about the ciphers in this chapter in many cryptography courses
and books, such as [1], [2], and [3].
C
aesar Cipher
The Caesar cipher is estimated to date back to the first century BC in the Roman
Empire. Its name comes from the Roman Emperor Julius Caesar, who used this cipher
to encrypt military messages and strategies [1], and it is estimated to be broken in about
the fifth century AD. The Caesar cipher is a substitution cipher, in which each letter of
the alphabet is moved a certain number of characters to the right. For example, if the
established number is 5, then A will become F, B will become G, C will become H, etc.
In this cipher, the key is represented by the number that the letters are shifted. Note that
the key should be secret, known only by the sender (to encrypt the messages) and by the
receiver (to decrypt the messages). The Caesar cipher is important because it is the basis
for other classical ciphers, such as Vigenère. The Caesar cipher with key k = 13 is also
known as Rot13.
Let’s consider an example. The key for the cipher is set to k = 6; therefore, all letters
are shifted six characters (see Table 5-1).
Note that there are 26 letters in the alphabet, and in Table 5-1 the numbering starts
with 0 and ends with 25 because it is related to ℤ26 = {0, 1, …, 25}. Sometimes, in other
documentation, the numbering starts with 1 and ends with 26, because it seems more
natural.
Considering the plain message as “CAESAR CIPHER EXAMPLE” and the key as k = 6,
the encrypted message will be “IGKYGX IOVNKX KDGSVRK.” The encrypted message
was obtained by replacing C with the corresponding I, A with the corresponding G, E
with the corresponding K, and so on.
48
Chapter 5 Classical Cryptography
To decrypt the message, the letters from the second row of the table are shifted
to the left for k positions. Therefore, the decryption of “IGKYGX IOVNKX KDGSVRK”
(with the key k = 6) is “CAESAR CIPHER EXAMPLE,” obtained by applying a similar
logic as for encryption: I is replaced with C, G is replaced with A, and so on. Note that
sometimes the space character is removed from the message; therefore, in the example,
the plain text would be “CAESARCIPHEREXAMPLE,” while the encrypted text would be
“IGKYGXIOVNKXKDGSVRK.”
From a mathematical point of view, the operations are addition for encryption and
subtraction for decryption via a modulo operation. The first step is to “convert” the
characters to numbers, as follows: ′A′ → 1,′B′ → 2, …, ′Z′ → 26. The encryption function
enck will take as input one parameter, i.e., the number corresponding to the letter that
needs to be encrypted at the current step, and will output the encrypted letter:
where c is the plain character and k is the key. The decryption function needs to shift
back the letters and, therefore, has the following representation:
where c′ is the encrypted character that needs to be decrypted and k is the key.
I mplementation
Listing 5-1 shows the implementation of the Caesar cipher; Figure 5-1 shows the result.
1 import java.util.Scanner;
2
3 public class CaesarCipher {
4
5 public static String Encrypt(String text, int positions) {
6 String toEncrypt = "", result = "";
7 //format the text to be encrypted
8 for (int i = 0; i < text.length(); i++) {
9 //remove space characters
49
Chapter 5 Classical Cryptography
50
Chapter 5 Classical Cryptography
51
Chapter 5 Classical Cryptography
The code is pretty simple and just follows the encryption and decryption formula.
Before encrypting the message, it is formatted by eliminating the space characters and
making all the letters uppercase.
52
Chapter 5 Classical Cryptography
C
ryptanalysis
The Caesar cipher is easy to use, but it is also easily broken in milliseconds using
automated tools [5]. The total number of keys is 25; therefore, there are only 25 shifting
possibilities. An attacker can easily generate all 25 forms and then recover the message
for all forms. This type of attack, in which all possible values are exploited, is called the
brute-force attack.
The brute-force attack for the Caesar cipher consists of determining the fitness value
of a part of the decrypted text, showing how that part is fitting in the text. This implies
some statistical information about the decrypted text compared to statistical information
about English text. The fitness value shows how “close” to recover the key an attacker is,
with higher values closer to recovering the key. An example of a statistical method that
can be applied here is the quadgram fitness measure [4] that works as follows:
2. Compute the probability for the event that the ciphertext has the
same distribution.
V
igenère Cipher
This historical cipher was mistakenly attributed to Blaise de Vigenère in the 18th
century, but it was invented by the Italian cryptologist Giovan Battista Bellaso (https://
en.wikipedia.org/wiki/Giovan_Battista_Bellaso), and the first use is estimated
to be in the 15th century. Until 1863, when it was broken through a method proposed
by Friedrich Kasiski, the Vigenère cipher was considered unbreakable, gaining the
nickname “le chiffrage indéchiffrable” (in French), meaning “the indecipherable cipher.”
The Vigenère cipher uses a key in a form of a word and an encryption table (see
Table 5-2). To encrypt a message, it should proceed as follows:
3. The found letter is the encrypted letter of the current plain letter.
53
Chapter 5 Classical Cryptography
Table 5-2. The Encryption Table for the Vigenère Cipher [6]
Consider the plaintext “LOREM IPSUM DOLOR SIT AMET” and the key “APRESS.”
First, extend the key, as in Table 5-3. Note that the space character was removed from
the plain message.
Second, find the intersection between the current key letter and the current message
letter (see Figure 5-2).
54
Chapter 5 Classical Cryptography
Figure 5-2. Encryption of the first word of the message using Vigenère
enc mi mi ki mod 26
55
Chapter 5 Classical Cryptography
The decryption of the current letter ci of the encrypted message is made using the
following formula:
I mplementation
This section presents the implementation of the Vigenère cipher. It follows the steps
described in the previous section, but first, the message is processed by eliminating
the space characters and making the letters uppercase. Listing 5-2 shows the
implementation, and Figure 5-3 shows the result.
1 import java.util.Scanner;
2
3 public class Vigenere {
4 static String ExtendKey(String message, String initialKey) {
5 int toLength = message.length();
6
7 for (int i = 0;; i++) {
8 if (toLength == i)
9 i = 0;
10 if (initialKey.length() == message.length())
11 break;
12 initialKey += initialKey.charAt(i);
13 }
14 return initialKey;
15 }
16
56
Chapter 5 Classical Cryptography
57
Chapter 5 Classical Cryptography
49 result += Character.toUpperCase(text.
charAt(i));
50 else
51 result += text.charAt(i);
52 }
53 }
54
55 return result;
56 }
57
58 public static void main(String[] args) {
59 System.out.println("VIGENERE CIPHER\n");
60
61 Scanner sc = new Scanner(System.in);
62
63 System.out.print("Type the message: ");
64 String plainMessage = sc.nextLine();
65 System.out.print("Type the key: ");
66 String key = sc.nextLine();
67 sc.close();
68
69 System.out.println("\nEncrypting...");
70
71 String processedText = ProcessText(plainMessage);
72 String keyword = ProcessText(key);
73
74 String extendedKey = ExtendKey(processedText, keyword);
75 String encryptedText = Encrypt(processedText,
extendedKey);
76
77 System.out.println("The encrypted message is: " +
encryptedText);
78 System.out.println("\nDecrypting...");
79 String recoveredMessage = Decrypt(encryptedText,
extendedKey);
58
Chapter 5 Classical Cryptography
C
ryptanalysis
The Vigenère cipher can be broken using frequency analysis. However, it is not
enough to do a simple analysis frequency because the same letter can be obtained
from intersections of the plain message letter and the extended key letter. It would be
easier if the length of the original key was discovered; let’s denote it with n, because the
encrypted text will be partitioned in blocks of length n (except for the last block that may
have a smaller length). From here, the problem is reduced to breaking n Caesar ciphers.
To find the key length in general, three techniques can be applied: brute-force, Kasiski
examination [7], or Friedman test [8].
59
Chapter 5 Classical Cryptography
H
ill Cipher
The author of the Hill cipher is Lester S. Hill, and it was proposed in 1929; it is an
example of a polygraphic substitution cipher. The mathematical background for the Hill
cipher lies in linear algebra, more exactly in matrices and their operations, in which the
plaintext is hidden.
The key of the cipher is a square matrix with an arbitrary dimension, with elements
in ℤ26. For example, consider the following matrix to be the secret key,
2 8 5
K 9 4 1 ,
6 17 7
having three rows and three columns (denote the dimension with n = 3), and the plain
message to be “WELCOME TO CRYPTOGRAPHY.” To encrypt the message, it should
proceed as follows:
3. Multiply the key (square matrix) with the column matrix that
represents the indices of the letters and apply modulo 26.
4. Convert the numbers into letters (for convenience, see the first
two rows of Table 5-1).
Following the example, for the first three letters of the message, it will be obtained
′
W = 22, ′E ′ = 4, and ′L′ = 11, and then
′
60
Chapter 5 Classical Cryptography
letters than n, some extra letters will be added to the end of the plain message to achieve
n letters. Note that not any matrix can be used as a key. To be invertible modulo 26, the
determinant of the matrix should be coprime with 26.
To decrypt the message, the first step is to find the inverse of K (let’s denote it with
K ) with elements also in ℤ26; the next steps is to multiply K′ with the column matrix
′
representing the encrypted blocks. The column matrix that will be obtained represents
the indices of the letters of the plain message.
21 1 22
K mod 26 7 12 23
17 22 22
Implementation
Listing 5-3 shows the implementation of the Hill cipher, and Figure 5-4 shows the result.
1 package ciphers;
2
3 import java.util.*;
4
5 class Utils {
6 String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
7
8 int getCharIndex(char c) {
9 if (alphabet.contains(Character.toString(c)))
10 return alphabet.indexOf(c);
11 else
12 return -1;
13 }
14
15 char getCharAtIndex(int index) {
61
Chapter 5 Classical Cryptography
16 return alphabet.charAt(index);
17 }
18 }
19
20 public class HillCipher {
21
22 Utils util = new Utils();
23 int keySize = 3;
24 int keyMatrix[][] = new int[keySize][keySize];
25 Scanner scanner = new Scanner(System.in);
26
27 HillCipher(int keySize) {
28 this.keySize = keySize;
29 }
30
31 void keyInitialize(String message) throws Exception {
32 System.out.println(message);
33 for (int i = 0; i < keySize; i++) {
34 for (int j = 0; j < keySize; j++) {
35 keyMatrix[i][j] = scanner.nextInt();
36 }
37 }
38 }
39
40 String blockEncryption(String plainBlock) throws Exception {
41 plainBlock = plainBlock.toUpperCase();
42 int indexMatrix[][] = new int[keySize][1];
43 int columnMatrix[][] = new int[keySize][1];
44 int sumElem = 0;
45 String encryptedBlock = "";
46
47 for (int i = 0; i < keySize; i++) {
48 indexMatrix[i][0] = util.getCharIndex(plainBlock.
charAt(i));
49 }
50
62
Chapter 5 Classical Cryptography
63
Chapter 5 Classical Cryptography
64
Chapter 5 Classical Cryptography
65
Chapter 5 Classical Cryptography
143 String plainMessage;
144 System.out.println("Enter the plain message:");
145 plainMessage = scanner.nextLine();
146
147 int keySize;
148 System.out.println("Enter the size of the matrix key:");
149 keySize = scanner.nextInt();
150
151 HillCipher cipher = new HillCipher(keySize);
152
153 plainMessage = plainMessage.replaceAll(" ", "");
154
155 String encryptedMessage;
156 encryptedMessage = cipher.messageEncryption(plainMessage);
157
158 System.out.println("Obtained encryptd message: \n" +
encryptedMessage);
159
160
161 String decryptedMessage = cipher.messageDecryption
(encryptedMessage);
162 System.out.println("Obtained decrypted message:\n" +
decryptedMessage);
163
164 }
165
166 }
66
Chapter 5 Classical Cryptography
The previous code follows the steps of the Hill cipher implementation. First, the
plain message/encrypted message is split into blocks of the key’s length. Then, each
block is encrypted and added to decrypted message/plain message.
Other good references for Java implementations of the Hill cipher are [10] and [11].
C
ryptanalysis
A known-plaintext attack can easily break the Hill cipher; therefore, if the attacker knows
the plaintext and the corresponding encrypted message, the key can be recovered
immediately, since all computations are linear. For a 2 × 2 key, the attack consists of
computing the frequency for each digraph that may be obtained in the encrypted text. To
launch this attack, knowing the standard English digraph representations is mandatory.
For example, the group of letters th and he are common. A good resource for Hill cipher
cryptanalysis is [9].
67
Chapter 5 Classical Cryptography
C
onclusion
This chapter showed that primordial forms of cryptography existed in ancient times
and presented three of the most important historical ciphers. These are considered
symmetric ciphers because the same key is used for both encryption and decryption and
it should be secret, known only by the sender and the receiver. Caesar, Vigenère, and
Hill are simple ciphers from the technical perspective and are a good starting point for
understanding cryptography. However, these ciphers are not used in practice because
are easily cracked.
References
[1]. Menezes, A. J., Van Oorschot, P. C., & Vanstone, S. A. (2018).
Handbook of applied cryptography. CRC press.
68
Chapter 5 Classical Cryptography
69
CHAPTER 6
Formal Techniques
for Cryptography
This chapter discusses mathematical elements used in cryptography and throughout the
remainder of this book. We’ll start with some definitions of specific terminology; then,
we’ll cover some minimal notions of algebra; and finally, we’ll delve into elliptic curves.
This chapter contains a compilation of different technical (mathematical) tools used in
cryptography gathered from different resources [1]–[9].
D
efinitions
Here are some definitions you need to know:
71
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_6
Chapter 6 Formal Techniques for Cryptography
Dec K Enc K m m ,
• Authorities and third parties: Authorities are usually used to issue digital
certificates, while trusted third parties are intermediary entities for
reciprocal actions between two entities in which they both trust each other.
72
Chapter 6 Formal Techniques for Cryptography
P
robabilities and Statistics
In cryptography, statistics and probabilities have an important role, especially in the
security analysis process for cryptosystems, and in a branch of cryptography called
steganalysis. This section covers basic statistics and probabilities notions. For more
advanced concepts, you can consult [9]–[11].
Let’s start by defining the notion of experiment. An experiment is a procedure
through which a value is obtained from a predefined set of values S = {s1, …, sn}, called
a sample space. A sample is an individual value within the given set S. A specific value
from S is called an event. A discrete sample space is a set for which the number of
possible outcomes is limited.
A probability distribution over the sample space S is a set K = {k1, …, km}, with K ⊂ S,
for which k1 + k2 + … + km = 1. The value ki is the probability that the event si will occur.
The probability of an event E is denoted with P(E). When the event E contains
values from S, E = {e1, …, ek}, the probability of the event E is computed as
P(E) = P(e1) + … + P(ek). The complementary event of E is denoted with E and means all
values that do not belong to E.
The following relations occur between S, E, and E , where E ⊂ S:
1. 0 ≤ P(E) ≤ 1.
Two events, E1, E2, are called mutually exclusive when P(E1 ⋂ E2) = 0.
73
Chapter 6 Formal Techniques for Cryptography
Conditional Probability
Conditional probability occurs in situations in which one event depends on one or more
other events. Let E1 and E2 be two events with P(E2) > 0. The conditional probability for E1
to occur conditioned by E2 is denoted with P(E1| E2) and has the following formula:
P E1 E2
P E1 |E2
P E2
Put more simply, this can be seen as how likely E1 will occur if E2 has already
occurred.
Regarding conditional probability, the following relationships take place:
P E1 ·P E2 |E1
P E1 |E2 , P E2 0
P E2
An important remark here is that P(E1| E2) is different from P(E2| E1). In the first
relation, E1 is conditioned by E2, while in the second relation E2 is conditioned by E1.
Random Variables
Let S be a sample space with distribution probability P, and let X be a function that maps
S to ℝ. For each element si ∈ S, a value xi = X(si) will exist. In this setting, X is called a
random variable. A random variable gives two important notions in statistics: mean (or
expected value) and variance. These values can be computed using these formulas:
• 2
Variance: Var X E X xi pi .
i
2
74
Chapter 6 Formal Techniques for Cryptography
Entropy
Let X be a random variable with corresponding values x1, …, xm, and pi = P(X = xi) for
which the following equality occurs:
n
p
i 1
i 1
Let A be an event. In these settings, the entropy of the event A, which gives the
uncertainty of A to occur, is computed using this formula:
m m 1
H A p j lg p j p j lg
pj
j 1 j 1
1
pi lg pi pi lg 0
pi
1. Joint entropy
H A ,B P A a ,B b lg P A a ,B b
a ,b
2. Conditional entropy
3. Equivocation of A related to B
H A|B P B m H A|B m
m
In the previous relations, a, b go through all of the values within the random variables,
A, B respectively, and m goes through all of the values within the random variable A.
75
Chapter 6 Formal Techniques for Cryptography
A Little Algebra
Prime factorization. This is the process of decomposing a composite number
into factors as prime numbers. The prime factorization is unique for each number,
according to the fundamental theorem of arithmetic. Prime factorization is important in
cryptography, because although it is easy (easy meaning a polynomial-time algorithm
exists that does this) to check whether a number is prime, there is no general method
through which the prime factorization can be achieved. For example, the prime
factorization of 4320 is 4320 = 25 ∙ 33 ∙ 51. Note here that 2, 3, and 5 are prime numbers.
Prime factorization is one of the most important hardness assumptions in cryptography.
One of the widely used cryptosystems, RSA, lies its hardness assumption on prime
factorization.
BigInteger. Big integers are not quite mathematical tools. They are used in computer
science (cryptography) to show that an integer value should have a very large value that
exceeds the representation of an int. For example, in Java, there is a special class called
BigInteger. Listing 6-1 is an example of using the BigInteger class in Java. Figure 6-1
shows the result.
1 import java.math.BigInteger;
2
3 public class BigIntegerExamples {
4
5 public static void main(String[] args) {
6 BigInteger bi1, bi2;
7
8 //initialization with a string value that will be
converted to BigInteger
9 bi1 = new BigInteger("5697726366552");
10 System.out.println(bi1);
11
12 //initialization with an int value
13 bi2 = BigInteger.valueOf(87362);
14 System.out.println(bi2);
15
76
Chapter 6 Formal Techniques for Cryptography
77
Chapter 6 Formal Techniques for Cryptography
The RSA problem. From the RSA encryption system, another hardness assumption
resulted. The RSA problem is as follows: let (N, e) be the public key of the RSA
cryptosystem and C be encrypted text (which is publicly available). It is required to
compute efficiently P, where C ≡ Pe(mod N). For more about the RSA cryptosystem, see
Chapter 10.
Blum integer. A Blum integer is a number of form n = p · q, where p and q are prime
numbers and they are congruent to 3 mod 4. Listing 6-2 provides a way in which an
integer value can be tested as a Blum integer or not. Figure 6-2 shows the result.
1 import java.util.Scanner;
2
3 public class BlumInteger {
4 public static boolean checkBlumInteger(int value)
5 {
6 //define an array with elements from 0 to value-1
7 //suppose each number in this interval is prime
8 int primesArray[] = new int[value + 1];
9 for (int i = 0; i < value; i++)
10 primesArray[i] = 1;
11
78
Chapter 6 Formal Techniques for Cryptography
12
//update the array with the primality of number within in the
interval
13 for (int i = 2; i * i <= value; i++) {
14 if (primesArray[i] == 1) {
15 //if a value is prime, then certainly its multiples
are no primes
16 //update the primality accordingly
17 for (int j = i * 2; j <= value; j += i)
18 primesArray[j] = 0;
19 }
20 }
21
22 //check whether the value is a product of two prime numbers
23 //on the same time check whether the value has a form of 4x+3
24 for (int aux = 2; aux <= value; aux++) {
25 if (primesArray[aux] == 1) {
26 if ((value % aux == 0) && ((aux - 3) % 4) == 0) {
27 int x = value / aux;
28
return (x != aux && primesArray[x] == 1 && (x - 3)
% 4 == 0);
29 }
30 }
31 }
32 return false;
33 }
34
35 public static void main(String[] args)
36 {
37 int vals[] = {177, 125};
38 System.out.println("Checking Blum integer...");
39 for(int i=0;i<vals.length;i++)
40 {
41 if (checkBlumInteger(vals[i]) == true)
42 System.out.println(vals[i] + " - True");
43 else
79
Chapter 6 Formal Techniques for Cryptography
80
Chapter 6 Formal Techniques for Cryptography
x 1 x1 2 x 2 n xn ,x G
then it is said that G is generated by S = {x1, …xn}. A group that is generated by only
one element is called a cyclic group. The order of a group is given by the number of its
elements. The order of an element g ∈ G represents the smallest integer m for which
gm = e, where (G, ∙) is the group.
Galois fields. Their name comes from the mathematician Evariste Galois and
represents fields with a finite number of elements in the base set. Galois fields are
important in computer science because here the data is represented as bits that
represent the elements of the Galois field GF = (ℤ2 = {0, 1}, + , ∙). Using field properties,
different operations can be applied between bits; therefore, data can be scrambled
easily. In the general case, a Galois field is defined as follows:
GF p n 0 , 1, p 1 p , p 1, p p 1 p 2 , p 2 1, , p 2 p 1
p n 1 , , p n 1 p 1
In this form, p is a prime number, and n is a positive integer. The values pn and p are
special, as the first gives the order of the field, and the other gives the characteristic of
the field. Note that addition and multiplication are made modulo p in a Galois field. The
following is an example of GF:
GF 2 3 0 , 1, 2 , 2 1, 2 2 , 2 2 1, 2 2 2 , 2 2 2 1 0 , 1, 2 , 3, 4 , 5, 6 , 7
81
Chapter 6 Formal Techniques for Cryptography
An example of usage Galois fields in computer science is the ASCII code that
contains 255 characters. The index of each character can be seen as an element
of GF(28).
E lliptic Curves
Elliptic curves have applications in different branches of cryptography, especially
in digital signatures. These were introduced by Neal Koblitz [1] and Victor Miller
[2] independently. Using elliptic curves brings advantages in the terms of efficiency
because the size of the keys in an elliptic curves–based cryptosystem is less than other
cryptosystems with the same level of security. Elliptic-curve cryptography (ECC) is
a branch of public-key cryptography (PKC) based on the algebraic properties of the
elliptic curves.
Weierstrauss form for elliptic curves. The graph that corresponds to the following
equation is called an elliptic curve E:
y 2 a1 xy a3 y x 3 a2 x 2 a4 x a6 ,
where a1, a2, a3, a4, a6 are constants and Δ ≠ 0 (called the discriminant of E). The
discriminant has the following form:
d2 a12 4a2
d4 2a4 a1a3
d6 a32 4a6
The condition for delta to be different from 0 is required to eliminate the possibility
of multiple roots. When defining an elliptic curve, it should be mentioned from which set
the values a1, a2, a3, a4, a6x, y are. In cryptography, usually these belong to ℤp (where p
82
Chapter 6 Formal Techniques for Cryptography
is a prime number) for which there are addition and multiplication operations, such
that together they form a field structure. Another possible set for the values is ℤq, where
q = pk, k ≥ 1, and p is prime. When the curve E has the values in a field K, then it is said
that E is defined over K, and it is denoted with E(K). However, the graph must contain
a special point called the point at the infinite and noted with ∞, which represents the
neutral element. Therefore, E(K) has the following form:
E K x , y K K |y 2 a1 xy a3 y x 3 a2 x 2 a4 x a6
For this structure, there is an operation called point addition, for which the neutral
element is ∞, together forming a group structure (E(K), +). Elliptic-curve cryptography
(ECC) lies its hardness assumption on the discrete logarithm problem (DLP) for elliptic
curves, which states the following:
Note that the operation kP represents the multiplication of a point on the curve
with a scalar value. You can find more about elliptic curves arithmetic and its use in
cryptography in [3]. Note that DLP can be generalized to any group structure.
One of the most efficient attacks against elliptic curve cryptosystems is the Pollard-
Rho attack that speculates on the discrete logarithm problem for elliptic curves.
First, it is given the general case of the DLP: let p be a prime number, a a generator
for the Diffie-Hellmann problem, x the private key, and y the corresponding public key.
Between all of these, the following equality exists:
y ≡ a x mod p
83
Chapter 6 Formal Techniques for Cryptography
A solution for this equation (i.e., finding x) is found when the equation is solved within
the modular ring modulus p − 1. Here, one of the following things can happen:
• The solution does not exist. In this situation, other values for u, v, u′,
v′ should be found.
• The solution exists, but it is not unique. In this situation, if there is a
relatively small number of solutions, then all of them can be tested by
brute force.
Conclusion
This chapter presented beginner background information (definitions and mathematical
descriptions) for the world of cryptography. You can find detailed references for
mathematical concepts that represent the background of cryptography in any of the
following references.
References
[1]. Koblitz, N. (1987). Elliptic curve cryptosystems. Mathematics of
computation, 48(177), pp. 203–209.
84
Chapter 6 Formal Techniques for Cryptography
85
CHAPTER 7
Pseudorandom Number
Generators
Randomness is a key element in cryptography, as cryptosystems and protocols are based
on arbitrary numbers that cannot be predicted. Numbers with such characteristics
are known as randomly generated numbers (or random numbers), and the technique
of their generation lies in a statistical context. Random numbers are mainly used in
domains in which results that cannot be predicted are expected, for example, statistical
sampling, simulations, or even gambling.
There are two main ways in which random numbers can be generated. The first
way is based on phenomenons from physics that prove to be random, generating
great entropy values. The second way is to create algorithms that can “choose”/
compute a sequence of numbers that appears to be random. Such algorithms are called
pseudorandom numbers generators (PRNGs), and usually, their base is a special value
called a seed from which the random generation of numbers starts in a specific way.
Because the PRNGs use this initial value seed, they are not truly random, which is the
reason for the pseudo in their name. However, the seed may come from natural sources
and may be changed occasionally. Another way to generate pseudorandom numbers
consists of combining the two main approaches.
Statistically, there is not too much information about what “random bits” refers to,
but from the computing machine point of view, random bits refers to a sequence of bits
chosen randomly.
To be considered a PRNG, an algorithm should meet the following conditions:
87
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_7
Chapter 7 Pseudorandom Number Generators
only smaller than a value, even if that value is the maximum (highest)
number that the computer supports; therefore, the period cannot be
infinite. However, the period can be set as high as possible.
In statistics, there is still some information about random bits: the frequency of the
appearance of 1 and 0 should be the same; the frequency for 00, 11, 01, 10 should be
the same, but these should appear half as less often than 1 and 0. To test “how much” a
sequence of numbers is random, different statistical tests may be used, such as Diehard
[2] or Kolmogorov-Smirnov [3]. Randomness is an essential aspect used in cryptography,
and deducing or recovering a random number should be very difficult (ideally
impossible). To be considered a perfect random number, the number may be recovered
by an attacker only by using brute force. Many techniques from cryptanalysis exploit the
weaknesses of the functions that generate random numbers.
Depending on the purpose, the required randomness degree of the PRNG can be
different. For example, when keys of an encryption system are generated, the degree
should be very high, while in protocols uniqueness for the generated nonce is required
and the degree of randomness is not required to be very high.
Some standards that describe the PRNGs are FIPS 186-4 [4], NIST SP 800-90A [5],
ANSI X9.17-1985 Appendix C, ANSI X9.31-1998 Appendix A.2.4, and ANSI X9.62-1998
Annex A.4, which is obsoleted by ANSI X9.62-2005, Annex D (HMAC_DRBG) [6].
88
Chapter 7 Pseudorandom Number Generators
E xamples of PRNGs
In this section, we present some PRNGs that are not necessarily as important as PRNGs
themselves but are important from the technical point of view and the mechanisms
used, because they represent the basis for other more complex or powerful PRNGs.
rn 1 arn b mod m ,
with a, b, m ∈ ℕ constants and r0 being the seed. A general formula for linear
congruential PRNGs is as follows:
rn k a k rn a k 1 cb 1 mod m
In these types of PRNGs, cycles occur, with the maximum length (called a period)
of cycles being m. The advantage of linear congruential PRNGs is the fastness of
computations. Its general form achieves the maximum period in the following situations:
• gcd(c, m) = 1
• b mod 4 = 0 if m mod 4 = 0
B
lum-Blum-Shub PRNG
A simple and efficient PRNG is Blum-Blum-Shub (BBS), also called a residual generator
[9], based on Blum integers (see Chapter 6 for a description of a Blum integer). To
generate random numbers using BBS, one should proceed as follows [9]:
89
Chapter 7 Pseudorandom Number Generators
Other types of LFSR generators are called stop-and-go. Some examples of stop-and-
go PRNGs are the Beth-Piper PRNG [13] (based on three circuits for which the clocks
are controlled; however, it does not resist against correlation attack) and the Gollmann
PRNG [14] (based on a serial construction of LFSRs, in which the clock of the current
LFRS is controlled by the previous LFSR).
O
ther PRNGs
The PRNGs lie their difficulty of recovering the sequence or predicting the next value in
different mathematical hardness assumptions.
An example of such a mathematical problem is the discrete logarithm problem
that represents the base for the Blum-Micali PRNG [15]. The setup for it consists of p, g,
which are prime numbers, and an initial value of x0. A sequence of random numbers is
p 1
given by the formula xi 1 g xi mod p . If xi , then the exit is 1; otherwise, the exit
2
is 0. For a large prime number p, the Blum-Micali PRNG is secure.
Another example of a mathematical problem that can be used in PRNGs is the RSA
problem [16], which represents the hardness of breaking the RSA cryptosystem. The
initial setup for this PRNG consists of the following values: p, q for large prime numbers,
n = pq; the value e that accomplishes the following criteria gcd(e, (p − 1)(q − 1)) = 1;
and an initial value x0 < n. A sequence of random numbers is given by the formula
xi 1 xie mod n . The exit of the RSA PRNG is zi = x1(mod 2). For a large number n, the
generator is secure.
Another type of PRNG is the Ranrot class [17] used in Monte Carlo algorithms, which
use Fibonacci numbers in their generation along with a shifting operation. Mainly, there
are four types of Ranrot generators.
P
RNGs Security
As you have already seen, pseudorandom number generators are extremely important
in cryptography. Because these are used in many cryptographic techniques, the PRNGs
themselves should be secure. [18] is a good reference for attacks applied to PRNGS, as
the author explores a wide range of attacks, grouping them into these three categories:
91
Chapter 7 Pseudorandom Number Generators
A detailed description of these classes of attacks can be found in [18], which also
presents examples of attacks that can be applied to known PRNGs. A more recent work
about PRNGs security is [19].
J ava.util.Random Class
In Java, random numbers can be generated using the java.util.Random class [20],
which can be instantiated using one of the following constructors:
• Random(): The seed for this generator is a value that was not used in
any other calls to instantiate in this way.
Using this class, you can generate streams of int, double, and long random
numbers or int, double, float, long, and boolean values. The seed is represented
in 48 bits but then changed through a linear congruential relationship. Note that the
individual values are generated using a uniform distribution, which means any value has
(almost) the same chances to be generated as the rest of the values of the same type. See
Listing 7-1.
92
Chapter 7 Pseudorandom Number Generators
1 import java.util.Random;
2
3 public class RandomExamples {
4
5 public static void main(String[] args) {
6
7 Random randomObject = new Random();
8 System.out.println("Generating an integer value < 1000... " +
randomObject.nextInt(1000));
9 System.out.println("Generating an integer value... " +
randomObject.nextInt());
10 System.out.println("Generating a long value... " +
randomObject.nextLong());
11 System.out.println("Generating a Boolean value... " +
randomObject.nextBoolean());
12 System.out.println("Generating a double value... " +
randomObject.nextDouble());
13 System.out.println("Generating a float value... " +
randomObject.nextFloat());
14 System.out.println("Generating an integer number... " +
randomObject.nextGaussian());
15
16 byte[] byteArray = new byte[15];
17 randomObject.nextBytes(byteArray);
18 System.out.println("Generating a sequence of bytes...");
19 System.out.print("[");
20 for(int i = 0; i< byteArray.length; i++)
21 {
22 System.out.print(byteArray[i] + " ");
23 }
24 System.out.print("]\n");
25 }
26 }
93
Chapter 7 Pseudorandom Number Generators
The code from Listing 7-1 is straightforward, and it generates different types of
random values. Figure 7-1 shows the output.
However, the instances of Random are not cryptographically secure. To use secure
PRNGs, Java provides a special class called java.security.SecureRandom [21]. The
PRNGs in this class are implemented according to FIPS 140-2 and RFC 1740 standards.
The ways in which the objects of the SecureRandom class are used are similar to how
Random is used. In Listing 7-2 we adapted the previous example to generate securely
random values. Figure 7-2 shows the output.
1 import java.security.SecureRandom;
2
3 public class SecureRandomExample {
4
5 public static void main(String[] args) {
6 SecureRandom secureRandomObject = new SecureRandom();
7
8 System.out.println("Securely generating an integer value <
1000... " + secureRandomObject.nextInt(1000));
94
Chapter 7 Pseudorandom Number Generators
9
System.out.println("Securely generating an integer value... " +
secureRandomObject.nextInt());
10
System.out.println("Securely generating a long value... " +
secureRandomObject.nextLong());
11
System.out.println("Securely generating a Boolean value... " +
secureRandomObject.nextBoolean());
12
System.out.println("Securely generating a double value... " +
secureRandomObject.nextDouble());
13
System.out.println("Securely generating a float value... " +
secureRandomObject.nextFloat());
14
System.out.println("Securely generating an integer number... " +
secureRandomObject.nextGaussian());
15
16 byte[] byteArray = new byte[15];
17 secureRandomObject.nextBytes(byteArray);
18
System.out.println("Securely generating a sequence of
bytes...");
19 System.out.print("[");
20 for(int i = 0; i< byteArray.length; i++)
21 {
22 System.out.print(byteArray[i] + " ");
23 }
24 System.out.print("]\n");
25 }
26 }
95
Chapter 7 Pseudorandom Number Generators
• Use a set of generated values only one time. Each time a series of
pseudorandom numbers is needed, the best approach is to generate
a new sequence.
96
Chapter 7 Pseudorandom Number Generators
C
onclusion
In this chapter, we discussed pseudorandom number generators. You learned which
characteristics an algorithm needs to have to be considered a pseudorandom generator.
In addition, to be used in cryptography, the pseudorandom generator must have two
additional characteristics. Further, we presented some PRNGs and the technical aspects
behind them, and lastly, we provided straightforward examples of how java.util.
Random and java.security.SecureRandom can be used.
References
[1]. Yao, A. C. (1982, November). Theory and application of trapdoor
functions. In 23rd Annual Symposium on Foundations of
Computer Science (SFCS 1982) (pp. 80–91). IEEE.
97
Chapter 7 Pseudorandom Number Generators
[9]. Blum, L., Blum, M., & Shub, M. (1986). A simple unpredictable
pseudo-random number generator. SIAM Journal on computing,
15(2), 364–383.
[13]. Beth, T., & Piper, F. (1984, April). The Stop-and-Go Generator. In
Eurocrypt (Vol. 84, pp. 88–92).
[14]. Park, S. J., Lee, S. J., & Goh, S. C. (1995, August). On the security
of the Gollmann cascades. In Annual International Cryptology
Conference (pp. 148-156). Springer, Berlin, Heidelberg.
[18]. Kelsey, J., Schneier, B., Wagner, D., & Hall, C. (1998, March).
Cryptanalytic attacks on pseudorandom number generators. In
International workshop on fast software encryption (pp. 168–188).
Springer, Berlin, Heidelberg.
98
Chapter 7 Pseudorandom Number Generators
99
CHAPTER 8
Hash Functions
In information security, hash functions are an important cryptographic tool. They have
applications in a wide range of use cases, such as securing passwords in a database,
securing authentication, and maintaining message integrity.
In a few words, a hash function is a compression mathematical function that takes
an input with any length and converts it into a string with a fixed length. The input can
be almost anything such as text or different types of files. The output, on the other hand,
should be unique for every input and has a predefined fixed length according to the type
of the hash function. The output is called a message digest, hash value, or hash.
A hashing class is a tuple with four elements, as follows [1]: the set of all possible
messages (encrypted or not) X; a finite set of fingerprints (digests) Y; a finite set of keys
K; and a set H of hash functions such that for every k ∈ K there exists a hash function
hK ∈ H, hK : X → Y. A pair (x, y) ∈ X × Y is valid for the key K if hK(x) = y.
The following problems should be hard to compute [1]:
• Weak collisions: For a given pair (x, y), it is hard to discover x1 ≠ x such
that h(x1) = h(x). This property protects against situations in which
the attacker has the input value and the corresponding hash and
tries to modify legitimate values with other values that seem to be
legitimate.
101
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_8
Chapter 8 Hash Functions
Several theorems establish an inferior limit for the cardinal of Y. One of them is
the birthday paradox through which a relation between #X and #Y is determined. The
relation is as follows: #X ≥ 2 ∙ # Y. The birthday attack is a brute-force attack that follows
to discover collisions. Generally, an attacker randomly generates some messages x1,
x2, … ∈ X (in practice, they use pseudorandom number generators) and, for each xi
computes and stores the digest yi = h(xi). Then, the attacker compares yi with the ones
stored previously. If yi equals another stored yj, then the attacker found a collision whose
N
form is (xi, xj). According to the birthday paradox, this would happen after about 2 2
messages. A hash function that represents the hash value on 40 bits is vulnerable to the
birthday attack using only 220 (approximately one million) random messages. Therefore,
in practice, it is recommended to use hash functions that represent the values on at least
256 bits. Table 8-1 presents a list of keyed cryptographic hash functions, while Table 8-2
presents a list of unkeyed cryptographic functions [2].
102
Chapter 8 Hash Functions
103
Chapter 8 Hash Functions
Hash functions have good applicability in digital signatures. Usually, when working
with digital signatures, the hash value of a long message is computed; only the hash
value is signed, and the sender sends it to the receiver. On the other hand, the receiver
computes the hash value of the received message. If it corresponds to the one sent by the
sender, then the message is righteous. This approach saves time and space complexity
because, otherwise, the original message should be split into blocks of a predefined
length, and then each block needs to be signed.
104
Chapter 8 Hash Functions
The BLAKE family [15] of hash functions uses the ChaCha stream cipher [30] as its
mathematical basis. The modifications besides ChaCha consist of adding a permuted
version of the input block XORed with constant numbers of the current round before
each ChaCha round. In BLAKE, there are used hash values of 8 words, which are
combined with 16 message words, and then the ChaCha value is truncated, obtaining
the next hash value.
The GOST hash function works as follows: the input message is split into blocks of
256 bits, and then a number of 0s are padded to the message such that it reaches the
length of 256 bits. The bits that are remaining are replaced by the sum of all previous
hashed blocks represented on 256 bits and an integer value represented on 256 bits
that is the length of the original message. However, [31] describes a collision attack that
breaks it into 2105 time.
The father of the message digest (MD) hash functions is Ronald Rivest, who
proposed MD2 in 1989. MD2-MD5 hash functions work on 128 bits. Each represents an
improvement of the previous one, and their mathematical construction is based on the
Merkle-Damgard function. Although on time, it was proven that they are not resistant
to collision attacks. For example, MD5 is still used as a checksum for data integrity,
although it is vulnerable to length extension attacks [32]. However, MD hash functions
represent the basis for other hash functions, such as RIPEMD. MD6 uses another
approach, namely, the Merkle tree. Their authors show that MD6 resists different types
of differential attacks [33].
The RACE Integrity Primitives Evaluation Message Digest (RIPEMD) family of
functions are created based on MD4 and MD5, and their performance is close to the one
of SHA-1.
The Secure Hashing Algorithms (SHA) family of hash functions is issued by the
National Institute of Standards and Technology (NIST). SHA-1 was designed by the
National Security Agency (NSA) after it was proved that the original SHA was insecure.
The basis of SHA-1 lies in the MD5 hash function. However, it was proved that SHA-1
is also insecure. SHA-224, SHA-256, SHA-384, and SHA-512 are included in the
next iteration of the SHA functions (known as SHA-2), which were also designed by
the NSA. SHA-3 hash functions represent the results of authors from outside of the
NSA. These are a subset of the Keccak family primitives, whose mathematical basis lies
in sponge functions. The reference [34] presents a well-organized table regarding the
security of the SHA hash functions. Here it is shown that SHA-512 and SHA-3 are secure
against collision attacks and length extension attacks.
105
Chapter 8 Hash Functions
The whirlpool hash function outputs a digest of 512 bits, and its mathematical
basis lies on the square block cipher, which was also used to design the AES
encryption system.
The most popular hash functions are those from the SHA-2 family. Although the MD
family and others like it are not secure anymore, they can be widely used as checksum
functions.
Although the hash functions are widely used with applications such as securing
passwords in databases, checking the integrity of different types of files, signing in
digital signatures, etc., they have a more recent important application, namely, the
blockchain. The entire infrastructure of blockchain technology lies in hash functions.
Blockchain, which is also called a distributed ledger, can be seen as a decentralized
database; therefore, there is no central authority that manages the database. All nodes
within the network are communicating on a peer-to-peer basis, which means that one
node communicates with all of the rest directly. One of the elements that a block of
data contains is the hash value of the previous block. With different types of consensus
algorithms that establish which node can add a block in the blockchain and this
approach of the structure, the data within a blockchain structure is extremely difficult to
forge. Figure 8-2 shows the general structure of a chain. Observe how the arrows indicate
that the field Prev contains the hash value of the previous data block. For example,
Bitcoin uses SHA-256 as its hash function.
In Java, using a hash function is easy, because they are already implemented in Java
libraries (see more details in Chapter 2). In Listing 8-1 we provide a simple example of
applying SHA-512 over input text. Figure 8-3 shows the result. Note that even a slight
modification of the input text yields a very different hash value. In Figure 8-3 the word
hash is written with a lowercase h, while in Figure 8-4, the word Hash is written with an
uppercase H.
106
Chapter 8 Hash Functions
1 import java.security.MessageDigest;
2 import java.util.Scanner;
3
4 public class HashFunctionExample {
5 public static void main(String args[]) throws Exception
6 {
7 System.out.println("\n Type the text: ");
8
9 Scanner scn = new Scanner(System.in);
10 String input = scn.nextLine();
11 scn.close();
12
13 System.out.println("\n The input text: " + input);
14
15 MessageDigest output_sha = MessageDigest.getInstance("SHA-512");
16
17 output_sha.update(input.getBytes());
18
19
20 byte[] digest = output_sha.digest();
21 System.out.println(digest);
22
23
24 StringBuffer hex_digest = new StringBuffer();
25
26 for (int i = 0;i<digest.length;i++)
27 {
28 hex_digest.append(Integer.toHexString(0xFF & digest[i]));
29 }
30 System.out.println("The hex representation : " + hex_digest.
toString());
31 }
32 }
107
Chapter 8 Hash Functions
Figure 8-3. The result of Listing 8-1 for the input “hash function example”
Figure 8-4. The result of Listing 8-1 for the input “Hash function example”
Besides collision resistance, hash functions must also meet another two security
requirements.
108
Chapter 8 Hash Functions
In [35] and [36], the authors classify attacks on hash functions into two categories.
C
onclusion
In this chapter, hash functions were presented. Hash functions are widely used
cryptographic primitives, and they have a large number of applications in the field of
information security.
A newer use case for hash functions is blockchain technology, which bases its core
on hash functions.
109
Chapter 8 Hash Functions
References
[1]. Atanasiu, A. (2009). Securitatea Informatiei vol 2 (Protocoale de
securitate). INFODATA Cluj Publishing House.
[8]. Kelsey, J., Chang, S. J., & Perlner, R. (2016). SHA-3 derived
functions: cSHAKE, KMAC, TupleHash, and ParallelHash. NIST
special publication, 800, 185.
[9]. Rivest, R. L., Agre, B., Bailey, D. V., Crutchfield, C., Dodis, Y.,
Fleming, K. E., ... & Yin, Y. L. (2008). The MD6 hash function–a
proposal to NIST for SHA-3. Submission to NIST, 2(3), 1-234.
Available online: http://groups.csail.mit.edu/cis/md6/
submitted-2008-10-27/Supporting_Documentation/md6_
report.pdf
110
Chapter 8 Hash Functions
[18]. Rivest, R., & Dusse, S. (1992). The MD5 message-digest algorithm.
[23]. Wang, X., Yin, Y. L., & Yu, H. (2005, August). Finding collisions
in the full SHA-1. In Annual international cryptology conference
(pp. 17–36). Springer, Berlin, Heidelberg.
111
Chapter 8 Hash Functions
[31]. Mendel, F., Pramstaller, N., Rechberger, C., Kontak, M., & Szmidt,
J. (2008, August). Cryptanalysis of the GOST hash function. In
Annual International Cryptology Conference (pp. 162-178).
Springer, Berlin, Heidelberg.
[33]. Rivest, R. L., Agre, B., Bailey, D. V., Crutchfield, C., Dodis, Y.,
Fleming, K. E., ... & Yin, Y. L. (2008). The MD6 hash function–a
proposal to NIST for SHA-3. Submission to NIST, 2(3), 1-234.
112
CHAPTER 9
Symmetric Encryption
Algorithms
In this chapter, we will discuss two types of symmetric encryption algorithms, Data
Encryption Standard (DES) and Advanced Encryption Standard (AES). The goal of this
chapter is to provide a starting point for implementing such algorithms from scratch
without using third-party libraries, by using the theoretical concepts and translating
them into a practical application using Java.
113
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_9
Chapter 9 Symmetric Encryption Algorithms
According to Figure 9-1, DES will encrypt the data using the first key (Key 1), and
the decryption will be done using the second key (Key 2). Further, the encryption is
performed again by using the third key (Key 3). There is another version of the algorithm
in which only the first and third keys are used, and the keys are the same. Some
applications still use this algorithm, but it is treated as a legacy algorithm.
114
Chapter 9 Symmetric Encryption Algorithms
Starting with Figure 9-2, you can see how the encryption and decryption processes
are performed within TDEA.
At this point, we will not focus on the mathematical background, and we will
proceed further with the implementation process. We strongly recommend following a
theoretical course in cryptography and information security to go deep and understand
what is happening during the implementation process. To achieve this goal, you’ll find
good references at the end of the chapter that will provide the best knowledge for a
cryptography mathematical apparatus.
115
Chapter 9 Symmetric Encryption Algorithms
Let’s take a look at the process of generating the keys. For this process, you need the
PC-1 and PC-2 permutations; see Table 9-1.
Table 9-1. Permutation PC-1 [5]
To transform the permutation PC-1 or PC-2 from Table 9-1 or Table 9-2 in a Java
expression, it is sufficient to declare a variable, for example, int pc_1[56] and int
pc2[48], respectively, and then initialize them properly as an array with a size set to 56
and 48, respectively.
Table 9-2. Permutation PC-2 [5]
• Input
• Data ← plaintext
• The IP will divide the plaintext into two equal-sized permuted blocks.
In some documentation, these permuted blocks are called the Left
Plain Text (LPT) and the Right Plain Text (RPT).
• Using the two blocks generated, LPT and RPT, the 16 rounds related
to the encryption process are performed. The steps behind the 16
rounds are as follows:
• Step 5: XOR
• Step 6: Swap
• Once the encryption process is done, the two blocks (LPT and RPT)
are rejoined.
• In the end, we get the encrypted version of the plaintext that will have
a size of 64 bits.
The decryption process is based on using the same algorithm but in reverse order.
Another important aspect that is taken into consideration when implementing the
DES algorithm is its modes of operation.
• Electronic Codebook (ECB): For each block with a 64-bit size, the
encryption and decryption are applied independently.
117
Chapter 9 Symmetric Encryption Algorithms
• Counter (CTR): For each of the blocks from the plaintext, the XOR
operation is performed with the help of an encrypted counter. The
next step is quite tricky as it needs to be incremented sequentially for
each of the blocks.
• Output Feedback (OFB): There are some similarities with the CFB
mode. The single difference is represented by the input of the
encryption algorithm, which is the output that precedes DES.
At this moment, we can say that we have covered all the elements and main concepts
to perform the implementation process.
In Listing 9-1 we will provide a basic implementation for the DES algorithm in which
we will show all the steps.
1 import java.io.*;
2 import java.security.spec.*;
3 import javax.crypto.*;
4 import javax.crypto.spec.*;
5
6
7 public class DES
8 {
9 //instance for encryption
10 private static Cipher encOp;
11
12 //instance for decryption
13 private static Cipher decOp;
14
15 //path for the file that will be encrypted
118
Chapter 9 Symmetric Encryption Algorithms
119
Chapter 9 Symmetric Encryption Algorithms
120
Chapter 9 Symmetric Encryption Algorithms
71 {
72 output.write(writeBuffer, 0, readBytes);
73 }
74 //closing the output stream
75 output.close();
76 //closing the input stream
77 input.close();
78 }
79
80 //encryption operation
81 private static void ComputeEncOperation(InputStream inFile,
OutputStream ouFile) throws IOException
82 {
83 ouFile = new CipherOutputStream(ouFile, encOp);
84
85 //write the bytes obtained from the encryption to the file
86 writeToFileTheBytes(inFile, ouFile);
87 }
88
89 //decryption operation
90 private static void ComputeDecOperation(InputStream inFile,
OutputStream ouFile) throws IOException
91 {
92 inFile = new CipherInputStream(inFile, decOp);
93
94 //write the bytes obtained from the decryption to the file
95 writeToFileTheBytes(inFile, ouFile);
96 }
97 }
Before running the implementation from Listing 9-1, we will need to have a file
created at a specified location, such as the one specified in line 16 (see Figure 9-3). If the
file does not exist, an exception is thrown with an error message (line 55). The other two
files are created automatically.
121
Chapter 9 Symmetric Encryption Algorithms
Figure 9-3. The file and its content that will be encrypted
Based on the file specified in line 16, when the encryption (see line 100) and
decryption operations (see line 110) are performed, two files will be generated: apress_
enc.txt for encryption output (see line 20 and Figure 9-4) and apress_dec.txt for
decryption output (see line 23 and Figure 9-5).
122
Chapter 9 Symmetric Encryption Algorithms
The same process that is used for encryption is used as well for decryption. With the
help of the init() method from the Cipher class, the algorithm will be initialized with
the public key based on the chosen transformation.
• Counter (CTR): For each of the blocks from the plaintext, the XOR
operation is performed with the help of an encrypted counter. The
next step is quite tricky as it needs to be incremented sequentially for
each of the blocks.
• Output Feedback (OFB): There are some similarities with the CFB
mode. The single difference is represented by the input of the
encryption algorithm, which is the output that precedes DES.
124
Chapter 9 Symmetric Encryption Algorithms
Based on the elements that we have mentioned, we can say that we have all the
elements and main concepts set to perform with the implementation process.
In Listing 9-2 we will provide a basic implementation for the AES algorithm in which
we will emphasize all the steps . Figure 9-6 shows the result.
1 import java.util.*;
2 import java.security.spec.*;
3 import javax.crypto.*;
4 import javax.crypto.spec.*;
5 import java.nio.charset.*;
6
7
8 public class AES
9 {
10 private static byte[] initialization_vector = {54, 34, 7, 3, 23,
78, 31, 68, 32, 40, 96, 43, 23, 54, 23, 76};
11 private static String aes_secretKey = "cryptoApress";
12 private static String aes_salt = "apress";
13
14 public static String Encrypt(String plain_message)
15 {
16 try
17 {
18 IvParameterSpec initializationVectorSpecs = new
IvParameterSpec(initialization_vector);
19
20 //the container for the secret key
21 SecretKeyFactory secretKeyContainer = SecretKey
Factory.getInstance("PBKDF2WithHmacSHA256");
22
23 //specification parameters (secret key, salt value,
iterations, key length)
24 KeySpec specificationsParameters = new PBEKeySpec
(aes_secretKey.toCharArray(),aes_salt.getBytes(),
65536, 256);
125
Chapter 9 Symmetric Encryption Algorithms
25
26 //generate the secret key based on the parameters
set above
27 SecretKey temporarySecretKey = secretKeyContainer.
generateSecret(specificationsParameters);
28
29 //align the secret key with the AES algorithm
30 SecretKeySpec crypto_key = new SecretKeySpec
(temporarySecretKey.getEncoded(), "AES");
31
32 //set the algorithm (e.g., AES) and its mode
together with its padding type
33 Cipher aesAlgorithm = Cipher.getInstance
("AES/CBC/PKCS5Padding");
34 aesAlgorithm.init(Cipher.ENCRYPT_MODE, crypto_key,
initializationVectorSpecs);
35
36 //get the encrypted version
37 return Base64.getEncoder().encodeToString
(aesAlgorithm.doFinal(plain _message.
getBytes(StandardCharsets.UTF_8)));
38 }
39 catch (Exception e)
40 {
41 System.out.println("During the encryption process,
the following error(s) occured: " + e.toString());
42 }
43 return null;
44 }
45
46 public static String Decrypt(String encrypted_message)
47 {
48 try
49 {
126
Chapter 9 Symmetric Encryption Algorithms
50
IvParameterSpec initializationVectorSpecs = new
IvParameterSpec(initialization_vector);
51
52 //the container for the secret key
53
SecretKeyFactory secretKeyContainer =
SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
54
55
//specification parameters (secret key, salt value,
iterations, key length)
56
KeySpec specificationsParameters = new PBEKeySpec
(aes_secretKey.toCharArray(),aes_salt.getBytes(),
65536, 256);
57
58
//generate the secret key based on the parameters
set above
59
SecretKey temporarySecretKey = secretKeyContainer.
generateSecret(specificationsParameters);
60
61
//align the secret key with the AES algorithm
62
SecretKeySpec secretKey = new SecretKeySpec
(temporarySecretKey.getEncoded(), "AES");
63
64
//set the algorithm (e.g., AES) and its mode together
with its padding type
65
Cipher cipher = Cipher.getInstance("AES/CBC/
PKCS5PADDING");
66
cipher.init(Cipher.DECRYPT_MODE, secretKey,
initializationVectorSpecs);
67
68 //get the decrypted value
69
return new String(cipher.doFinal(Base64.getDecoder().
decode(encrypted_message)));
70 }
71 catch (Exception e)
127
Chapter 9 Symmetric Encryption Algorithms
72 {
73 System.out.println("Error occured during decryption: "
+ e.toString());
74 }
75 return null;
76 }
77
78
79 public static void main(String[] args)
80 {
81 //set the message that we want to encrypt
82 String originalval = "Welcome to Apress. Enjoy learning
cryptography";
83
84 //perform the encryption
85 String encryptedval = Encrypt(originalval);
86
87 //perform the decryption
88 String decryptedval = Decrypt(encryptedval);
89
90 //show some messages
91 System.out.println("Plaintext used for encryption and
decryption -> " + originalval);
92 System.out.println("The encryption is -> " + encryptedval);
93 System.out.println("The decryption is -> " + decryptedval);
94 }
95 }
Before running the implementation from Listing 9-2, we need to set the initialization
vector, which can be set manually (see line 10); the secret key (see line 13); and the salt
value (see line 15). As a best practice, we strongly recommend that the initialization
vector be generated randomly without hard-coding it. This method is used only for the
example and educational purposes.
C
onclusion
In this chapter, we discussed symmetric encryption algorithms such as Data Encryption
Standard and Advanced Encryption Standard. You now should understand the main
differences, advantages, and disadvantages of DES and AES, as well as a short summary
of the modes used for each of the algorithms.
The examples provided were straightforward; we used a common and basic
implementation and explained the mode in which they should be implemented. The
implementations that we have provided are offered for educational purposes, and there
is no guarantee that in practice they will offer a maximum benefit, especially in the case
of the AES algorithm, which is quite sensitive about the process of implementation.
Lastly, Figure 9-7 summarizes the encryption process between DES and AES, as
shown in Figure 9-7.
Figure 9-7. Summary of the encryption process between DES and AES
129
Chapter 9 Symmetric Encryption Algorithms
References
[1]. Stinson, Douglas R., and Maura B. Paterson. Cryptography:
Theory and Practice. Fourth edition, CRC Press, Taylor & Francis
Group, 2019.
130
CHAPTER 10
Asymmetric Encryption
Schemes
Another name for asymmetric encryption is public-key cryptography (PKC). This name
comes from the fact that the cryptosystems in this category are using a pair of keys in
their algorithms. Specifically, a public key is used by the encryption algorithm, and a
private (secret) key is used by the decryption algorithm. In classical cryptography, the
purpose of each type of key is well established, but in modern cryptography, these types
of keys can be used for additional purposes. For example, another type of secret key can
be a master key, used to encrypt and decrypt the keys of a specific cryptosystem.
While in symmetric encryption schemes the cryptosystems use mathematical
concepts such as substitutions and permutations (learn about the AES and DES
algorithms in Chapter 9), asymmetric encryption has asymmetric functions as its
foundations. The authors who introduced the concept of asymmetric encryption are
Diffie and Hellman in their paper “New directions in cryptography” [1]. In this paper,
the authors explained what asymmetric encryption is and what the characteristics of
such a cryptosystem are. In addition, they showed how the secret keys can be securely
distributed over an insecure channel between the sender and the receiver. This new
concept was welcomed by the scientific community, and many encryption systems
that follow the rules from [1] were proposed in the meantime. The following are the
requirements presented in [1] that need to be accomplished by the cryptosystems:
• The receiver (which is the owner of the secret key) should be able to
use a computationally efficient algorithm to generate the pair of keys.
• A pair of keys is used. The public key is used to encrypt the plain
messages, and the secret key is used to decrypt the encrypted
messages.
131
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_10
Chapter 10 Asymmetric Encryption Schemes
• The plain text (message) cannot be computed if one knows the public
key and the encoded message.
3. To recover the message, R uses its private key and the decryption
algorithm to recover the message.
Some examples of well-known public-key encryption systems are RSA [2], ElGamal
[3], and Merkle-Hellman [4], which will be explained individually in the remainder
of this chapter. Asymmetric encryption is important because it is used in different
applications in cryptography, such as digital certificates and signatures, protocols
(encryption, multiparty computation, zero-knowledge), etc. Types of encryption
schemes include asymmetric encryption, homomorphic encryption, searchable
encryption, predicate encryption, functional encryption, etc., while branches of public-
key cryptography are integer factorization cryptography, elliptic-curve cryptography,
lattice-based cryptography, learning and ring-learning with errors, multivariate
cryptography, code-based cryptography, etc.
Sometimes, symmetric cryptosystems are faster than asymmetric ones, although
they may have the same security level. Usually, in these cases, the plain messages are
encrypted using the symmetric encryption scheme, and the secret key is encrypted using
the asymmetric encryption scheme and is sent between the sender and receiver over an
insecure channel.
132
Chapter 10 Asymmetric Encryption Schemes
R
SA
A well-known and commonly used public-key cryptosystem is RSA [2], which was
introduced in 1978 and named after its authors: Ron Rivest, Adi Shamir, and Len
Adleman. The hardness assumption for RSA is integer factorization, which means that
for two prime numbers that are large enough, their product is hard to be factorized by a
computing machine. What specifically does hard mean? It means that the problem to be
solved requires more than polynomial time.
In the remainder of this section, we will present the algorithms of the RSA
cryptosystem [2] and then their implementation in Java.
The first algorithm is the key generation algorithm, and it works as follows:
2. Determine n = pq.
4. Generate the integer value e, with 1 < e < ϕ(n) and gcd(e, ϕ(n)) = 1.
m e c mod n
The last algorithm is the decryption algorithm, which recovers the plain message m
from the encrypted value c, using the following formula:
c d m e m mod n
d
133
Chapter 10 Asymmetric Encryption Schemes
1 import java.io.BufferedReader;
2 import java.io.IOException;
3 import java.io.InputStreamReader;
4 import java.math.BigInteger;
5 import java.security.SecureRandom;
6
7
8 public class RSA {
9
10 private BigInteger prime_p, prime_q, val_n, phi_n, val_e, val_d;
11 private BigInteger one = BigInteger.ONE;
12 private int maximumLength = 1024;
13 private SecureRandom random;
14
15 public void KeyGeneration() {
16 random = new SecureRandom();
17 prime_p = BigInteger.probablePrime(maximumLength, random);
18 prime_q = BigInteger.probablePrime(maximumLength, random);
19 val_n = prime_p.multiply(prime_q);
20 phi_n = prime_p.subtract(one).multiply(prime_q.
subtract(one));
21 val_e = BigInteger.probablePrime(maximumLength, random);
22 do {
23 val_e = BigInteger.probablePrime(maximumLength, random);
24 }
25 while (phi_n.gcd(val_e).compareTo(one) < 0 && val_e.
compareTo(phi_n) > 0);
26 val_d = val_e.modInverse(phi_n);
27 }
28
29
134
Chapter 10 Asymmetric Encryption Schemes
135
Chapter 10 Asymmetric Encryption Schemes
57
58 System.out.println("\nDecrypting the message... ");
59 byte[] decryptedMessage = rsa.Decryption(encryptedMessage,
rsa.val_d, rsa.val_n);
60 System.out.println("Decrypted message [bytes]: " + byteTo
String(decryptedMessage));
61 System.out.println("Decrypted message [text]: " + new
String(decryptedMessage));
62 }
63
64
65 private static String byteToString(byte[] byteArray)
66 {
67 String recoveredStrig = "";
68 for (byte byteVal : byteArray)
69 {
70 recoveredStrig += Byte.toString(byteVal);
71 }
72 return recoveredStrig;
73 }
74 }
The code from Listing 10-1 follows the steps of the RSA algorithms presented in this
section. In lines 1–5, the necessary packages were imported, as follows: BufferedReader
and InputStreamReader are used for plain messages on line 50. The IOException is
necessary for cases where the input introduced by the user is not correct and makes
that main function to throw an IOException in this case. The BigInteger package is
used to work with big integers in Java. As shown, BigInteger is a Java class (and not a
third-party one). SecureRandom is used to generate pseudorandom numbers securely
(see Chapter 7 for details). In lines 10–13, the variables used in the RSA cryptosystem
are declared (see the descriptions of the algorithms from the previous listing), with the
prime_ prefix showing that the parameter should be a prime number and val_ showing
that the parameter is an integer value. The KeyGeneration, Encryption, and Decryption
functions just follow the mathematical operations of the RSA cryptosystem for each
algorithm. Note that BigInteger already implements the mathematical operations
(including prime number generation), which makes it easy to use. The encryption
136
Chapter 10 Asymmetric Encryption Schemes
function has as input the plain message and the public key, while the decryption
function has as input the encrypted message and the private key. In lines 44–60 the plain
message is read from the keyboard; then it is encrypted, and the result is decrypted. All
this information is displayed in the console. The function byteToString is used just to
print the byte array in a neat form, converting it to String. The size for the keys is 1024
(given by the value of maximumLength); in practice, the key size of RSA is 512, 1024, or
even 2048. Figure 10-1 shows the output of Listing 10-1. Note that the values obtained
in Figure 10-1 can be different every time because pseudorandom numbers are used.
However, the plain message should be the same as the decrypted message every time.
137
Chapter 10 Asymmetric Encryption Schemes
computations directly with the encrypted text, and the decryption of the result is the
same as the result of the equivalent operations (via a homomorphism) applied on the
plain text. Chapter 14
will discuss homomorphic encryption in more detail. For the RSA cryptosystem, the
homomorphic operation is the following multiplication:
E lGamal
Another notable example of public-key cryptosystems is ElGamal [3], whose theoretical
foundations lie in the cyclic groups and the hardness assumption is the discrete
logarithm problem (DLP). The specific DLPs for the ElGamal encryption system are
the Diffie-Hellman assumption and the decisional Diffie-Hellman assumption (more
technical details about DLP and Diffie-Hellman assumptions can be found in [5]
and [6]). In this section, we present the ElGamal algorithms [3] and then show the
implementation in Java.
The first algorithm is the key generation algorithm, and it works as follows:
2. Compute s = hy.
3. Compute c1 = g y.
4. Compute c2 = m ∙ s.
138
Chapter 10 Asymmetric Encryption Schemes
1. Compute s = c1x .
2. Compute s−1, the inverse of s.
3. Compute m = c2 ∙ s−1.
the same as the value from the first step of the decryption c1x g y g xy h y . So, the
x
1 import java.io.BufferedReader;
2 import java.io.IOException;
3 import java.io.InputStreamReader;
4 import java.math.BigInteger;
5 import java.security.SecureRandom;
6
7 public class ElGamal {
8
9 private BigInteger prime_q, val_x, val_g, val_h;
10 private byte[] c1, c2;
11 private BigInteger one = BigInteger.ONE;
12 private BigInteger two = new BigInteger("2");
13 private int maximumLength = 1024;
139
Chapter 10 Asymmetric Encryption Schemes
140
Chapter 10 Asymmetric Encryption Schemes
47 }
48 while (y.compareTo(val_h) >= 0);
49
50 s = val_h.modPow(y, prime_q);
51 c1 = (val_g.modPow(y, prime_q)).toByteArray();
52
c2 = (new BigInteger(plainMessage).multiply(s)).
toByteArray();
53
54
System.out.println("Encrypted message [bytes]: " +
byteToString(c1) + byteToString(c2));
55
System.out.println("Encrypted message [text]: " + new
String(c1) + new String(c2));
56
57 }
58
59 public void Decryption()
60 {
61 BigInteger s = new BigInteger(c1).modPow(val_x, prime_q);
62 BigInteger invS = s.modInverse(prime_q);
63
BigInteger m = invS.multiply(new BigInteger(c2)).
mod(prime_q);
64
65
System.out.println("\nDecrypted message [bytes]: " + byteTo
String(m.toByteArray()) + byteToString(m.toByteArray()));
66
System.out.println("Decrypted message [text]: " + new
String(m.toByteArray()));
67 }
68
69
70 public static void main(String[] args) throws IOException {
71 ElGamal elGamal = new ElGamal();
72 elGamal.KeyGeneration();
73
74
BufferedReader d = new BufferedReader(new InputStreamReader
(System.in));
141
Chapter 10 Asymmetric Encryption Schemes
75 String plainMessage;
76 System.out.print("Type the plain message: ");
77 plainMessage = d.readLine();
78
79 System.out.println("\nEncrypting the message... ");
80 elGamal.Encryption(plainMessage.getBytes());
81 elGamal.Decryption();
82 }
83
84 private static String byteToString(byte[] byteArray)
85 {
86 String recoveredStrig = "";
87 for (byte byteVal : byteArray)
88 {
89 recoveredStrig += Byte.toString(byteVal);
90 }
91 return recoveredStrig;
92 }
93 }
Similarly, with RSA, the ElGamal implementation follows the algorithms described
earlier. Figure 10-2 shows the result. Note that the values obtained in Figure 10-2 can
be different every time because pseudorandom numbers are used. However, the plain
message should be the same as the decrypted message every time. Examples of attacks
that can be launched against the ElGamal cryptosystem are brute-force attacks, meet-in-
the-middle attacks, and two-table attacks. A good reference for these attacks on ElGamal
is [13].
142
Chapter 10 Asymmetric Encryption Schemes
M
erkle-Hellman
Another example of asymmetric encryption is the Merkle-Hellman cryptosystem [4].
Although it has been proven that it is insecure [8], it is interesting from the technical
approach used, specifically the knapsack approach, presented in the next section.
143
Chapter 10 Asymmetric Encryption Schemes
A
lgorithms
Merkle-Hellman’s cryptosystem has the general three algorithms: key generation,
encryption, and decryption, which are presented in this section [7].
The key generation algorithm has the following steps:
where m1 is the most significant bit and mi is a bit of the message m with the length n.
The decryption algorithm has the following steps for recovering the plain message m
from the encrypted value c:
144
Chapter 10 Asymmetric Encryption Schemes
3. Pick a subset X ′ = {x1, …xk} for which the elements fulfill the
k
condition c wi xi .
i 1 k
4. The plain message is recovered as m 2n xi .
i 1
The third step of the decryption algorithm represents a problem called the subset
sum problem for the value c′. This problem can be used by applying a greedy algorithm.
Conclusion
The chapter explained what asymmetric encryption is and whether it is different from
symmetric encryption. The three of the most important asymmetric encryption schemes
were presented and then implemented: RSA, ElGamal, and Merkle-Hellman.
References
[1]. Diffie, W., & Hellman, M. (1976). New directions in cryptography.
IEEE transactions on Information Theory, 22(6), 644–654.
[2]. Rivest, R. L., Shamir, A., & Adleman, L. (1978). A method for
obtaining digital signatures and public-key cryptosystems.
Communications of the ACM, 21(2), 120–126.
[6]. Bao, F., Deng, R. H., & Zhu, H. (2003, October). Variations of diffie-
hellman problem. In International conference on information
and communications security (pp. 301–312). Springer, Berlin,
Heidelberg.
145
Chapter 10 Asymmetric Encryption Schemes
[12]. Dujella, A. (2004). Continued fractions and RSA with small secret
exponent. arXiv preprint cs/0402052.
146
CHAPTER 11
Signature Schemes
In the real world, when a message needs to be authenticated by individual, it is written
on paper, and then the individual signs the message. Therefore, it is known that this
specific message belongs to a specific person. In the digital world, things can happen
similarly: a piece of data (message) is created by an individual, and then the message is
signed digitally with a specific signature by that individual.
Digital signature schemes are public-key schemes that authenticate a message and
check its integrity. The receiver and any third party may check individually the bond
between the received message and the sender’s digital signature. In the digital signatures
schemes, the sender owns a secret key based on which the signature (which is public)
is generated. An important aspect is that the sender cannot reject the message once the
message is digitally signed by the sender. This property is called nonrepudiation, and it is
crucial in digital signature schemes. Besides nonrepudiation, other important properties
are data integrity and message authentication.
Although they belong to public-key cryptography, the signature schemes have a
slightly different form than regular encryption schemes. A digital signature scheme has
the following algorithms:
• Key generation: This algorithm generates the pair of keys, namely, the
secret key and the public key.
147
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_11
Chapter 11 Signature Schemes
Digital signatures were first mentioned by Diffie and Hellman in [1], but their
rigorous description and security requirements were presented by Goldwasser, Micali,
and Rivest in [2].
Digital signatures can be stand-alone algorithms or a combination of an encryption
algorithm with hash functions. Beware of the second approach as using only certified
algorithms for this purpose is recommended. Our first example is using the RSA
algorithm (learn about the RSA algorithm in Chapter 10) with the hash function
SHA-256 (learn more about the hash function in Chapter 8). Listing 11-1 shows the
implementation, and Figure 11-1 shows the output. Java implements a class called
Signature from the java.security package that contains a wide range of digital
signatures, for example, RSA combined with a hash function, NIST’s Digital Signature
Algorithm (DSA) [3] combined with a hash function, and the Edwards-Curve signature
algorithm [4]. You can learn more about signature schemes implemented in Java in [5].
1
2 import java.security.*;
3
4 public class DigitalSignature
5 {
6 //the function will help to generate the digital signature based
on SHA256 and RSA algorithm, using input and a private key
7 public static byte[] GenerateDS(byte[] dataInput, PrivateKey
prvKey) throws Exception
8 {
9 Signature signSHA256RSA = Signature.getInstance
("SHA256withRSA");
10 signSHA256RSA.initSign(prvKey);
11 signSHA256RSA.update(dataInput);
12 return signSHA256RSA.sign();
13 }
14
15 //the function will generate an asymmetric key pair based on
SecureRandom class and using RSA algorithm
16 //128 value
148
Chapter 11 Signature Schemes
149
Chapter 11 Signature Schemes
45
46 System.out.println("The message for which the signature
will be computed is -> " + message);
47 System.out.println("The length of the message is -> " +
message.length());
48
49 System.out.println("\n");
50
51 System.out.println("The 512-signature is -> \n " +
encStringToHex(generatedSignature512));
52
53 System.out.println("Status of 512-verification -> " +
CheckDS(message.getBytes(), generatedSignature512, kp512.
getPublic()));
54
55 System.out.println("\n");
56
57 System.out.println("The 1024-signature is -> \n " +
encStringToHex(generatedSignature1024));
58 System.out.println("Status of 1024-verification -> " +
CheckDS(message.getBytes(), generatedSignature1024,
kp1024.getPublic()));
59
60 System.out.println("\n");
61
62 System.out.println("The 2048-signature is -> \n " +
encStringToHex(generatedSignature2048));
63 System.out.println("Status of 2048-verification -> " +
CheckDS(message.getBytes(), generatedSignature2048, kp2048.
getPublic()));
64 }
65
66 //encoding string to hex value
67 public static String encStringToHex(byte[] generated_signature)
150
Chapter 11 Signature Schemes
68 {
69 StringBuffer hexStringValue = new StringBuffer();
70 for (int count = 0; count < generated_signature.length;
count++)
71 {
72
73 hexStringValue.append(encByteValuesToHex(generated_
signature [count]));
74 }
75 return hexStringValue.toString();
76 }
77
78 public static String encByteValuesToHex(byte value)
79 {
80 char[] hex_digit_value = new char[2];
81 hex_digit_value[0] = Character.forDigit((value >> 4) &
0xF, 16);
82 hex_digit_value[1] = Character.forDigit((value & 0xF), 16);
83 return new String(hex_digit_value);
84 }
85 }
151
Chapter 11 Signature Schemes
In lines 9–17, the digital signature is created. To do this, the message (dataInput)
and the private key used to sign the message are both required. Here, an instance
of the Signature class is created (in the previous example, the signature’s type is
SHA256withRSA), and then the signing process is initialized with the secret key. Next,
the message is signed and then returned. In lines 22–28, the pair of the secret key and
the public key for the RSA algorithm is generated. Next, in lines 31–38, the signature
is verified, based on the message and the public key, following a process similar to
the one for signing. In the main function, there are three examples of signing, namely,
using RSA with the key length 512, then 1024, and finally 2048. In lines 84–102 there
are helper functions that convert a string to a hex value, and a byte value to a hex value,
respectively.
The next signature scheme is ElGamal [6], which is based on the discrete logarithm
problem. The protocol is described next.
Key generation.
• In this algorithm, the sender picks a large prime integer value p and a
primitive root α.
• The sender picks an integer value a, which is the secret key, and then
computes the value β ≡ αa (mod p).
152
Chapter 11 Signature Schemes
1 import java.math.BigInteger;
2 import java.util.Scanner;
3
4 public class ElGamalSignature {
5 public static void main(String[] args) {
6 Scanner sc = new Scanner(System.in);
7 System.out.println("Value of p");
8 BigInteger p=new BigInteger(sc.next());
9 System.out.println("Value of alpha");
10 BigInteger alpha=new BigInteger(sc.next());
11 System.out.println("Value of m");
12 BigInteger m=new BigInteger(sc.next());
13 System.out.println("Value of k");
14 BigInteger k=new BigInteger(sc.next());
15 sc.close();
16
17 signingAlgorithm sign = new signingAlgorithm(p,
alpha, k, m);
18
19 System.out.println("Public key: " + p.intValue() + " " +
alpha.intValue() + " " + sign.beta.intValue());
20 System.out.println("y1: " + sign.y1 + "; y2: " + sign.y2);
21
22 verifyingAlgorithm verify = new verifyingAlgorithm(m, sign.
y1, sign.y2, sign.alpha, sign.beta, p);
23 verify.verify();
24 }
25
26 }
27
28
29 class signingAlgorithm {
30 public BigInteger p, alpha, beta, k, m, y1, y2;
31 private BigInteger a = new BigInteger("3");
153
Chapter 11 Signature Schemes
32
33 public signingAlgorithm(BigInteger p, BigInteger alpha,
BigInteger k, BigInteger m)
34 {
35 this.p = p;
36 this.alpha = alpha;
37 this.k = k;
38 this.m = m;
39
40 computeBeta();
41 computeY1();
42 computeY2();
43 }
44
45 public void computeBeta() {
46 this.beta = alpha.modPow(a, p);
47 }
48
49 public void computeY1() {
50 this.y1 = alpha.modPow(k, p);
51 }
52
53 public void computeY2() {
54 BigInteger invK = k.modInverse(p.subtract(BigInteger.ONE));
55 this.y2 = ((m.subtract(a.multiply(y1))).modInverse
(p.subtract(BigInteger.ONE)).m ultiply(invK)).mod
(p.subtract(BigInteger.ONE));
56 }
57 }
58
59
60 class verifyingAlgorithm {
61
62 public BigInteger m, y1, y2, alpha, beta, p;
63
154
Chapter 11 Signature Schemes
155
Chapter 11 Signature Schemes
Note that the previous implementation just follows the steps described for the
ElGamal signature scheme. However, in practice, it is recommended to use algorithms
already implemented in libraries, as they are tested and validated widely. In advanced
implementations, the message is hashed using a hash function, and it’s working with
the hash value of the message instead of the plain message. You can learn more about
signature schemes in [7] and [8].
C
onclusion
This chapter presented digital signatures, which are important algorithms used to
validate the bond between the sender and the message that it signs. The chapter
included two implementations of digital signatures: the first is a combination between
an encryption scheme (RSA) and a hash function (SHA256), and the second one is the
implementation of the ElGamal signature scheme.
References
[1]. Diffie, W., & Hellman, M. (1976). New directions in cryptography.
IEEE transactions on Information Theory, 22(6), 644–654.
[2]. Goldwasser, S., Micali, S., & Rivest, R. L. (1988). A digital signature
scheme secure against adaptive chosen-message attacks. SIAM
Journal on computing, 17(2), 281–308.
[3]. FIPS PUB 186-4. Digital Signature Standard. Available
online: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.
FIPS.186-4.pdf
[4]. Bernstein, D. J., Duif, N., Lange, T., Schwabe, P., & Yang,
B. Y. (2012). High-speed high-security signatures. Journal of
cryptographic engineering, 2(2), 77–89.
156
Chapter 11 Signature Schemes
157
CHAPTER 12
Identification Schemes
Identification schemes are one of the most important types of scheme used in
cryptography. There are two entities, namely, the prover and the verifier, in a scheme.
The prover tries to prove its identity to the verifier in such a way that the prover cannot
be impersonated by an adversary either in the process of demonstrating its identity or
after the demonstration. Once the identity is confirmed, not even the verifier can alter
the prover’s identity. The process of proving the identity may end with acceptance or
rejection (termination without acceptance).
A rudimentary technique of identification is using a password in a particular
process. This method provides weak authentication. Identification schemes have many
applications, such as access control. Access control is an important part of a system
because it manages the access to different resources based on the privileges of each
type of user within the system. However, the identification schemes are not related only
to human users; they can be used for a specific process authentication. For example,
a process/application may use a specific port for communication transmission, or
some automated task within an application is implemented to do specific operations
according to its privileges. Another handy example is related to our daily lives: we use
our biometric features (fingerprints, face) to unlock our smartphones.
An identification protocol takes place in real time, showing that the prover is active
and operational during the whole process of identification. To identify a prover, the
following techniques can be used:
159
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_12
Chapter 12 Identification Schemes
Weak authentication is made by using passwords, and there are several approaches. In
this case, the passwords can be stored in specific files that are protected from reading and
writing. However, the passwords should not be stored in plain text. Instead, the password
should be hashed using a particular hash function or hashing technique (see Chapter 8
for more about hash functions). Another approach involves defining rules for passwords,
for example using a minimum number of characters, uppercase letters, special symbols,
etc. These rules have the purpose of protecting against dictionary attacks, which can easily
break predictable passwords. For an additional level of security, the passwords can be, for
example, XORed with a specific value, and then on the obtained value is applied a hash
function. Finally, the hashed value is stored for further authentication.
The identification schemes that are based on passwords are exposed to the following
types of attacks: replay of fixed passwords, exhaustive password search, password-
guessing and dictionary attacks, etc.
There are two other techniques similar to passwords: PINs and two-step
authentication. One-time passwords (OTPs) are an intermediary technique between
weak authentication (passwords) and strong authentication (zero-knowledge proofs);
they provide a stronger authentication than passwords. As the name suggests, when the
user wants to authenticate, a different password is used each time. For the OTP, there
are several ways in which they can be used: a list of OTPs that is shared between the
authentication server and the user, OTPs that are updated continuously, and OTPs that
use hash functions.
Zero-knowledge proofs are the most secure way to prove an identity, because they
provide strong authentication. To identify itself, the prover may use zero-knowledge
proofs, and usually, the proof consists of several pairs of challenge-response messages
exchanged between parties (prover and verifier). To prove the identity, the verifier
challenges the prover, and the prover must respond with values known only by itself
that prove its identity. It works like a secret key-public key pair: the prover generates its
response based on its secret key, and the verifier checks the response using the prover’s
public key. When the messages are exchanged, the verifier learns nothing additional
about the verifier (has “zero knowledge”), and no additional information about the
prover is leaked such that the verifier convinces other entities about the prover’s identity.
Figure 12-1 shows a general form of message exchange.
160
Chapter 12 Identification Schemes
Figure 12-1. Exchanging the messages between the prover and verifier
The identification schemes that are based on zero-knowledge proofs have the
following characteristics:
3. The public key for the prover is PK = (v1, …, vk), and the secret
key is SK = (s1, …, sk).
• Messages exchange: For each round t, three messages are exchanged
between the prover and the verifier (see the next step for the formulas
for each value here):
e j 1
162
Chapter 12 Identification Schemes
e j 1
j 1
checks whether z = ± x and z ≠ 0.
Next, the implementation in Java is presented in Listing 12-1, and the result can be
checked in Figure 12-2.
1 import java.math.BigInteger;
2 import java.util.ArrayList;
3 import java.util.BitSet;
4 import java.util.List;
5 import java.util.Random;
6 import java.util.Scanner;
7
8 public class FFSScheme {
9
10 // declare system paramters: prime numbers p,q, computed n,
and given k
11 private static BigInteger p;
12 private static BigInteger q;
13 private static BigInteger n;
14 private static int k;
15
16 // used to generate random values
17 private static Random random = new Random();
18
19 // the set of k random integer values (private/secret key)
20 private static List<BigInteger> random_s_set = new
ArrayList<>();
163
Chapter 12 Identification Schemes
165
Chapter 12 Identification Schemes
166
Chapter 12 Identification Schemes
114
115 // compute y = [the product from above] x r (mod n)
116 y = product_s.multiply(r.mod(n)).mod(n);
117 }
118
119 private static void CheckProof() {
120
121 // compute the product (v_1)^(e_1) x ... x (v_k)^(e_k)
122 product_v = new BigInteger("1");
123 for (int i = 0; i < k; i++) {
124
product_v = product_v.multiply(computed_v_set.get(i).
pow(random_e_set.get(i) ? 1 : 0));
125 }
126
127 //compute z = [the product from above] x y^2 (mod n)
128
BigInteger z = (y.pow(2).mod(n)).multiply
(product_v).mod(n);
129
130 // BigInteger z = new BigInteger("1234555");
131
132 System.out.print("\nz = " + z.toString());
133
134 System.out.print("\nResponse: ");
135
136 //check whether z = +/- x and z != 0
137
if ((z.equals(x) || z.equals(x.negate().mod(n))) &&
!z.equals(new BigInteger("0"))) {
138 System.out.print("\nAccept");
139 } else {
140 System.out.print("\nReject");
141 }
142 }
143
144 public static void main(String[] args) {
145
167
Chapter 12 Identification Schemes
146 GenerateParameters();
147
148 GenerateKeys();
149
150 ExchangeMessages();
151
152 System.out.println("\n=== System parameters and
computed values
153 ===");
154
155 System.out.print("\np = " + p);
156 System.out.print("\nq = " + q);
157 System.out.print("\nn = " + n);
158
159 System.out.print("\nSecret key: ( ");
160 for (int i = 0; i < k; i++)
161 System.out.print(random_s_set.get(i) + " ");
162 System.out.print(")");
163
164 System.out.print("\nPublic key: ( ");
165 for (int i = 0; i < k; i++)
166 System.out.print(computed_v_set.get(i) + " ");
167 System.out.print(")");
168
169 System.out.print("\nr = " + r);
170
171 System.out.print("\nb = " + b);
172
173 System.out.print("\nx = " + x);
174
175 System.out.print("\nRandom bits e: ( ");
176 for (int i = 0; i < k; i++)
177 System.out.print(random_e_set.get(i) ? 1 + " " :
0 + " ");
178 System.out.print(")");
168
Chapter 12 Identification Schemes
179
180 System.out.print("\ny = " + y);
181
182 CheckProof();
183 }
184 }
The code from Listing 12-1 contains on the first six lines the imported libraries
used in the program. The code is divided into four methods, namely, the method
that implements the generation of the system parameters, the method for the keys
generation, the method that computes the values exchanged between the prover and
verifier, and the method that checks whether the response checks the identity of the
prover or not. Each method follows the computations presented in the technical details
of the FFS scheme. To check if the verification fails when a wrong value is sent, just
comment line 132 and uncomment line 134. It is obvious that the integer from line
134 does not fulfill the conditions z = ± x and z ≠ 0. Indeed, in this case, the identity is
rejected (see Figure 12-3).
169
Chapter 12 Identification Schemes
Note that the code from Listing 12-1 is implemented for the t = 1 round. For an
arbitrary number of rounds, the ExchangeMessages and CheckProof should be called
together for that number of times. If each time the message is “Accept,” then the identity
of the prover is confirmed; otherwise, the identity of the prover is not confirmed.
The FFS identification protocol has the following security properties [1]:
C
onclusion
This chapter showed that there are several types of identification schemes that confirm
the identity of an entity, from ones that provide weak authentication (such as passwords)
to ones that provide strong authentication (zero-knowledge proofs).
170
Chapter 12 Identification Schemes
References
[1]. Menezes, A. J., Van Oorschot, P. C., & Vanstone, S. A. (2018).
Handbook of applied cryptography. CRC press.
[4]. Feige, U., Fiat, A., & Shamir, A. (1988). Zero-knowledge proofs of
identity. Journal of cryptology, 1(2), 77–94.
171
CHAPTER 13
Lattice-Based
Cryptography and NTRU
This chapter presents an important topic in cryptography, namely, the encryption
schemes based on lattices. These structures are important because it has been proven
they can be included in post-quantum cryptography. Lattices are one of the few
techniques that can resist quantum attacks and are good candidates for encryption
schemes for quantum computers.
Such techniques are important because quantum computers are knocking on
the door and the digital world needs to be prepared. Traditional encryption systems,
such as RSA, Diffie-Hellmann, and elliptic curves cryptosystems, will be overcome by
the technological revolution brought about by quantum computers; therefore, more
powerful techniques and tools are necessary to protect the data.
As great as lattices seem, we need to pay a price for using lattices: they are very
complex mathematical structures that require solid knowledge of algebra and the ability
to understand and work with abstract concepts. Lattices are the basis for a large number
of fully homomorphic encryption schemes, which are another hot topic in cryptography
nowadays, because they allow computations to be made directly on the encrypted
data, obtaining the same result as applying equivalent operations on the plaintext (see
Chapter 14 for more details). Examples of lattice-based cryptosystems are Peikert’s
RLWE Key-Exchange [1], the GGH cryptosystem [2], and the NTRU cryptosystem [3].
This chapter will cover the main mathematical aspects that characterize lattices.
The concepts presented represent the minimum theoretical information required to
understand lattices.
173
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_13
Chapter 13 Lattice-Based Cryptography and NTRU
Consider the n-dimensional real numbers space ℝ n, whose elements have a form
of a row vector v = (v1, …, vn) and each vi ∈ ℝ, i ∈ {1, …, n}. A lattice has the following
representation:
n
v aivi |ai .
i 1
Note that the vector v from the previous definition should be a basis in ℝ n, and
ai is an integer number. In other words, a lattice is the set of all linear combinations
with integer coefficients. From the lattice’s definition, it can be easily seen that ℤ n is a
lattice produced by the standard basis in ℝ n. Figure 13-1 shows the representation of a
lattice in ℝ 2.
v b ,
174
Chapter 13 Lattice-Based Cryptography and NTRU
175
Chapter 13 Lattice-Based Cryptography and NTRU
a f c mod q
b a mod p
m = fp b
176
Chapter 13 Lattice-Based Cryptography and NTRU
Figure 13-2. Configuring the building path for adding NTRU library from
https://github.com/tbuktu/ntru
177
Chapter 13 Lattice-Based Cryptography and NTRU
2. Click Add External Class Folder. Select the path to the location
where the NTRU library was downloaded.
Figure 13-3. Adding an external class folder for the NTRU library
3. After adding it to the JARs and class folders on the build path list,
check that the path to the NTRU has been added correctly. Once
everything is OK, click Apply and Close.
178
Chapter 13 Lattice-Based Cryptography and NTRU
Once steps 1 through 3 have been performed, you should be able to run the example
from Listing 13-1 smoothly without any issues.
179
Chapter 13 Lattice-Based Cryptography and NTRU
12 }
13
14 private void ExecuteNTRUEncryptionDecryptionProcess() throws
Exception
15 {
16 String message = "Welcome to Apress. Enjoy learning " + "
practical cryptography and NTRU operations";
17
18 // setup the parameters for NTRU and AES
19 String ntru_aes_parameters = "AES/CBC/PKCS5Padding";
20 int length_for_aes = 128;
21 EncryptionParameters parameters_for_ntru = Encryption
Parameters.APR2011_439_FAST;
22
23 // setup an NTRU instance based on the encryption parameters
24 // and generate the key pair using NTRU instance
25 NtruEncrypt encryption_with_ntru = new NtruEncrypt
(parameters_for_ntru);
26 EncryptionKeyPair ntru_key_pair = encryption_with_ntru.
generateKeyPair();
27
28
29 System.out.println("Decrypted message = " + message.
substring(0, 50) + "...");
30 System.out.println("Length of plain message = " + message.
length());
31 System.out.println("Maximum length of NTRU = " + parameters_
for_ntru.getMaxMessageLength());
32
33 // compute the encryption of the message
34 byte[] encryption_message = EncryptTheMessage(message.
getBytes(),
35 ntru_key_pair.getPublic(),
36 ntru_aes_parameters,
37 length_for_aes,
180
Chapter 13 Lattice-Based Cryptography and NTRU
38 parameters_for_ntru);
39
40 System.out.println("Encrypted length = " + encryption_
message.length +
41 " (NTRU=" + parameters_for_ntru.
getOutputLength() + ", "
42 + "AES=" + (encryption_message.length - parameters_
for_ntru.getOutputLength()) + ")");
43
44 // compute the decryption of the message
45 String decryption_message = new String(DecryptTheMessage
(encryption_message,
46 ntru_key_pair,
47 ntru_aes_parameters,
48 length_for_aes,
49 parameters_for_ntru));
50
51 System.out.println("The decryption of message is = " +
decryption_message.substring(0, 50) + "...");
52 System.out.println("The length of the decrypted message is = " +
decryption_message.length());
53 }
54
55 // encryption function will receive the following parameters:
56 // - the public key
57 // - the mode of AES
58 // - the length of AES
59 // - the encryption parameters for NTRU block
60 private byte[] EncryptTheMessage(byte[] clearMessage,
61 EncryptionPublicKey public_key,
62 String modeOfAES,
63 int lengthOfAES,
64 EncryptionParameters ntru_parameters) throws Exception
65 {
66 // compute cryptographic AES key
67 SecretKey cryptoKeyForAES = generateAesKey(lengthOfAES);
181
Chapter 13 Lattice-Based Cryptography and NTRU
68
69 // generate key specifications for encoding with AES - also
it will for generating
70 // the initialization vector (IV)
71 SecretKeySpec key_specifications_aes = new SecretKeySpec
(cryptoKeyForAES.getEncoded(), "AES");
72
73 // providing encryption for message using AES
74 Cipher algorithm = Cipher.getInstance(modeOfAES);
75 algorithm.init(Cipher.ENCRYPT_MODE, key_specifications_aes);
76 byte[] initialization_vector = algorithm.getParameters().
getParameterSpec(IvParameterSpec.class).getIV();
77 byte[] encryption_with_aes = algorithm.doFinal(clearMessage);
78
79 // encrypt AES key and IV with NTRU
80 NtruEncrypt encryption_with_ntru = new NtruEncrypt(ntru_
parameters);
81 byte[] cryptoAESKey_Array = cryptoKeyForAES.getEncoded();
82 byte[] initializationVector_and_cryptoKey = generate_byte_
array(cryptoAESKey_Array, initialization_vector);
83 byte[] encryptedResultWithNtru = encryption_with_ntru.
encrypt(initializationVector_and_cryptoKey, public_key);
84
85 // put everything in one byte array
86 return generate_byte_array(encryptedResultWithNtru,
encryption_with_aes);
87 }
88
89
90 // decryption function will receive the following parameters
91 // - the encrypted message as an array of byte
92 // - the decryption key pair
93 // - the mode of AES
94 // - the length of AES
95 // - the encryption parameters related to NTRU block
182
Chapter 13 Lattice-Based Cryptography and NTRU
183
Chapter 13 Lattice-Based Cryptography and NTRU
121
122 // set the specifications of the parameters for the
initialization vector
123 IvParameterSpec initialization_vector_specifications = new Iv
ParameterSpec(initializationVectorArray);
124
125
126 // initialize the algorithm for decryption by specifying the
mode, the AES key and initialization vector
127 algorithm.init(Cipher.DECRYPT_MODE, key_specification_aes,
initialization_vector_specifications);
128
129 // obtain the message in clear based on the encrypted message
with AES
130 byte[] messageInClear = algorithm.doFinal(encrypted_message_
with_aes);
131
132 // return the clear version of the message
133 return messageInClear;
134 }
135
136 private SecretKey generateAesKey(int number_of_bits) throws
Exception
137 {
138 // generate the key for AES
139 KeyGenerator generatorForAESKey = KeyGenerator.getInstance
("AES");
140
141 // initialize the key based on the number of the bits
142 generatorForAESKey.init(number_of_bits);
143
144 // get and return the generated crypto key
145 return generatorForAESKey.generateKey();
146 }
147
184
Chapter 13 Lattice-Based Cryptography and NTRU
185
Chapter 13 Lattice-Based Cryptography and NTRU
When running the example from Listing 13-1, the output should look like
Figure 13-5.
Figure 13-5. The output of the NTRU encryption and decryption process
Except the main function, which executes the NTRU encryption and decryption
mechanisms, the process is based on these five functions:
186
Chapter 13 Lattice-Based Cryptography and NTRU
using the encryption parameters and cryptographic key generated earlier using the
NTRU instance and its given parameters (line 8). Next, in line 14 to 16 we will show
different aspects related to the process (as shown in Figure 13-1, the first three lines
from the console). In line 18 we declare a byte array for the encrypted message, and
the encryption of the message is obtained using the EncryptTheMessage() method
(described and shown in Listing 13-3). This process has to be done with respect to the
parameters, such as the message (its representation as bytes), the public key from the
key pair generated in line 11, the NTRU AES parameters set in line 6, the length of an
encryption key for AES (set in line 7), and the parameters mentioned for NTRU (set
in line 8). In line 24 we will show in the console the result (as shown in Figure 13-1,
the fourth line from the console output). Continue with line 29, we will process the
decryption process for the encrypted message with the help of the DecryptTheMessage()
method, shown and described in Listing 13-4. The parameters received by the
DecryptTheMessage() method are the same as the ones from the EncryptTheMessage
method, except the first parameter, which is represented by the encryption form of the
message. In lines 35 and 37, we will show the result, as displayed in Figure 13-1, which
are the last two lines from the output.
187
Chapter 13 Lattice-Based Cryptography and NTRU
188
Chapter 13 Lattice-Based Cryptography and NTRU
• modeOfAES: Represents the mode chosen for AES (set in line 6 from
Listing 13-2)
Based on these parameters, the processes in Listing 13-3 are executed by following a
simple, logical, and rational procedure. In line 7 we will compute the AES cryptography
key using the length received as a parameter. In line 9 we use the key specifications
to help us to provide the proper encoding using AES, and we will obtain later the
initialization vector, which is very important for AES. Further, in line 12 we mention an
instance of class Cipher by providing the operating mode for AES. In line 14 we compute
and obtain the initialization vector. Lines 18 to 23 represent the encryption process using
the AES cryptography key and initialization vector with NTRU.
189
Chapter 13 Lattice-Based Cryptography and NTRU
10
11 Cipher algorithm = Cipher.getInstance(modeOfAES);
12 algorithm.init(Cipher.ENCRYPT_MODE, key_specifications_aes);
13 byte[] initialization_vector = algorithm.getParameters().
getParameterSpec(IvParameterSpec.class).getIV();
14 byte[] encryption_with_aes = algorithm.doFinal(clearMessage);
15
16 NtruEncrypt encryption_with_ntru = new NtruEncrypt
(ntru_parameters);
17 byte[] cryptoAESKey_Array = cryptoKeyForAES.getEncoded();
18 byte[] initializationVector_and_cryptoKey = generate_byte_
array(cryptoAESKey_Array, initialization_vector);
19 byte[] encryptedResultWithNtru = encryption_with_ntru.encrypt
(initializationVector_and_cryptoKey, public_key);
20
21 return generate_byte_array(encryptedResultWithNtru,
encryption_with_aes);
22 }
Next, we will take a closer look at the DecryptTheMessage method, which is shown in
Listing 13-4. The parameters received in line 1 through the signature of the method are
similar to the ones from the EncryptTheMessage method shown in Listing 13-3.
Based on the NTRU parameters discussed, in line 7 we need those parameters to
provide the proper decryption process. Lines 9 to 15 represent the obtaining process of
the cryptographic key and initialization vector using the NTRU block. Moving forward,
in line 18, based on the AES cryptographic key and initialization vector, we will perform
the decryption of the message. In line 21 we will get an instance to set up the algorithm
used in the decryption process and initialized in the variable modeOfAES. Further, in line
23, we will need to specify the key specifications that are related to the algorithm that we
are using (e.g., AES); in line 25, we set the specification parameters for the initialization
vector; and in line 28, we initialize the algorithm for decryption by specifying the mode,
190
Chapter 13 Lattice-Based Cryptography and NTRU
the cryptographic key, and the initialization vector. Moving forward, in line 31 we
compute the decryption process and obtain the plaintext, and in line 33 we return the
message.
191
Chapter 13 Lattice-Based Cryptography and NTRU
23
24 algorithm.init(Cipher.DECRYPT_MODE, key_specification_aes,
initialization_vector_specifications);
25
26 byte[] messageInClear = algorithm.doFinal(encrypted_message_
with_aes);
27
28 return messageInClear;
29 }
Conclusion
This chapter presented lattices, one of the most important techniques in cryptography.
Their importance in quantum cryptography was highlighted, as well as the reasons why
lattices are one of the best candidates for post-quantum encryption schemes.
The technical presentation of lattices and the NTRU encryption scheme was
followed by a practical example of using NTRU in Java.
References
[1]. Peikert, C. (2014, October). Lattice cryptography for the internet.
In International workshop on post-quantum cryptography
(pp. 197–219). Springer, Cham.
[2]. Goldreich, O., Goldwasser, S., & Halevi, S. (1997, August). Public-
key cryptosystems from lattice reduction problems. In Annual
International Cryptology Conference (pp. 112–131). Springer,
Berlin, Heidelberg.
[3]. Hoffstein, J., Pipher, J., & Silverman, J. H. (1998, June). NTRU: A
ring-based public key cryptosystem. In International Algorithmic
Number Theory Symposium (pp. 267–288). Springer, Berlin,
Heidelberg.
192
Chapter 13 Lattice-Based Cryptography and NTRU
193
CHAPTER 14
Advanced Encryption
Schemes
Advanced encryption schemes include fully homomorphic encryption (FHE) and
searchable encryption (SE), which is a particular case of FHE. More than a decade ago
when it was introduced, fully homomorphic encryption was considered a revolutionary
approach in cryptography, although privacy homomorphism was introduced in the
late 1970s [1]. Both types of encryption schemes are important for today’s technologies
as they correspond to the current cybersecurity needs. Both are mainly focused on
technologies such as cloud computing.
H
omomorphic Encryption
Homomorphic encryption is a type of encryption scheme that enables the user to
make computations on encrypted data. This eliminates the need for decryption
before applying some computations to the data. This saves a lot of time by eliminating
additional procedures for downloading the data from the cloud server, decrypting it,
applying computations on data, and then encrypting it back and storing it again on the
cloud server in encrypted form. A classical use case of homomorphic encryption is when
a user who is on a vacation in a foreign country wants to find out which is the nearest
restaurant from their geographical position, or where the interesting museums are. A
simple search on the Internet for these places can reveal a lot of information about the
user: what country they are in, their eating preferences (by looking at the restaurant
type), what kind of knowledge they want to learn (by looking at the museum type), their
current location, and so on. If the search engine system implemented a homomorphic
encryption scheme, then this information about the user would not be accessible to
the search engine system anymore, because all search operations would be made over
195
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_14
Chapter 14 Advanced Encryption Schemes
encrypted data and the user would receive the result in encrypted form. From this
simple example, you can see the potential of homomorphic encryption for (almost) all
domains of activities.
Let’s suppose there are two structures of the same type (groups, rings, or fields):
(G1, ⊥), (G2, ∗). A function f : G1 → G2 is called homomorphism between G1, G2 if
f x1 x 2 f x1 f x 2 ,x1 , x 2 G1
This relation says that the properties of the operation from G1 are transferred to G2
via a homomorphism f. In other words, in homomorphic encryption, all computations
applied on the plaintext give the same result as applying the corresponding operations
(via a homomorphism) over encrypted data. In this case, the result obtained from the
plaintext is the same as the decrypted result obtained from the encrypted text. This
is translated in technical aspects through the relationship that will be given next. In
homomorphic encryption, there is an additional algorithm, besides the well-known key
generation, encryption, and decryption. This algorithm is called evaluation (usually
denoted with Eval), and it enables the evaluation of two encrypted texts c1, c2 (or an
arbitrary number of encrypted text c1, …cn) as follows:
Dec kpriv ,Evalkeval c1 ,c 2 f m1 ,m2 .
where m1, m2 are the corresponding plain messages from c1 and c2. Note that the
evaluation algorithm uses an evaluation key, which is public.
From the four mathematical operations, only addition and multiplication should
have homomorphic properties, because the circuit of any function can be expressed
by using only the gates corresponding to these two operations. In short, functions are
expressed through logical circuits that contain logical gates (AND, OR, XOR, NOT). More
information about logical circuits and how the functions are expressed using them can
be found in [2] and [3]. The problem with some homomorphic schemes is that they are
constrained by physical limitations, as will be explained in the following categories;
therefore, the operations will not be applied unlimitedly.
The intuition for homomorphic encryption is introduced in [1], in the form of
privacy homomorphism. However, there are pros and cons to this approach; an example
of danger is an attacker that alters the encrypted text, therefore resulting in other
plaintext that is not legitimate. The unpadded RSA [4] is considered among the first
encryption schemes that support homomorphic properties and works as follows:
196
Chapter 14 Advanced Encryption Schemes
where m1, m2 represents plain messages in the form for unpadded RSA and Enc is the
encryption function of unpadded RSA.
Figure 14-1 shows the history of homomorphic encryption in a graphical form and
represents some important encryption systems in each category.
• Fully homomorphic encryption (FHE): The last and the most exciting
category of homomorphic encryption schemes is FHE, which
enables both operations to be homomorphic and to be applied an
unlimited number of times; therefore, any type of computation
can be applied over encrypted data. In the research literature, FHE
is considered the “holy grail of cryptography” or the “Swiss Army
197
Chapter 14 Advanced Encryption Schemes
• SEAL [14] : This was developed by Microsoft and implements the BFV
[15] and CKKS [16] encryption schemes. It can be used as a library in
C# and C++.
198
Chapter 14 Advanced Encryption Schemes
For Java, there is a library that implements homomorphic encryption schemes that
can be found at [21] , but it is deprecated.
HE is standardized through the efforts of actors from different areas of business,
such as industry, government, and academic institutions. All resources regarding HE
standardization can be found at [19].
S
earchable Encryption
Searchable encryption is a particular case of fully homomorphic encryption that allows
search operations to be made over encrypted data. A classic example here is the medical
unity that needs to retrieve a medical file for a specific patient from the servers by typing
the personal Social Security number of the patient. Searchable encryption would work
here as the search would be made directly on encrypted data; therefore, there is no need
to retrieve the encrypted documents from the server or decrypt them. Searching for text
based on a keyword is also an operation, and because the search is on encrypted data,
then SE is a particular case of FHE.
The use-case scenario for SE is when there exists an entity that owns a set of
documents D = {D1, …, Dn}, which are described by a set of keywords K = {kw1, …, kwm}.
The owner encrypts the documents using an SE scheme and stores them on a cloud
server. Then, when the user wants a document (or more) that contains a specific
keyword, the user will compute a special value called a trapdoor that the search process
will be based on. The trapdoor value is then submitted to the cloud server that performs
the search operation directly over the encrypted data and then sends the result to the
user, who further decrypts the received documents.
Usually, searchable encryption schemes have two components: the setup
component and the retrieval component. In the setup are operations such as data
preprocessing, key generation, encryption, and storing data on the cloud servers, while
the retrieval component contains operations such as query submission, search, and
document retrieval. Searchable encryption has its specific types of users as follows:
• The data owner is the entity that owns the data, encrypts it, and
stores it in encrypted form on the cloud server.
199
Chapter 14 Advanced Encryption Schemes
• The data user is the entity that works with the data. The data user can
compute trapdoor values based on the query keyword and submit
the queries to the cloud server. Also, the data user decrypts the
encrypted result received from the server.
• The cloud server stores the encrypted data uploaded by the data
owner and makes the search operation based on the trapdoor value
received from the data user.
As you can see, the roles are very well established and delimited. In addition to
the well-known key generation, encryption, and decryption algorithms, searchable
encryption has two (or three) more algorithms based on which search is made. These are
as follows:
• Controlled searching means that the system does not accept search
queries from unauthorized users. Moreover, the search operation
made by the server should be applied directly to the encrypted data
(without decrypting the data in any way).
• Encrypted queries means that the keyword for the search query
should always be encrypted before being sent to the server.
200
Chapter 14 Advanced Encryption Schemes
• Query isolation means that the server learns nothing about the
keyword, documents, the correspondence between a keyword and
a set of documents, etc. In many studies, the server is described
as “honest but curious,” meaning that the server does its work as
it should, but it can try to find relevant information in the process.
Query isolation is also required in this setup for the server.
Among the first SE schemes were [22] and [23], and they are important for the
categories in which they are included (SSE and PKSE, respectively) because they are
considered primary works.
Two libraries that implement searchable encryption schemes are [24] and [25] .
C
onclusion
This chapter presented two of the most important topics of cryptography for today’s
research community. Fully homomorphic encryption is important because the
techniques that it uses and its mathematical properties make it quantum resistant.
This is a powerful property as quantum computers already exist in dedicated research
laboratories. Searchable encryption is also an important topic, being a particular case
of fully homomorphic encryption. Its focus is on searching for specific data that fulfills
some criteria, an aspect that is very useful in the database field.
References
[1]. Rivest, R. L., Adleman, L., & Dertouzos, M. L. (1978). On data
banks and privacy homomorphisms. Foundations of secure
computation, 4(11), pp. 169–180.
201
Chapter 14 Advanced Encryption Schemes
[8]. Dan Boneh, Eu-Jin Goh, and Kobbi Nissim, “Evaluating 2-DNF
formulas on ciphertexts.” Theory of Cryptography Conference.
Springer, Berlin, Heidelberg, 2005.
202
Chapter 14 Advanced Encryption Schemes
[16]. Cheon, J. H., Kim, A., Kim, M., & Song, Y. (2017i). Homomorphic
encryption for arithmetic of approximate numbers. In
International Conference on the Theory and Application
of Cryptology and Information Security (pp. 409–437).
Springer, Cham.
[17]. Chillotti, I., Gama, N., Georgieva, M., & Izabachene, M. (2016).
Faster fully homomorphic encryption: Bootstrapping in less
than 0.1 seconds. In international conference on the theory and
application of cryptology and information security (pp. 3–33).
Springer, Berlin, Heidelberg.
[20]. Song, D. X., Wagner, D., Perrig, A. (2000). Practical techniques for
searches on encrypted data. In Proceeding 2000 IEEE Symposium
on Security and Privacy. SP 2000 (pp. 44–55). IEEE.
[21]. kryptnostic/fhe-core, https://github.com/kryptnostic/
fhe-core
203
Chapter 14 Advanced Encryption Schemes
204
CHAPTER 15
Cryptography Tools
This chapter presents two of the most popular software applications and tools for
cryptography that are great for learning and practice purposes: CrypTool (CT) [1] and
OpenSSL [2].
C
ryptTool
The original version of CT was written in C++, but there are several versions, including
an online version and a version written in Java, called JCrypTool (JCT). The latest
stable version is 1.0.8, and it is supported on Windows, macOS, and Linux; it can
be downloaded from the official website at https://www.cryptool.org/en/jct/
downloads. After downloading the archive, unarchive it and then launch the executable
file called JCrypTool.exe. After opening it, you’ll see the main window of JCT, as
shown in Figure 15-1. Here, there are several options. To start using JCT, click the Start
JCT option.
205
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5_15
Chapter 15 Cryptography Tools
You’ll see four main sections after starting to use JCT, as shown in Figure 15-2.
The first section is File Explorer, which, by default, shows the content of the Users
folder. The second section is the Help window, where you can find descriptions of
different functionalities of JCT . The third section is a .txt file that can be written with
different input values for a chosen cryptosystem. Lastly, the fourth section contains a
list of encryption systems and cryptographic primitives that can be tested; it is called
CryptoExplorer. You can choose different operations in CryptoExplorer such as Analysis,
Visuals, or Games. For example, if you select an encryption system from the fourth
section, then in the Help section you will see information about the selected topic in the
window shown in Figure 15-3.
206
Chapter 15 Cryptography Tools
207
Chapter 15 Cryptography Tools
The first example of using JCT is an easy one; namely, we’ll look at the Caesar cipher.
To start, edit the text in the third section of the window with a message that will be
encrypted using Caesar; then in the Algorithms menu choose Classic ➤ Caesar. Next, a
window will open, where you’ll choose the secret key and set some settings (Figure 15-4).
Figure 15-4. Choosing the secret key and the settings for the Caesar cipher
In the window shown in Figure 15-4, choose the type of operation, i.e., encryption
or decryption. You’ll see settings for the alphabet. The default setting is Upper Latin
(A-Z), but you can choose from a wide range of alphabets; the tool even supports a
user-defined alphabet. The alphabet can be displayed by clicking the “Show alphabet”
button, and the input can be filtered, such that the symbols that are not contained in the
alphabet are excluded from the input. Then select the key by choosing the index of the
208
Chapter 15 Cryptography Tools
symbol key in the alphabet or the letter directly. Here also is the setting for the index of
the first character of the alphabet, and it can be set to 0 or 1. The Caesar encryption can
be executed from the command line, and in the last setting, the text of the command is
shown. Once you’ve established the encryption key and the settings, then you can click
the Next button, which leads to the window in Figure 15-5.
Figure 15-5. Choosing the secret key and the settings for the Caesar cipher
209
Chapter 15 Cryptography Tools
The settings in Figure 15-5 refer to some transformations that can be applied to
the input before encryption, for example transforming all characters to uppercase,
replacing some special symbols, deleting white spaces, or eliminating the characters
that do not belong to the alphabet; then click the Finish button. The result is shown in
Figure 15-6, and it is saved in a text file called out002.txt (or a similar name). Note that
the encrypted text is displayed in a separate text window. For this example, the text for
encryption is “This is an example of using Caesar cipher in JCrypTool.”
The decryption for the Caesar cipher works similarly: from the window shown
in Figure 15-4, choose the decryption operation. But before doing that, the text file
unsaved001.txt should be closed, such that the input text for the decryption is the
one obtained from the encryption (stored in the text file out002.txt). Remember,
Caesar is a symmetric cipher; therefore, the decryption key should be the same as the
encryption key. In this example, the key is J (or its index in the alphabet; namely, 9 is the
starting index is 0). For decryption, the Next button is disabled; therefore, click Finish.
Figure 15-7 shows the result for the decryption.
210
Chapter 15 Cryptography Tools
The next example, of the RSA encryption system, is more complex. Before selecting
the type of cryptosystem, type the message to be encrypted into a text file. For this
example, the message is “Using RSA to encrypt the message.” Choose Algorithms ➤
Asymmetric ➤ RSA from the menu. The window shown in Figure 15-8 opens.
From here, choose Encrypt as the operation and then click “Create a new key pair in
the keystore,” if you do not already have a secret-public key pair for the RSA.
For the new key pair, some information should be completed: the contact name,
the algorithm for generating the pair and the length, and, lastly, the passwords for the
process. The default contact name is [PW: 1234] Alice Whitehead, but for this example,
we have changed it to Apress Reader. Keep the default values for the algorithm and key
length. The password for this example is RSA@2021. Then click Finish (see Figure 15-9).
211
Chapter 15 Cryptography Tools
After generating the keys, you are returned to the window shown in Figure 15-10,
where you should click the Finish button.
212
Chapter 15 Cryptography Tools
The output for the encryption process is the encrypted text, which is shown in a new
generated file with the extension .bin. The encrypted message from this example looks
like the one from Figure 15-11. On the left side of the .bin file is the representation of
the message in hexadecimal format, while in the right part there is the message in text
form. For a selected byte, some information is shown at the bottom of the window: the
hexadecimal value, the decimal, and the binary form. At the bottom left, you’ll see the
number of the current byte and the total number of bytes in the .bin file.
Figure 15-11. The encrypted message resulted from using the RSA cryptosystem
To decrypt the message, choose again Algorithms ➤ Asymmetric ➤ RSA. Then, from
the open window, choose “Decryption as operation” this time. Note this time the pair of
keys previously generated is not preloaded, and the button for generating a new pair is
disabled. From here, choose the pair of keys generated previously and then click Finish
(Figure 15-12). Next, the password used to create the pair of keys should be introduced;
click OK (Figure 15-13). Note it is important to not forget the password used in the key
generation.
213
Chapter 15 Cryptography Tools
214
Chapter 15 Cryptography Tools
CryptTool is a powerful software application for cryptography that can be used for
different purposes such as encryption/decryption with a wide range of cryptosystems
(symmetric and asymmetric), key generation, hashing, pseudorandom number
generation, cryptanalysis, etc.
O
penSSL
OpenSSL is another powerful tool for cryptography. It can be used in different scenarios
such as generating keys for different cryptosystems (although the keys can be generated
directly with Java) and working with SSL requests. OpenSSL can be downloaded from
the official website (https://slproweb.com/products/Win32OpenSSL.html). The latest
version for Windows at this moment is 3.0.0.
Download the installer, open it, and then follow the installation steps, leaving the
default settings (Figure 15-15).
215
Chapter 15 Cryptography Tools
The next step is to add the OpenSSL configuration and binaries to the system
variables.
To run Environment Variables, go to System Properties and click Environment
Variables (Figure 15-16). From the opened window, click the New button at the bottom
(Figure 15-17), and complete the information for the OpenSSL configuration as in
Figure 15-18.
216
Chapter 15 Cryptography Tools
217
Chapter 15 Cryptography Tools
Then, add the binary files for OpenSSL, as follows: in the “System variables” section
select Path and then Edit (Figure 15-19). Here, click New and paste the path of the bin
folder for OpenSSL (Figure 15-20). Click OK, then OK again, and OK again. The System
Properties window closes.
218
Chapter 15 Cryptography Tools
219
Chapter 15 Cryptography Tools
To test whether OpenSSL was configured and added properly, open a terminal
window and type the command openssl version. The version of the library should be
displayed (Figure 15-21). If you need help with the OpenSSL commands, just type the
openssl command in the terminal.
To demonstrate the use of OpenSSL, the next example shows how to generate the
private and public keys for the RSA cryptosystem.
First, change the current directory to a specific folder that can be easily found. In
this example, we are placing the folder in C:\openssl. The command to generate Alice’s
private key is as follows:
Check the content of the current directory; indeed, the two keys have been generated
(Figure 15-22).
220
Chapter 15 Cryptography Tools
Conclusion
Cryptography and information security are some of the most exciting and important
branches of computer science and information technology as technology evolves and
threats may appear anytime even from unexpected sources.
This chapter presented two important software applications and tools used in
these fields, namely, CrypTool and OpenSSL. They are very powerful and provide
complex operations. Also, the chapter presented how the tools can be installed and how
they can be used. The JCrypTool version is even more relevant as it is written in Java,
while OpenSSL can be used to parametrize things in Java cryptosystems or for other
cryptographic purposes.
221
Chapter 15 Cryptography Tools
References
[1]. CrypTool. Available online: https://www.cryptool.org/en/
222
Index
A Ciphertext, 4
Closest vector problem (CVP), 174
Advanced Encryption Standard (AES), 113
Collision-resistant hash function, 102
advantages, 123
Collisions, 108
disadvantages, 123
Conditional probability, 74
encryption/decryption, 123
Control access, 159
implementation, 125, 128, 129
Counter (CTR), 118, 124
modes of operation, 124
Cryptanalysis, 3, 4, 72
Algebraic structures, 80
Cryptanalytic attacks, 109
Application programming
CryptoExplorer, 206
interface (API), 9, 32
Cryptographic engines, 31
Asymmetric encryption, 131
Cryptographic primitive, 4, 71
Attacks, 72
Cryptographic Service Provider (CSP), 31
Authorities, 72
Cryptography, 1–3, 47
Authorization modules, 23
Cryptology, 3
CrypTool (CT), 205, 215
B Cryptosystem, 72, 131
BigInteger package, 136 Cyclic group, 81
Big integers, 76, 78
Binary operation, 80
Bits, 71
D
Blum-Blum-Shub (BBS), 89, 90 Data encryption, 36, 38, 39
Blum integer, 78, 80 Data Encryption Standard (DES), 113
Brute-force attack, 53 encryption/decryption, 116–118, 121
generating keys, 116
modes of operation, 117
C Decryption algorithm, 133
Caesar cipher, 48, 49 DecryptTheMessage() method, 187
cryptanalysis, 53 Digital Signature Algorithm (DSA), 148
implementation, 49, 51, 52 Digital signature schemes, 147
Cipher Block Chaining (CBC), 117, 124 algorithms, 147, 148, 152
Cipher Feedback (CFB), 118, 124 ElGamal, 153, 155
223
© Stefania Loredana Nita and Marius Iulian Mihailescu 2022
S. L. Nita and M. I. Mihailescu, Cryptography and Cryptanalysis in Java,
https://doi.org/10.1007/978-1-4842-8105-5
INDEX
G
Galois and Counter Mode (GCM), 124 J
Galois fields, 81 Jakarta EE 10, 21
Generic attacks, 109 business applications, 23
GOST hash function, 105 CDI, 26
224
INDEX
225
INDEX
227