使用RSA算法，解决银行系统中的安全问题。

## Objectives

- Design a solution with MV* architecture.
- Reuse Java CLI to read from, and write to external sources.
- Use functional Java where appropriate (you do not need to use it everywhere!)
- More practice with design patterns

## General Requirements

Create a new Gradle project for this assignment in your individual GitHub repo.

For this assignment, please continue to use packages as in the past. There is only one problem so you may have only one package, but it can be helpful to create additional packages to keep your code organized. The requirements for repository contents are the same as in previous assignments.

Please include a brief write-up of which design pattern(s) you used, where, and why. This is just to help your grader understand your approach.

To submit your work, push it to GitHub and create a release on your master branch. Only one person needs to create the release.

## The problem: Online Banking and RSA Digital Signatures

In this assignment, we are considering a simple example of secure online banking. If your bank did not have a way to confirm your identity, then anyone could claim that they are you, and they would be able to log into your bank account.

To prevent that from happening, most online services rely on digital signatures. Digital signatures are a public key-based cryptographic mechanism that allows an online service to do two things simultaneously: verify your identity, and verify your message.

Public key cryptography (in a nutshell): all public-key cryptographic algorithms have one thing in common: they all consist of two keys: a public key, PK and a private (secret) key, SK.

Digital signatures (in a nutshell): Let’s assume you want to digitally sign your message to the bank, m. To do so, you would take your message, and you would then perform some cryptographic operation f on that message using your private key, SK. You would then append your digital signature to your original message, (m, f(m, SK)), and send that pair to your bank. To verify your identity, and the content of your message, the bank would then take your public key, PK, and apply some related cryptographic function, g(m, f(m, SK), PK), on the received pair. If the verification returns true, the bank would know that it is indeed you, sending the message (because, presumably, you are the only one who knows your private key), and that the message hasn’t been altered en route.

## Your Task

Your task is to simulate the described identity and message verification process in some typical, but imaginary, financial institution, Secure Bank, N.A. You will create a program, SecureBankVerificationSimulator, that takes four input arguments:

- The number of unique bank clients - an integer, upper-bounded by 50 000 (inclusive). It represents the number of unique clients that the bank has, and that can use bank’s online services.
- The number of unique verifications - an integer, upper-bounded by 10 000 (inclusive). It represents the number of distinct digital signature verifications that the bank needs to perform.
- The percentage of invalid messages - a real number, in the range [0, 100], representing the fraction of (message, digital signature) pairs either incorrectly generated on the client’s side, or incorrectly received by the bank. In the given range, bound zero means that all of the (message, digital signature) pairs are correct, and bound 100 that all of the pairs are incorrect.
- The output file - a string, representing the name of the output file

The order of arguments should be as defined above, and if one of the arguments is missing, the program should terminate with an appropriate message.

Within your simulator, you can create the requested number of unique clients, and the requested number of unique pairs (message, digital signature) any way you prefer (randomly is perfectly fine). In doing so, please take into account the parameter indicating the percentage of incorrect messages.

Once the unique (message, digital signature) pairs have been created, your simulator should then simulate the verification process, and write the simulation results into the provided output file.

## Generating and Storing the Requested Number of Unique Bank Clients

An important observation about this assignment: while we are not building a networked system, we are trying to simulate a system that consists of two logical components, a bank, and bank clients. These two components have different information available, as explained below.

Additionally, we are assuming that the bank, and all of the individual clients are using the RSA- based digital signature to secure the clients’ online interaction with the bank. The RSA digital signature algorithm consists of three distinct phases, key generation, digital signature generation, and signature verification, and their details are described below. With that in mind, for the purpose of your simulation, you will need to randomly generate the requested number of unique bank clients. Every bank client has:

- A unique ID number - this number should be a randomly generated integer, but it should be unique for every client (i.e., it should never be the case that two clients have the same ID). This number is known to both the client and the bank.
- A (private key, public key) RSA pair - this pair of integers should be generated using the RSA key generation algorithm, described below. Both keys are known to the client, but only the public key is known to the bank.
- A deposit limit - this number should be a randomly generated integer from the range [0,

2000], and it does not have to be unique for every user. The information about the deposit limit is only known to the bank - A withdrawal limit - this number should also be a randomly generated integer, but from the range [0, 3000]. It again does not have to be unique for every user, and it is only known to the bank.

## Generating (message, digital signature) Pairs

To generate the requested number of (message, digital signature) pairs, your simulator should randomly choose the requested number of clients, and for every client, it should generate:

- A message, where a message is a randomly generated integer from the set [0, 30000], and it does not have to be unique for every transaction. For simplicity, the last digit of the generated number represents the transactions that a client is requesting - numbers 0-4 mean that a client is requesting a deposit, whereas numbers digits 5-9 mean that a client is requesting a withdrawal. That last digit should be included into a computation of a digital signature.
- A digital signature, where the digital signature is generated in two possible ways, depending on whether a message is valid or not. You should make a random determination of whether a message is valid or not, taking into account the input parameter, percentage of invalid messages.
- If a message is deemed invalid, then a digital signature should be just some randomly generated integer.
- If a message is deemed valid, you should generate the corresponding digital signature using the RSA signature generation algorithm, described below.

## Processing (message, digital signature) Pairs

Another important part of your program is the simulation of the steps that a typical bank would take to verify a received (message, digital signature) pair. In this implementation, we assume that the bank knows the IDs, the public keys, and the withdrawal and deposit limits of all the clients, but it does not know the clients’ private keys.

So, every time the bank receives the (message, digital signature) pair from some client A who has a unique ID, ID A , it has to find the client A’s corresponding public key, PK A . It then uses that public key to verify the received (message, digital signature) pair, using the RSA signature verification algorithm, described below.

If the signature verification process succeeds (i.e., it returns true as a result), the bank proceeds to validate a client’s request. Based on the last digit of the received message, it determines whether a client wants to make a deposit or a withdrawal, and then based on the limits set for that clients, verifies if the received request can be fulfilled or not. Please note that the last digit of the message should only be used for action determination, and not for amount determination. For example, a message 15005 means that a client wants to withdraw $1500 from their account, and message 23004 means that a client wants to deposit $2300 to their account (for example, using quick pay or a check scan).

Note 1: Since the bank is expected to process a large number of (message, digital signature) pairs daily, it needs to be able to efficiently find the corresponding public key of the current client. As a part of this assignment, you want to take seriously this requirement for efficient access, and encode the knowledge accessible to the bank in an appropriate data collection that will achieve that efficiency.

## RSA Key Generation, Digital Signature Generation, and Signature Verification

The RSA digital signature consists of three components, namely Key Generation, Signature Generation, and Signature Verification, described as follows:

### RSA Key Generation

Some client, Alice, generates keys for the RSA digital signature scheme via the following procedure:

- Alice generates two distinct large primes p and q, and then computes
`φ(n) = (p - 1)(q - 1)`

, and`n = p * q`

. - Alice generates a random integer a that satisfy
`gcd(a, n) = 1`

and`gcd(a, φ(n)) = 1`

, where gcd denotes a greatest common divisor. - Alice computes b such that
`ab ≡ 1 mod φ(n)`

. - Alice’s public key PKA is given by (b, n). Her private key is SKA = (a, n), she keeps it as a secret.

Note 2: The public key and private key for the RSA digital signature are generated in the same way as the public and private keys for RSA encryption.

### RSA Signature Generation

Alice generates a signature on a message m by computing: `sigSKA (m) = m^(a) mod n`

, where m^(a) mod n means m raised to exponent a under modulus n.

### RSA Signature Verification

Some bank, referred to as Bob, who receives a (message, signature) pair (m,) from Alice, verifies the message through the following procedure:

- Compute
`m' = σ^(b) mod n`

. - If
`m' = m`

, accept the message (return true). Otherwise, reject (discard) the message (return false).

Note 3: In this assignment, you will need to implement all three steps of the RSA digital signature algorithm, key generation, signature generation, signature verification. In doing so, you may want to use classes java.math.BigInteger and java.security.SecureRandom.

Note 4: Please note that there exist many implementations of RSA algorithm online. You are allowed to consult online resources, but please cite any resources that you may use. More importantly, please be mindful because many of the implementations available online either are not correct, or do not conform with our established software development practice.

## Generating the Output File

The results of your simulation should be stored in the provided CSV file (if the file does not exist, it should be created). The raw data, randomly generated during the simulation, should be stored into the CSV files, that will include the following header:

- Transaction number - Date,
- Time,
- Client ID,
- Message,
- Digital signature,
- Verified,
- Transactions status.

For every processed (message, digital signature) pair, the information indicated in the header should be provided as a row in the file, where column verified can have only two values - yes, if the message was verified, and no, if it verification failed. Similarly, column transaction status can have only four values - deposit accepted, deposit rejected, withdrawal accepted, and withdrawal rejected