0

You can ignore everything up to update 3, the rest is just for reference about what got me to the point I am at.

Okay, so I'm pretty new to coding, and I wanted to tackle something functional. I've been working on a RSA cryptosystem that will generate a key pair and will encrypt/decrypt messages using said key pair. So far, I've figured out how to generate the modulus and exponent for each key, and how to get each key to function properly when encoding/decoding. But I'm working with the raw modulus and exponent separately for each key, and I have no real clue how the formatting of an RSA key is supposed to look. So, I want to know how I can create a properly formatted RSA key (I know I have to use the javax.crypto, but I don't quite get how). What I'd prefer is if I can take the code I already have (which is below) and add a part which takes the modulus and the exponent and puts them together into a proper key. Oh, and I'd like to be able to find the modulus and exponent from a key so I can add it to my encrypt/decrypt code parts. Additionally I have the public key I've generated as a modulus and exponent.

UPDATE on issue: Okay, so thanks to ArtJom B. I have been looking at the security library in java. But now I've run into a new issue, and I'm completely lost. I edited my code so that it (hopefully) should take the parts of each key and turn them into key objects using the keyfactory. But I keep getting the same error. Below is the new program's code, and also the error I keep getting. I don't really care if it means that I'm remaking the algorithm's implementation, I just want to get my code functioning.

Update 2: Okay, so GregS linked me to a thing about exceptions. Great! the code will compile now, and run. But a few problems exist. A) the private key only displays as [this part is fixed]and I don't know what I can do with that... B) the public key is still separated as the modulus and public exponent, I thought it wasn't supposed to do that

Small update: Oh, I figured it out, I accidentally put the private exponent in the modulus area and he public exponent in the private exponent area in the RSAPublicKeySpec ctor. But issues A and B still exist...

Final Edit: Okay, so the question was starting to get too broad. I was changing its focus from the original intention. My original question was answered, and so the code that works is below. I generate a key object then get the base64 of its encode.

Here's the new code:

    import javax.xml.bind.DatatypeConverter;
import java.util.Base64;
import java.math.*;
import java.util.Scanner;
import java.security.spec.KeySpec;
import java.security.*;
import javax.crypto.Cipher;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.Provider;
import java.security.Key;
import java.security.Security;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.spec.RSAPrivateCrtKeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;

public class RSAcryptprop {

public static void main(String[] args){
        try{
        Scanner reader = new Scanner(System.in);
        KeyFactory kF = KeyFactory.getInstance("RSA"); 

        BigInteger valP, valQ, valN, totN, valE, valD, valC, valM, valMD, valsub, valDD, valED, valND, valQE, valPE, valCrtC;

        String valPt, valQt, valEt, valMt;

        //here's the set of starting values, two prime numbers of similar bit length


        System.out.println("Value of P?:");
        valPt = reader.next();
        valP = new BigInteger(valPt);
        System.out.println("Value of Q?:");
        valQt = reader.next();
        valQ = new BigInteger(valQt);


        //then find the value of N and the totient of N

        valN= valQ.multiply(valP);
        valsub = new BigInteger("1");

totN= (valQ.subtract(valsub)).multiply(valP.subtract(valsub));


        System.out.println("Totient of N:" + totN.toString(10));
        System.out.println("Value of E? (must be coprime to totient of N):");
        //E is a number coprime to the totient of N

        valEt = reader.next();
        valE = new BigInteger(valEt);



        //N and E are the public key
        RSAPublicKeySpec pubKeyS;
        pubKeyS = new RSAPublicKeySpec(valN,valE);
        PublicKey pubKey = kF.generatePublic(pubKeyS);
        String pubKeyProp = DatatypeConverter.printBase64Binary(pubKey.getEncoded());
        byte[] encodedPubKey = Base64.getDecoder().decode(pubKeyProp);  

        //then I find the modular inverse of the totient modulus E.
        valD = valE.modInverse(totN);




        valPE = valD.mod(valP.subtract(valsub));
        valQE = valD.mod(valQ.subtract(valsub));
        valCrtC = (valQ.subtract(valsub)).mod(valP);
        //N and D are the private key
        RSAPrivateCrtKeySpec privKeyS;
        privKeyS = new RSAPrivateCrtKeySpec(valN, valE, valD, valP, valQ, valPE, valQE, valCrtC);
        PrivateKey privKey = kF.generatePrivate(privKeyS);
        String privKeyProp = DatatypeConverter.printBase64Binary(privKey.getEncoded());
        byte[] encodedPrivKey = Base64.getDecoder().decode(privKeyProp);

        System.out.println("Value of the message?:");
        valMt = reader.next();

        //M is the message that is being encrypted

        valM = new BigInteger(valMt);



        //now for encryption/decryption
        RSAPublicKeySpec pubKeySD;      
        pubKeySD = kF.getKeySpec(pubKey,RSAPublicKeySpec.class);
        valND = pubKeySD.getModulus();
        RSAPrivateCrtKeySpec privKeySD;
        privKeySD = kF.getKeySpec(privKey,RSAPrivateCrtKeySpec.class);
        valDD = privKeySD.getPrivateExponent();


        //C is the encrypted form of the message

        valED = pubKeySD.getPublicExponent();

        valC= valM.modPow(valED,valND); 

        //now to decode the value of M from the value of C
        valMD = valC.modPow(valDD,valND);


        //M is the message, C is the encoded form, n and e are the public key, n and d are the private key


        System.out.println("Message being encrypted: " + valM);

        System.out.println("Encrypted form of message: " + valC);

        System.out.println("Message after going through decrypting: " + valMD);
        System.out.println();
        System.out.println("Proper Private Key:");
        System.out.println("-----BEGIN RSA PRIVATE KEY-----");
        System.out.println(privKeyProp);
        System.out.println("-----END RSA PRIVATE KEY-----");
        System.out.println("Proper Public Key:");
        System.out.println("-----BEGIN RSA PUBLIC KEY-----");
        System.out.println(pubKeyProp);
        System.out.println("-----END RSA PUBLIC KEY-----");

        }
        catch(NoSuchAlgorithmException e){
        System.err.println("algorithm error");
        }
        catch(InvalidKeySpecException e){
        System.err.println("keyspec error");
        }

    }

}
Ryuluce
  • 21
  • 6
  • Is there a particular reason you want to write the encryption and decryption code yourself, instead of getting the crypto API to do it? – user253751 Mar 25 '15 at 03:11
  • Well, this code is mainly for A) code practice and B) demonstration for my digital media class. Besides, I don't know how to use the crypto API anyways. If it's that helpful, I would appreciate advice on it. – Ryuluce Mar 25 '15 at 03:12
  • I would recommend that you learn how to use the crypto API, rather than trying to do any cryptography yourself - unless your project is focused on implementing cryptogaphy. (This also applies to all things, not just cryptography - if someone else has done it, and you're not trying to learn how to do it, using theirs is probably much easier) – user253751 Mar 25 '15 at 03:20
  • Well that was kind of my intention with this program. I was self-studying implementation. But I don't really need to go much farther I guess. But I don't know where to start with the crypto API. Can you please give me some direction (I have looked at the documentation on oracle's site, but I'm just lost reading it). – Ryuluce Mar 25 '15 at 03:23
  • You mean [RSAPublicKeySpec](http://docs.oracle.com/javase/7/docs/api/java/security/spec/RSAPublicKeySpec.html) which takes a modulus and exponent as BigInteger? – Artjom B. Mar 25 '15 at 09:27
  • Thanks ArtJom, that's what I was looking for (I didn't know it was in the security library rather than the javax.crypto library). But I've been trying to implement it and I have a new issue, any ideas why? – Ryuluce Mar 25 '15 at 22:46
  • I gather you are unfamiliar with Java exceptions. The [Java Tutorial section on exceptions](https://docs.oracle.com/javase/tutorial/essential/exceptions/) should help. – President James K. Polk Mar 25 '15 at 22:49
  • Hey, thanks! I've caught the exceptions and now have the code running. But... it's not encrypting and decrypting properly... – Ryuluce Mar 25 '15 at 23:23
  • The two-arg ctor for `RSAPrivateKeySpec` takes (modulus, privateExponent) which in your terms is (valN, valD). Note that even if you get this to correctly output the input value, "pure" PKC (not hybrid symmetric/PKC) is of very limited use, non-CRT-private RSA is much slower than needed, and "textbook" (non-padded) RSA is in practice usually not secure, as described briefly in wikipedia and detailed in probably a dozen questions on security.SE and crypto.SE. – dave_thompson_085 Mar 26 '15 at 05:54
  • So, should I use RSAPrivateCrtKeySpec instead? – Ryuluce Mar 26 '15 at 12:01
  • Hey, thanks dave, and everyone. I think I'm close to what I want. But I don't know how to retrieve the key from the byte array. Help? More details are in the updated question. – Ryuluce Mar 26 '15 at 21:43

0 Answers0