Мне нужно зашифровать пароль на веб-сайте с помощью открытого ключа. Открытый ключ доставляется через веб-службу Java с информацией: Ключ - это ключ RSA для использования с алгоритмом RSA/ECB/PKCS1Padding. Открытый ключ поставляется в виде JSON в виде:Java RSA/ECB/PKCS1Padding encryption with .NET
{
"kid":"PWD",
"kty":"RSA",
"use":"enc",
"n":"MTA0OTgzNjg0OTMxMzE2NjkwNTU4Mjg3NDIwMDg1NTY0ODEyMjg1MDk2NTcwNzU5NDIzNzM0O
DA3OTA2MzA0MDczNTU0NDQ2Njg3ODY2ODk2NTk0NjYzNTAxMzg0NzE1OTExMjA0MjU1MzMzOTIzMjA
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
zcwMjA3MzQxOTcwNzc4NDAwNzM3MTY2NDMyNzIwNjMwMDQwOTMwOTQ0MTA2OTE1NDEzMDAwNTMyMTE
5ODM0MTA2MjAzMDIyODEwMjYyMDM3MDQ0NzkxNzIzNTU1MjQyNjYxMzE2ODc4OTc5NzY1OTgzMjg4M
zQ0NDc3OTYwNTg3MzE2NTUwMDgx",
"e":"NjU1Mzc"
}
Я пытался шифровать пароль с помощью открытого ключа, но ключ генерируется не является правильным. Вот мой код:
encryptedPassword = EncrypIt("Password01", "MTA1MzQxNzIwODA3NjUwNzg5ND
Y4ODU2Mjc0NDA3ODIwMjQ1ODQ5NDE1MDk1MDIzMTM3MjM0NzAwNzYzNjc2MTgwNjg3ODMxMjA3
NTY0NTcxMjg2MzM4NjQ1NzEwMDcyMjY2MTQyNDIzMTczMjkwMDk0MTc0MTA5MTc5MzI0NjYwMjQ4NzI3NzM0MTQ5NDY0MjUwODkwO
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
c2OTAzNjc3NzQzODM3NzM0MjE2ODM0NjY4MjM4MTQ0OTA3MDQ3MTk1Njc1NzU3OTE2NjEyNzkzMzM2MzI3MDUyNjg0NDI5NDExNjI
2MzA0MzM5", "NjU1Mzc");
public static string EncrypIt(string password, string publicKey, string exponent)
{
UnicodeEncoding ByteConverter = new UnicodeEncoding();
byte[] publicKeyByte = ByteConverter.GetBytes(publicKey);
byte[] passwordByte = ByteConverter.GetBytes(password);
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
RSAParameters RSAKeyInfo = new RSAParameters();
RSAKeyInfo = RSA.ExportParameters(false); //Export only public key
//Set RSAKeyInfo to the public key values.
RSAKeyInfo.Modulus = publicKeyByte;
//RSAKeyInfo.Exponent = exponentBytes; //I tried to set exponent but I have an error
RSA.ImportParameters(RSAKeyInfo);
byte[] encryptedPassword = RSA.Encrypt(passwordByte, false);
return Convert.ToBase64String(encryptedPassword);
}
(открытый ключ отличается между JSON и мой код, но не обращайте на это внимания, я просто скопированную информацию из различных источников)
- зашифрованный пароль Я получил слишком много: зашифрованный пароль должен быть 172 символа (я знаю, потому что у меня есть небольшая программа Java, которая позволяет мне правильно шифровать пароли), но я получаю 1100 символов.
- Я не использую экспонента: Должен ли я?
- Могу ли я использовать JSON для непосредственной настройки RSACryptoServiceProvider правильно?
Ответ от owlstead помог мне получить зашифрованный пароль с правильным размером строки, но сервис с помощью зашифрованной строки отклонить его с сообщением: javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes
Я otained код программы Java который делает правильное шифрование (см. ниже). Мне нужно добиться того же шифрования с помощью .NET.
public class EncryptionServiceImpl
{
private static final Charset UTF8 = Charset.forName("UTF-8");
@Resource(name = "briqueAuthentificationClient")
private BriqueAuthentificationClientImpl briqueAuthentificationClient;
protected static final String ALGORITHM_RSA = "RSA";
protected static final String TRANSFORMATION_RSA_ECB_PKCS1PADDING = "RSA/ECB/PKCS1Padding";
private static final Logger LOG = LoggerFactory.getLogger(EncryptionServiceImpl.class);
public EncryptionServiceImpl() {
LOG.info("constructeur EncryptionServiceImpl");
}
/**
* @param briqueAuthentificationClient the briqueAuthentificationClient to set
*/
public void setBriqueAuthentificationClient(final BriqueAuthentificationClientImpl briqueAuthentificationClient) {
this.briqueAuthentificationClient = briqueAuthentificationClient;
}
public String encrypt(final String input) throws GeneralSecurityException {
if (StringUtils.isNotBlank(input)) {
final CertificateDto certificate = this.briqueAuthentificationClient.getCurrentCertificate();
if (certificate != null) {
return new String(this.encryptAndEncode(input.getBytes(), certificate), EncryptionServiceImpl.UTF8);
} else {
throw new RuntimeException("Certificate is null");
}
}
return null;
}
protected byte[] encryptAndEncode(final byte[] input, final CertificateDto currentCertificate)
throws GeneralSecurityException {
// Création de la clé publique
final PublicKey publicKey = this.buildPublicKey(currentCertificate);
// Chiffre
final byte[] inputEncrypted = this.encrypte(input, publicKey);
// Encode
return this.encodeBase64Url(inputEncrypted);
}
protected PublicKey buildPublicKey(final CertificateDto currentCertificate) throws GeneralSecurityException {
if ("RSA".equals(currentCertificate.getKeyType())) {
return this.buildRSAPublicKey(currentCertificate);
}
LOG.error(String.format("Tentative de création d'une clé publique avec un algorithme non connu [%s]",
currentCertificate.getKeyType()));
return null;
}
protected PublicKey buildRSAPublicKey(final CertificateDto currentCertificate) throws GeneralSecurityException {
final BigInteger modulus = new BigInteger(new String(Base64.decodeBase64(currentCertificate.getModulus()),
EncryptionServiceImpl.UTF8));
final BigInteger publicExponent = new BigInteger(new String(Base64.decodeBase64(currentCertificate
.getPublicExponent()), EncryptionServiceImpl.UTF8));
try {
return KeyFactory.getInstance(ALGORITHM_RSA).generatePublic(new RSAPublicKeySpec(modulus, publicExponent));
} catch (InvalidKeySpecException e) {
throw e;
} catch (NoSuchAlgorithmException e) {
throw e;
}
}
protected byte[] encrypte(final byte[] input, final RSAPublicKeySpec rsaPublicKeySpec)
throws GeneralSecurityException {
PublicKey publicKey;
try {
publicKey = KeyFactory.getInstance(ALGORITHM_RSA).generatePublic(
new RSAPublicKeySpec(rsaPublicKeySpec.getModulus(), rsaPublicKeySpec.getPublicExponent()));
} catch (InvalidKeySpecException e) {
throw e;
} catch (NoSuchAlgorithmException e) {
throw e;
}
return this.encrypte(input, publicKey);
}
protected byte[] encrypte(final byte[] input, final PublicKey publicKey) throws GeneralSecurityException {
try {
final Cipher cipher = Cipher.getInstance(TRANSFORMATION_RSA_ECB_PKCS1PADDING);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(input);
} catch (NoSuchAlgorithmException e) {
throw e;
} catch (NoSuchPaddingException e) {
throw e;
} catch (IllegalBlockSizeException e) {
throw e;
} catch (BadPaddingException e) {
throw e;
}
}
protected byte[] decrypte(final byte[] input, final RSAPrivateKeySpec rsaPrivateKeySpec)
throws GeneralSecurityException {
final BigInteger modulus = rsaPrivateKeySpec.getModulus();
final BigInteger privateExponent = rsaPrivateKeySpec.getPrivateExponent();
try {
final PrivateKey privateKey = KeyFactory.getInstance(ALGORITHM_RSA).generatePrivate(
new RSAPrivateKeySpec(modulus, privateExponent));
final Cipher cipher = Cipher.getInstance(TRANSFORMATION_RSA_ECB_PKCS1PADDING);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(input);
} catch (NoSuchAlgorithmException e) {
throw e;
} catch (NoSuchPaddingException e) {
throw e;
} catch (IllegalBlockSizeException e) {
throw e;
} catch (BadPaddingException e) {
throw e;
} catch (InvalidKeySpecException e) {
throw e;
} catch (InvalidKeyException e) {
throw e;
}
}
protected byte[] encodeBase64Url(final byte[] input) {
return Base64.encodeBase64(input, false);
}
protected byte[] decodeBase64Url(final byte[] input) {
return Base64.decodeBase64(input);
}
/**
* Method to connect to an url
*
* @param httpclient the http connection
* @return the response GetMethod
* @throws OAuthException in cas of connection error
*/
private GetMethod connect(final HttpClient httpclient, final String url) {
final GetMethod httpget = new GetMethod(url);
try {
httpclient.executeMethod(httpget);
} catch (final UnknownHostException e) {
throw new RuntimeException("Connection ERROR - Host could not be determined.", e);
} catch (final IOException e) {
throw new RuntimeException("Connection ERROR - Input/Output error.", e);
}
return httpget;
}
}
шаги я достиг с помощью owlstead в ответ ниже. Когда я использую эту программу Java для кодирования Строки Password01 я получаю строку, как:
sy5/XElHvuYA4Rbq8OBydLymT82R+z77jy6MU2sNal7VenzPEbARgy7p3zWgYgG13Cypk+zbnnB5L37fVUhgOgCqCyLtikzxJBNmPyzUK9+beiHJKyONZwifDzQ44hXTeXcZ0bmF9b5dLFy9QS/N5m28vIyBSGY8K2B7EB2FF38=
Этот зашифрованный пароль может быть расшифрован на Java стороне
Когда я использую код .NET строка является например:
ACZXYj/KudyxKBB510SxSouKaVwssmEUM6Jpreh8jTtrIH9eGb18GIdkBU7rXzMuLYbAhyREbFLbR87zW/2DNa4tN97FOlqr6k1JppJ/SSS/9fGdMvSOAQbWjsxksDH7fRu9dCvK0m0exFtGfXG7Yua9bB1m0dTNiwCZUZM0LnEM
Этот зашифрованный пароль не был расшифрован на стороне Java. Ошибка с сообщением об ошибке:
javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes
Вместо того, чтобы * кодировать * эти строки, используя UTF-16, вы почти наверняка должны быть * расшифровать * его с base64. И да, вам нужно правильно установить экспонента. –
@GregS Нужен сон, это база 64, но без заполнения символов. –
@owlstead: Я считал, что в кодировках всего 25 различных символов. Это f__ked. –