By using RSA encryption, it is possible to "encrypt" sign with sender's private key and then with receiver's public key, and decrypt with receiver's private key and then with sender's public key?
Like this:
- Sender keys
- private: $(n_s,d_s)$
- public: $(n,s,e_s)$
- Receiver keys
- private: $(n_r,d_r)$
- public: $(n_r,e_r)$
- (Signature then) Encryption of message $m$
- $c_1\gets m^{d_s}\bmod n_s$
- $c_2\gets {c_1}^{e_r}\bmod n_r$
- and then decryption with
- $\widetilde{c_1}\gets {c_2}^{d_r}\bmod n_r$
- $\widetilde{c_2}\gets {\widetilde{c_1}}^{e_s}\bmod n_s$
Mathematically speaking it should work, right?
EDIT: code with the methods to generate keys, encrypt and decrypt.
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class ChatRSA {
//inizializzazione di un oggetto BigInteger con valore intero randomico
public static BigInteger Rand(){
Random ra=new Random();
int bits=1024;
BigInteger bigran;
do{
//Numero che è probabilmente primo(la possibilità che non lo sia è di 1 ogni 100 miliardi di anni approssimativamente)
bigran=BigInteger.probablePrime(bits, ra);
//Eseguo un doppio controllo per aumentare la possibilità che sia primo
}while(!bigran.isProbablePrime(100));// Più è grande il parametro, più aumenta la possibilità che sia primo
return bigran;
}
//Calcolo primo numero delle 2 chiavi
public static BigInteger N(BigInteger p, BigInteger q){
BigInteger n=p.multiply(q);
return n;
}
//Funzione Toziente(Conta in base a un numero n i numeri coprimi rispetto a n)
public static BigInteger V(BigInteger p, BigInteger q){
BigInteger v=p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
return v;
}
//Secondo numero della chiave pubblica, che deve essere coprimo di V
public static BigInteger Npub(BigInteger v){
BigInteger npub;
do{
npub=ChatRSA.Rand();
// gcd, il massimo comune divisore deve essere 1
}while(!npub.gcd(v).equals(BigInteger.ONE)&&npub.compareTo(v)==-1);
return npub;
}
//Secondo numero della chiave privata
public static BigInteger Npri(BigInteger v, BigInteger npub){
BigInteger npri;
do{
//(Npri * Npub)mod(v)Deve risultare = 1
//quindi questo metodo opera npri^-1 mod(v)
npri=npub.modInverse(v);
//System.out.println((npri.multiply(npub)).mod(v).toString());
}while(!(npri.multiply(npub)).mod(v).equals(BigInteger.ONE));
return npri;
}
//Metodo per convertire la Stringa del messaggio in cifre
public static BigInteger StringToCipher(String msg){
//Array di byte, tipo di dato intero più piccolo. Viene usato e gestito in array
//Recupera in array di bytes la stringa e la assegna
byte [] bar=msg.getBytes();
//Il valore dell'array di bytes convertito nel corrispondete grande intero
BigInteger cmsg=new BigInteger(bar);
return cmsg;
}
//Metodo per convertire il messaggio cifrato in stringa
public static String CipherToString(BigInteger msg){
byte [] bar=msg.toByteArray();
String dcmsg=new String(bar);
return dcmsg;
}
//Metodi per criptare e decriptare il messaggio
public static BigInteger Encryption(BigInteger cmsg, BigInteger npub, BigInteger n){
//Il metodo modPow utilizza la formula per criptare il messaggio nell RSA: cmsg^npub mod(n)
BigInteger c=cmsg.modPow(npub, n);
return c;
}
public static BigInteger Decryption(BigInteger c, BigInteger npri, BigInteger n){
BigInteger m=c.modPow(npri, n);
return m;
}
}