I am having a java class in which RSA Encryption
is performed for the passed String
value. getting encoded value as lengthy.
Input String: justin
RSA Encoded value as output: .eJwdy00OwiAQBtC7zFqS4Ufg8zLNUIaGDZjaxoXx7ja-_fvQc751X3qlB2Wp4kKCU47BZy4A7pa9uuitqNKN5t63PuToY1vO87-wri02gSlSiwloMKhcDZxoSClDAl-zj9exjHkFy0zfH5pUI3w.YfvMdQ.GcmMQuY3BN33JATAfFB3ZyeXO8U
RSA Encryption Code:
String username="justin";
String encrypteduser=getEncryptedPassword(username);
System.out.println("encrypteduser! " encrypteduser);
public String getEncryptedPassword(String plainTextPassword)
{
String result="";
try {
result= getEncryptedPasswd(plainTextPassword);
log.info("result: " result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
protected String getEncryptedPasswd(String plain) throws Exception {
try {
InputStream is = new ByteArrayInputStream(getCertificate().getBytes());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
PublicKey pubKey = cert.getPublicKey();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte cipherBytes[] = cipher.doFinal(plain.getBytes());
String encrypted = Base64.getEncoder().encodeToString(cipherBytes);
return encrypted;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
private String getCertificate() {
String certStr = "-----BEGIN CERTIFICATE-----\n"
"MIIGgDCCBWigAwIBAgIKMvrulAAAAARG5DANBgkqhkiG9w0BAQsFADBbMRMwEQYK"
"CZImiZPyLGQBGRYDbmV0MRkwFwYKCZIm"
"-----END CERTIFICATE-----";
return certStr;
}
and my goal here is that wanna compress RSA Encoded value into shorten one.
I hope after conversion(RSA
to UTF-8
) will get some shortened value.
Note: looking for some compression to the Encoded value if UTF-8
conversion not helps.
Is there any way to achieve this in java 8?
CodePudding user response:
Your cipher text appears to be already UTF-8–encoded. It's base-64–encoded; base-64 uses only US-ASCII characters, and US-ASCII encoding is a subset of UTF-8 encoding.
I believe you are not asking for what you want. Do you want shorter cipher text? If so, UTF-8 has nothing to do with that.
RSA cipher text has a length equal to the modulus of the RSA key. (This also imposes an upper bound on the plain text length.) The key size is chosen according to security requirements. Nowadays 3072 bits or maybe 2048 bits is typical. With those key lengths, the shortest text encoding generally supported is 512 or 342 characters, respectively. (There are some less common binary-to-text encodings that could get it down to 480 or 320 characters, respectively, but they will cause problems in URLs and other contexts because they use more symbols.)
If you want a shorter cipher text, use a different encryption algorithm. For public key cryptography, elliptic curve algorithms give the same level of security with shorter keys (as far as we know, anyway). This means your plain text and cipher text will be shorter. Or, perhaps a symmetric algorithm might work in your scheme. Depending on the mode, these can output cipher text the same length as the plain text (although that leaks information about the plain text and might compromise security).
Cryptographic operations result in strings bytes that can have any value in any sequence. I'm not aware of any single-byte character encodings that map every value to a character, and there isn't a multi-byte character encoding that maps every byte sequence to a character. Taking these facts together, you'll always require something like base-64 encoding to convert your cipher text to actual characters. So your text will be 33% longer on average.
CodePudding user response:
To remain largely compatible with US-ASCII, a 7 bit character code, UTF-8 only encodes single byte characters using the lower 7 bits as well. That means that the same 95 printable characters are present using a single byte in UTF-8 and ASCII. Moving to two or higher byte UTF-8 encoding takes more space, so that's not useful at all.
So basically you can use any text encoding for ASCII that exists. You are already using base 64 which is already pretty dense. However, you could e.g. also use Z85 which can contain more binary data, with the disadvantage that it is not a power of two, so the encoding / decoding (or base conversion) will be somewhat trickier and costly. Furthermore, a base 85 encoding only encodes around 6.41 bits per character over 6 bits for base 64, so the return is minimal (around 6.82%).
You should always indicate the encoding when performing conversion. However,UTF-8 is fully compatible to ASCII for base 64 and Z85 as mentioned before. So I'd indicate encoding StandardCharsets.US_ASCII
, not UTF_8
as others no doubt will propose.
Just to be sure: if you are able to handle bytes then no encoding is always better than performing some conversion to a less efficient representation.
The only real way of creating smaller ciphertext is to look at hybrid encryption. Just encrypting or deriving a symmetric key with RSA and use that to encrypt a small string such as a password is not really feasible. An RSA ciphertext consist of (largely) random bytes, so at least on average is not possible to compress these bytes any further.
However, you could take a look at ECIES, possibly with a compressed ephemeral public key. Then you could use 33 bytes for the public key (of e.g. curve type P256, for a 128 bit strength) and a specific maximum password size for the password itself, encrypted with e.g. AES-CTR. You should use a static sized encoding for the passwords, or you could leak the password size.