I am trying to create a JWT from private key in java. The private key is in a file.
Here is my method.
protected String prepareJWT() throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
String poyntPrivateKey = this.getPoyntPrivateKey();
byte[] privateBytes = poyntPrivateKey.getBytes();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
JWSSigner signer = new RSASSASigner((RSAPrivateKey) privateKey);
...
}
I get an Exception at keyFactory.generatePrivate(keySpec); with message:
java.security.InvalidKeyException: invalid key format
and here is getPoyntPrivateKey()
protected String getPoyntPrivateKey() {
File file = new File("resources/poynt_api_private_key.txt");
StringBuilder privateKeyBuilder = new StringBuilder();
String privateKey = privateKeyBuilder.toString();
try {
FileReader fr = new FileReader(file);
Scanner scanner = new Scanner(fr);
while(scanner.hasNextLine()) {
privateKeyBuilder.append(scanner.nextLine() + "\r");
}
scanner.close();
privateKey = privateKeyBuilder.toString();
} catch (Exception e) {
privateKey = "Error";
} finally {
}
return privateKey;
}
Here you go (using com.nimbusds.jwt.* and org.bouncycastle.openssl.*):
private static String getJWT() throws Exception{
File f = new File(privateKeyFile);
InputStreamReader isr = new InputStreamReader(new FileInputStream(f));
PEMParser pemParser = new PEMParser(isr);
Object object = pemParser.readObject();
PEMKeyPair kp = (PEMKeyPair) object;
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
RSAPrivateKey privateKey = (RSAPrivateKey) converter.getPrivateKey(kp.getPrivateKeyInfo());
pemParser.close();
// Create RSA-signer with the private key
JWSSigner signer = new RSASSASigner(privateKey);
// Prepare JWT with claims set
JWTClaimsSet claimsSet = new JWTClaimsSet();
claimsSet.setSubject(applicationId);
claimsSet.setAudience(Arrays.asList(apiEndpoint));
claimsSet.setIssuer(applicationId);
claimsSet.setExpirationTime(new Date(new Date().getTime() + 360 * 1000));
claimsSet.setIssueTime(new Date(new Date().getTime()));
claimsSet.setJWTID(UUID.randomUUID().toString());
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
// Compute the RSA signature
signedJWT.sign(signer);
String s = signedJWT.serialize();
return s;
}
Related
I am generating Asymmetric public key and private using the code below.
public static KeyPair generateRSAKkeyPair()
throws Exception {
SecureRandom secureRandom = new SecureRandom();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(
2048, secureRandom);
return keyPairGenerator
.generateKeyPair();
}
public static byte[] do_RSAEncryption(
String plainText,
PublicKey publicKey)
throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(
Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(
plainText.getBytes());
}
public static String do_RSADecryption(
byte[] cipherText,
PrivateKey privateKey)
throws Exception {
Cipher cipher = Cipher.getInstance(RSA);
cipher.init(Cipher.DECRYPT_MODE,
privateKey);
byte[] result = cipher.doFinal(cipherText);
return new String(result);
}
public static PublicKey getKey(String key) {
try {
byte[] byteKey = Base64.getDecoder().decode(key.getBytes());
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(X509publicKey);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static PrivateKey getPrivateKey(String key) {
try {
byte[] byteKey = Base64.getDecoder().decode(key.getBytes());
X509EncodedKeySpec X509publicKey = new X509EncodedKeySpec(byteKey);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(X509publicKey);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
This works as expected.
String plainText = "This is the PlainText. I want to Encrypt using RSA.";
byte[] cipherText = do_RSAEncryption(plainText, keypair.getPublic());
String decryptedText = do_RSADecryption(cipherText, keypair.getPrivate());
Now, I am storing the generated the generated public key and private key in a string and trying to encrypt and decrypt and it is failing.
String base64EncodedEncryptionKey = DatatypeConverter.printBase64Binary(keypair.getPublic().getEncoded()));
String base64EccodedDecryptionKey = DatatypeConverter.printBase64Binary(keypair.getPrivate().getEncoded()));
PublicKey pubKey = getKey(base64EncodedEncryptionKey);
byte[] cipherText1 = do_RSAEncryption(plainText, pubKey);
System.out.println("Encrypted Text ===> "+ DatatypeConverter.printHexBinary(cipherText1));
PrivateKey privateKey = getPrivateKey(base64EccodedDecryptionKey);
String decryptedText1 = do_RSADecryption(cipherText1,privateKey);
System.out.println("DecryptedText ====>>> "+decryptedText1);
Error:-
java.security.spec.InvalidKeySpecException: Only RSAPrivate(Crt)KeySpec and PKCS8EncodedKeySpec supported for RSA private keys
at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:389)
at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:247)
at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.getPrivateKey(Asymmetric.java:96)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.main(Asymmetric.java:135)
Exception in thread "main" java.security.InvalidKeyException: No installed provider supports this key: (null)
at java.base/javax.crypto.Cipher.chooseProvider(Cipher.java:930)
at java.base/javax.crypto.Cipher.init(Cipher.java:1286)
at java.base/javax.crypto.Cipher.init(Cipher.java:1223)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.do_RSADecryption(Asymmetric.java:68)
at com.apple.ist.alloy.memsqlloader.service.Asymmetric.main(Asymmetric.java:137)
Private keys are encoded with PKCS8EncodedKeySpec. You should replace X509EncodedKeySpec with that.
I am trying to send digitally signed mail using EWS, I have implemented code for signing the mail. The mail gets sent successfully but the content of it is empty, following is the code, what am I doing wrong. any help is appreciated.
**
public static EmailMessage sign(EmailMessageContent messageContent)
throws Exception {
EmailMessage signedMessage = messageContent.getEmailMessage();
char[] smimePw = messageContent.getPassword().toCharArray();
CMSProcessableByteArray cmsProcessableByteArray = new CMSProcessableByteArray(signedMessage.getBody().toString().getBytes());
try{
if(signer==null){
signer = getSigner(messageContent, smimePw);
}
CMSSignedData cmsSignedData = signer.generate(cmsProcessableByteArray,"BC");
MimeContent content = new MimeContent("UTF-8", cmsSignedData.getEncoded());
signedMessage.setMimeContent(content);
signedMessage.setItemClass("IPM.Note.SMIME");
}catch(Exception exp){
LOGGER.error("In sign() method", exp);
}
return signedMessage;
}
private static CMSSignedDataGenerator getSigner(EmailMessageContent messageContent,
char[] smimePw)
throws KeyStoreException, IOException, NoSuchAlgorithmException,
CertificateException, Exception, UnrecoverableKeyException,
InvalidAlgorithmParameterException, NoSuchProviderException,
CertStoreException, SMIMEException {
InputStream is = null;
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
try{
is = getCertFile(messageContent.getCertFile());
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(is, smimePw);
String keyAlias = getAlias(keystore);
if (keyAlias == null) {
System.err.println();
throw new Exception("Can't find an alias.");
}
PrivateKey privateKey = (PrivateKey)keystore.getKey(keyAlias, smimePw);
if (privateKey == null) {
throw new Exception("No private key for alias: " + keyAlias);
}
Certificate[] certificates = getCertificates(keystore, keyAlias);
//Certificate[]
gen.addSigner(privateKey, (X509Certificate) certificates[0], CMSSignedGenerator.DIGEST_MD5);
List<Certificate> certList = Arrays.asList(certificates);
CertStore certs = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certList), "BC");
gen.addCertificatesAndCRLs(certs);
}finally{
if(is!=null)is.close();
}
return gen;
}
**
Dears,
I need help to understand why decryptString doesn't work and throw "java.security.InvalidKeyException: Need RSA private or public key". When call encrypt method, i use public key by the private key/certificate.
Thanks for any help!
public class KeysHandler {
/***
* Generate and store in AndroidKeyStore a security KeyPair keys.
* #param alias - Alias to create the key.
* #return KeyPair object with: private and public key.
*/
public static KeyPair generateKeyPair(String alias) {
KeyPair kp = null;
if (alias != null) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
kpg.initialize(new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_SIGN |
KeyProperties.PURPOSE_VERIFY |
KeyProperties.PURPOSE_ENCRYPT |
KeyProperties.PURPOSE_DECRYPT)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
.build());
kp = kpg.generateKeyPair();
} catch (NoSuchProviderException | NoSuchAlgorithmException | InvalidAlgorithmParameterException ex) {
kp = null;
}
}
return kp;
}
public static String encryptString(String alias, String textToEncrypt) {
String cipheredText = null;
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
// Encrypt the text
if(textToEncrypt != null && textToEncrypt.length() > 0) {
Cipher input = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
input.init(Cipher.ENCRYPT_MODE, privateKeyEntry.getCertificate().getPublicKey());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
CipherOutputStream cipherOutputStream = new CipherOutputStream(
outputStream, input);
cipherOutputStream.write(textToEncrypt.getBytes("UTF-8"));
cipherOutputStream.close();
byte[] vals = outputStream.toByteArray();
cipheredText = Base64.encodeToString(vals, Base64.DEFAULT);
}
} catch (Exception e) {
cipheredText = null;
}
return cipheredText;
}
public static String decryptString(String alias, String cipheredText) {
String clearText = null;
try {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
output.init(Cipher.DECRYPT_MODE, privateKeyEntry.getPrivateKey());
CipherInputStream cipherInputStream = new CipherInputStream(
new ByteArrayInputStream(Base64.decode(cipheredText, Base64.DEFAULT)), output);
ArrayList<Byte> values = new ArrayList<>();
int nextByte;
while ((nextByte = cipherInputStream.read()) != -1) {
values.add((byte)nextByte);
}
byte[] bytes = new byte[values.size()];
for(int i = 0; i < bytes.length; i++) {
bytes[i] = values.get(i).byteValue();
}
clearText = new String(bytes, 0, bytes.length, "UTF-8");
} catch (Exception e) {
clearText = null;
}
return clearText;
}
}
Try omitting the cipher provider:
Cipher output = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Secondly, you can instantiate the provider first to make sure that works, then pass it along as the second argument to Cipher.getInstance(). The second argument can be either a String (provider name) or a Provider (object). Using the second might make debugging easier.
I get Exception in thread "main"
javax.crypto.BadPaddingException: Decryption error in the RSA encryption/decryption.
My java classes are Client,Server and go like this
Client
public class Client {
private static SecretKeySpec AES_Key;
private static String key;
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException {
Socket mySocket = null;
PrintWriter out = null;
BufferedReader in = null;
try {
mySocket = new Socket("localhost", 4443);
out = new PrintWriter(mySocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
} catch (UnknownHostException e) {
System.err.println("Don't know about host");
System.exit(1);
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: localhost.");
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String fromServer;
String fromUser, m1;
byte[] input;
System.out.println("Client run ");
int cnt = 0;
while (true) {
// fromServer = in.readLine();
m1 = in.readLine();
//input=in.readLine().getBytes();
if (m1 != null && cnt < 1) {
cnt++;
byte[] m = new BASE64Decoder().decodeBuffer(m1);
PrivateKey privKey = readKeyFromFile("/privateClient.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] plaintext_decrypted = cipher.doFinal(m);
fromServer = new String(plaintext_decrypted, "ASCII");
AES_Key = new SecretKeySpec(fromServer.getBytes(), "AES");
System.out.println("RSA communication ends");
System.out.println("AES communication established");
}
System.out.println("type message :");
//Encrypt msg to send
Cipher AES_Cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
fromUser = stdIn.readLine();
AES_Cipher.init(Cipher.ENCRYPT_MODE, AES_Key);
byte plaintext[] = fromUser.getBytes();
byte[] final_plaintext = AES_Cipher.doFinal(plaintext);
String msg = new BASE64Encoder().encode(final_plaintext);
if (fromUser != null) {
out.println(fromUser);
} else {
break;
}
fromServer = in.readLine();
if (fromServer != null) {
// Decrypt the message received
AES_Cipher.init(Cipher.DECRYPT_MODE, AES_Key);
input = new BASE64Decoder().decodeBuffer(fromServer);
byte plaintext_decrypted[] = AES_Cipher.doFinal(input);
fromServer = new String(plaintext_decrypted, "ASCII");
System.out.println("Client receive :" + fromServer);
} else {
break;
}
}
out.close();
in.close();
stdIn.close();
mySocket.close();
}
static PrivateKey readKeyFromFile(String keyFileName) throws IOException {
InputStream in
= Client.class.getResourceAsStream(keyFileName);
ObjectInputStream oin
= new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey privKey = fact.generatePrivate(keySpec);
return privKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
static PublicKey readKeyFromFilePb(String keyFileName) throws IOException {
InputStream in
= Client.class.getResourceAsStream(keyFileName);
ObjectInputStream oin
= new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
static byte[] rsaDecrypt(byte[] in) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
PrivateKey privKey = readKeyFromFile("/publicServer.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privKey);
byte[] cipherData = cipher.doFinal(in);
return cipherData;
}
static byte[] rsaEncrypt(byte[] data) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
PublicKey pubKey = readKeyFromFilePb("/privateClient.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(data);
return cipherData;
}
private String toHexString(byte[] block) {
StringBuffer buf = new StringBuffer();
int len = block.length;
for (int i = 0; i < len; i++) {
byte2hex(block[i], buf);
if (i < len - 1) {
buf.append(":");
}
}
return buf.toString();
}
/*
* Converts a byte to hex digit and writes to the supplied buffer
*/
private void byte2hex(byte b, StringBuffer buf) {
char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F'};
int high = ((b & 0xf0) >> 4);
int low = (b & 0x0f);
buf.append(hexChars[high]);
buf.append(hexChars[low]);
}
}
Server
public class Server {
private static SecretKeySpec AES_Key;
private static final String key = "1234567890ABCDEF";
public static PublicKey keycl;
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InstantiationException, IllegalAccessException {
AES_Key = new SecretKeySpec(key.getBytes(), "AES");
//System.out.println(AES_Key);
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4443);
} catch (IOException e) {
System.err.println("Could not listen on port: 4443.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String inputLine, outputLine;
System.out.println("Server run ");
int cnt = 0;
byte final_plaintext[];
byte[] AES = key.getBytes();
PublicKey pubKey = readKeyFromFile("/publicClient.key");
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
final_plaintext = cipher.doFinal(AES);
String m = new BASE64Encoder().encode(final_plaintext);
System.out.println(m);
out.println(m);
while ((inputLine = in.readLine()) != null) {
cnt++;
Cipher AES_Cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
AES_Cipher.init(Cipher.DECRYPT_MODE, AES_Key);
byte[] input = new BASE64Decoder().decodeBuffer(inputLine);
//System.out.println(input);
byte plaintext_decrypted[] = AES_Cipher.doFinal(input);
inputLine = new String(plaintext_decrypted, "UTF-8");
System.out.println("Server receive : " + inputLine);
System.out.println("type message :");
outputLine = stdIn.readLine();
AES_Cipher.init(Cipher.ENCRYPT_MODE, AES_Key);
byte plaintext[] = outputLine.getBytes();
final_plaintext = AES_Cipher.doFinal(plaintext);
String msg = new BASE64Encoder().encode(final_plaintext);
out.println(msg);
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
public static PublicKey readKeyFromFile(String keyFileName) throws IOException {
InputStream in
= Server.class.getResourceAsStream(keyFileName);
ObjectInputStream oin
= new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
public static byte[] rsaEncrypt(byte[] data) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
PublicKey pubKey = readKeyFromFile("/privateServer.key");
System.out.println(pubKey);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(data);
return cipherData;
}
public static byte[] rsaDecrypt(byte[] data) throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
PublicKey pubKey = readKeyFromFile("/publicClient.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(data);
return cipherData;
}
private static String toHexString(byte[] block) {
StringBuffer buf = new StringBuffer();
int len = block.length;
for (int i = 0; i < len; i++) {
byte2hex(block[i], buf);
if (i < len - 1) {
buf.append(":");
}
}
return buf.toString();
}
/*
* Converts a byte to hex digit and writes to the supplied buffer
*/
private static void byte2hex(byte b, StringBuffer buf) {
char[] hexChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F'};
int high = ((b & 0xf0) >> 4);
int low = (b & 0x0f);
buf.append(hexChars[high]);
buf.append(hexChars[low]);
}
}
Generate keys
public class KeyPair {
public KeyPair() {
}
public void GenerateKey(String name) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
java.security.KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
System.out.println(pub);
String publ="public"+name+".key";
String priva="private"+name+".key";
saveToFile(publ, pub.getModulus(),
pub.getPublicExponent());
saveToFile(priva, priv.getModulus(),
priv.getPrivateExponent());
}
public void saveToFile(String fileName,
BigInteger mod, BigInteger exp) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
oout.close();
}
}
public PublicKey readKeyFromFile(String keyFileName) throws IOException {
InputStream in
= KeyPair.class.getResourceAsStream(keyFileName);
ObjectInputStream oin
= new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
}
public class Main {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
KeyPair kpC = new KeyPair();
KeyPair kpS = new KeyPair();
kpS.GenerateKey("Server");
kpC.GenerateKey("Client");
}
}
I found it. It was at the
Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
at the client code. Before it was (Cipher cipher = Cipher.getInstance("RSA");).
At First,please forgive my poor English level。And thanks for your solution!
I am new with bouncycastle。 I have succssed used it creating PGPkeypair ,get PGPPublickKey and secretKey 。I also use secretKey to encrypt a txt file,but I can't signed and decrypt it 。My codes are almost from the org.bouncycastle.openpgp.example and I dont know where the problem is
Here is my codes:
1,Create PGPKeyPair and get PGPPublickey,secretKey and save them:
public static PGPPublicKey generateKeyPair() throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA", "BC");
keyGen.initialize(1024, new SecureRandom());
int algorithm = PGPPublicKey.RSA_GENERAL;
PGPKeyPair pkp=new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
Security.addProvider(new BouncyCastleProvider());
Security.addProvider(new BouncyCastlePQCProvider());
// 生成RSA密钥对
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
kpg.initialize(4096);
KeyPair kp = kpg.generateKeyPair();
// 转为PGP密钥对
JcaPGPKeyPair pgpKeyPair = new JcaPGPKeyPair(PGPPublicKey.RSA_GENERAL,
kp, new Date());
// 用户标识一般使用email
String identity = "fad#163.com";
// 用来保护密钥的密码
char[] passPhrase = "123456".toCharArray();
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(HashAlgorithmTags.SHA1);
PGPContentSignerBuilder certSignerBuilder = new JcaPGPContentSignerBuilder(
pgpKeyPair.getPublicKey().getAlgorithm(),
HashAlgorithmTags.SHA1);
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
SymmetricKeyAlgorithmTags.AES_256, sha1Calc,0x90).setProvider("BC").build(
passPhrase);
// 生成PGP密钥
PGPSecretKey secretKey = new PGPSecretKey(
PGPSignature.DEFAULT_CERTIFICATION, pgpKeyPair, identity,
sha1Calc, null, null, certSignerBuilder, keyEncryptor);
// 保存PGP密钥到asc文件
File externalStorageDirectory = Environment
.getExternalStorageDirectory();
String path = externalStorageDirectory.toString();
OutputStream secretOut = new ArmoredOutputStream(new FileOutputStream(
path + "/SecretKey.asc"));
secretKey.encode(secretOut);
secretOut.close();
// 保存PGP公钥到asc文件
OutputStream publicOut = new ArmoredOutputStream(new FileOutputStream(
path + "/PublicKey.asc"));
PGPPublicKey key = secretKey.getPublicKey();
key.encode(publicOut);
publicOut.close();
return key;
}
2,Use SignedFileProcessor.java to encrypt file and decryptfile:
public class KeyBasedLargeFileProcessor{
public static void decryptFile(
String inputFileName,
String keyFileName,
char[] passwd,
String defaultFileName)
throws IOException, NoSuchProviderException
{
InputStream in = new BufferedInputStream(new FileInputStream(inputFileName));
InputStream keyIn = new BufferedInputStream(new FileInputStream(keyFileName));
decryptFile(in, keyIn, passwd, defaultFileName);
keyIn.close();
in.close();
}
/**
* decrypt the passed in message stream
*/
public static void decryptFile(
InputStream in,
InputStream keyIn,
char[] passwd,
String defaultFileName)
throws IOException, NoSuchProviderException
{
in = PGPUtil.getDecoderStream(in);
try
{
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
//
// the first object might be a PGP marker packet.
//
if (o instanceof PGPEncryptedDataList)
{
enc = (PGPEncryptedDataList)o;
}
else
{
enc = (PGPEncryptedDataList)pgpF.nextObject();
}
//
// find the secret key
//
Iterator it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(keyIn));
while (sKey == null && it.hasNext())
{
pbe = (PGPPublicKeyEncryptedData)it.next();
sKey = PGPExampleUtil.findSecretKey(pgpSec, pbe.getKeyID(), passwd);
}
if (sKey == null)
{
throw new IllegalArgumentException("secret key for message not found.");
}
InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider("BC").build(sKey));
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
PGPCompressedData cData = (PGPCompressedData)plainFact.nextObject();
InputStream compressedStream = new BufferedInputStream(cData.getDataStream());
PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream);
Object message = pgpFact.nextObject();
if (message instanceof PGPLiteralData)
{
PGPLiteralData ld = (PGPLiteralData)message;
String outFileName = ld.getFileName();
if (outFileName.length() == 0)
{
outFileName = defaultFileName;
}
InputStream unc = ld.getInputStream();
OutputStream fOut = new BufferedOutputStream(new FileOutputStream(outFileName));
Streams.pipeAll(unc, fOut);
fOut.close();
}
else if (message instanceof PGPOnePassSignatureList)
{
throw new PGPException("encrypted message contains a signed message - not literal data.");
}
else
{
throw new PGPException("message is not a simple encrypted file - type unknown.");
}
if (pbe.isIntegrityProtected())
{
if (!pbe.verify())
{
System.err.println("message failed integrity check");
}
else
{
System.err.println("message integrity check passed");
}
}
else
{
System.err.println("no message integrity check");
}
}
catch (PGPException e)
{
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
public static void encryptFile(
String outputFileName,
String inputFileName,
String encKeyFileName,
boolean armor,
boolean withIntegrityCheck)
throws IOException, NoSuchProviderException, PGPException
{
OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFileName));
PGPPublicKey encKey = PGPExampleUtil.readPublicKey(encKeyFileName);
encryptFile(out, inputFileName, encKey, armor, withIntegrityCheck);
out.close();
}
public static void encryptFile(
OutputStream out,
String fileName,
PGPPublicKey encKey,
boolean armor,
boolean withIntegrityCheck)
throws IOException, NoSuchProviderException
{
if (armor)
{
out = new ArmoredOutputStream(out);
}
try
{
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(new JcePGPDataEncryptorBuilder(PGPEncryptedData.AES_256).setWithIntegrityPacket(withIntegrityCheck).setSecureRandom(new SecureRandom()).setProvider("BC"));
cPk.addMethod(new JcePublicKeyKeyEncryptionMethodGenerator(encKey).setProvider("BC"));
OutputStream cOut = cPk.open(out, new byte[1 << 16]);
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
PGPCompressedData.ZIP);
PGPUtil.writeFileToLiteralData(comData.open(cOut), PGPLiteralData.BINARY, new File(fileName), new byte[1 << 16]);
comData.close();
cOut.close();
if (armor)
{
out.close();
}
}
catch (PGPException e)
{
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
}
3,Here are my test code:
private void test() {
File storageDirectory = Environment.getExternalStorageDirectory();
final String opath = storageDirectory.toString();
final File publcKeyFile = new File(storageDirectory, "PublicKey.asc");
if(!publcKeyFile.exists()){
try {
OpenGPGUtil.generateKeyPair();
} catch (Exception e) {
e.printStackTrace();
}
}else {
System.out.println("密钥存在");
}
final File secretKeyFile = new File(storageDirectory, "SecretKey.asc");
final File enFile = new File(storageDirectory, "s.txt");
final File file = new File(storageDirectory, "x.txt");
final File deFile = new File(storageDirectory, "ss.txt");
final String publcKeyfilePath = publcKeyFile.toString();
final String secretKeyFilePath = secretKeyFile.toString();
final String enFilePath = enFile.toString();
final String filePath = file.toString();
final String deFilePath = deFile.toString();
new Thread(new Runnable() {
#Override
public void run() {
try {
KeyBasedLargeFileProcessor.encryptFile(enFilePath,
filePath, publcKeyfilePath, true, true);
// KeyBasedLargeFileProcessor.decryptFile(enFilePath,
// secretKeyFilePath, "123456".toCharArray(),
// deFilePath);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
Here are three line annotation,if I erase them Eclipse's logcat will show:
/System.err(7498): java.io.FileNotFoundException:
/x.txt: open failed: EROFS (Read-only file system)
System.err(7498): at libcore.io.IoBridge.open(IoBridge.java:409)
System.err(7498): at java.io.FileOutputStream
<init(FileOutputStream.java:88)
System.err(7498): at java.io.FileOutputStream
.<init> (FileOutputStream.java:128)
System.err(7498): at java.io.FileOutputStream
.<init>(FileOutputStream.java:117)
System.err(7498): at com.example.opengpgs.KeyBasedLargeFileProcessor.
decryptFile(KeyBasedLargeFileProcessor.java:147)
System.err(7498): at com.example.opengpgs.KeyBasedLargeFileProcessor
.decryptFile(KeyBasedLargeFileProcessor.java:69)
System.err(7498): at com.example.opengpgs.MainActivity$1.
run(MainActivity.java:62)
System.err(7498): at java.lang.Thread.run(Thread.java:841)
System.err(7498): Caused by: libcore.io.ErrnoException:
open failed: EROFS (Read-only file system)
System.err(7498): at libcore.io.Posix.open(Native Method)
System.err(7498): at libcore.io.BlockGuardOs.
open(BlockGuardOs.java:110)
System.err(7498): at libcore.io.IoBridge.open(IoBridge.java:393)
System.err(7498): ... 7 more
IInputConnectionWrapper(7498): getCursorCapsMode on
inactive InputConnection
From the error it seems your filesystem is read-only but you are trying to write in it to the file x.txt