#java #c# #encryption #public-key #diffie-hellman
#java #c# #шифрование #открытый ключ #диффи-Хеллман
Вопрос:
Я не специалист в области шифрования. У нас есть требование зашифровать данные на c # и расшифровать их на java. Мы смогли зашифровать и расшифровать данные для одного и того же ключа на c # и java. Когда мы пытаемся зашифровать строку на c # и расшифровать ее на java, мы получаем
com.nimbusds.jose.Исключение JOSEException: сбой дешифрования AES / GCM / NoPadding: несоответствие тегов!
Может кто-нибудь, пожалуйста, помогите.
Ниже приведен код C # для шифрования данных.
Код для расшифровки строки на C#
public class JWK
{
public string alg { get; set; }
public int? created_at { get; set; }
public string crv { get; set; }
public int? expired_at { get; set; }
public string kid { get; set; }
public string kty { get; set; }
public string use { get; set; }
public string x { get; set; }
public string y { get; set; }
public string d { get; set; }
}
public static string stringkey = @" {
""y"": ""AGum7Ok3MsKuMfrGtYUoeRq09oXwuO5yiMcxDjPbZglLKaZK-Z_kGt3ZcakVavLx46ieXw4agldm9qV6KmBCf6d7"",
""kty"": ""EC"",
""d"": ""AaDyXhcUwH90OvzbYJvocSl7uYlZNRZvgj8yesGjtqUWfxmN50NIFfnBpKohNc3wkYqviScjevczATzibw0Cnlgp"",
""kty"": ""EC"",
""crv"": ""P-521"",
""x"": ""AeyTJd9u-0k3ihg5T1OKqc7xlfn-a5WWTwp0yeQLz03lTHotMhiuKYQGez5KgeuODtOyZNmNdcKN6WjlFuMmVlTd""
}";
static void Main(string[] args)
{
string secretMessage = "Hello world";
string encryptedValue = Encrypt(secretMessage);
Console.WriteLine("Encrypted Value: " encryptedValue);
string decryptedValue = Decrypt(encryptedValue);
Console.WriteLine("Decrypted Value: " decryptedValue);
string encryptedValuewithByteCode = EncryptWithByteCode(secretMessage);
Console.WriteLine("Decrypted Value: " Decrypt(encryptedValuewithByteCode));
}
public static string Encrypt(string encryptValue) {
JsonTextReader reader = new JsonTextReader(new StringReader(stringkey));
var jwk = JsonSerializer.CreateDefault().Deserialize<JWK>(reader);
var publicECCKey = EccKey.New(WebEncoders.Base64UrlDecode(jwk.x), WebEncoders.Base64UrlDecode(jwk.y), usage: CngKeyUsages.KeyAgreement);
string token = Jose.JWT.Encode(encryptValue, publicECCKey, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM);
return token;
}
public static string EncryptWithByteCode(string encryptValue)
{
JsonTextReader reader = new JsonTextReader(new StringReader(stringkey));
var jwk = JsonSerializer.CreateDefault().Deserialize<JWK>(reader);
var publicECCKey = EccKey.New(WebEncoders.Base64UrlDecode(jwk.x), WebEncoders.Base64UrlDecode(jwk.y), usage: CngKeyUsages.KeyAgreement);
string token = Jose.JWT.EncodeBytes(System.Text.Encoding.UTF8.GetBytes(encryptValue), publicECCKey, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM);
return token;
}
public static string Decrypt(string encryptedValue)
{
JsonTextReader reader = new JsonTextReader(new StringReader(stringkey));
var jwk = JsonSerializer.CreateDefault().Deserialize<JWK>(reader);
var publicECCKey = EccKey.New(WebEncoders.Base64UrlDecode(jwk.x), WebEncoders.Base64UrlDecode(jwk.y), WebEncoders.Base64UrlDecode(jwk.d), usage: CngKeyUsages.KeyAgreement);
string token = Jose.JWT.Decode(encryptedValue, publicECCKey, JweAlgorithm.ECDH_ES, JweEncryption.A256GCM);
return token;
}
}
public class JWK
{
public string alg { get; set; }
public int? created_at { get; set; }
public string crv { get; set; }
public int? expired_at { get; set; }
public string kid { get; set; }
public string kty { get; set; }
public string use { get; set; }
public string x { get; set; }
public string y { get; set; }
public string d { get; set; }
}
Java расшифровывает генерацию строк:
String encryptedFromDotNet= "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSIsImVwayI6eyJrdHkiOiJFQyIsIngiOiJBWEVBdzR6MmpnRmkzRktXZ3IwNHQwS3VwOEVOeGpJaWE3aDNVQ1BZSGpwODdwMXpxMHBHVUxXVUxNaFUzOVdubERJLTFFMEl5Mzd6WmJ3LVYzQ0pURFpsIiwieSI6IkFIMUtWOWpONG9JTEpzLThGYlJmVDNVWXF3MnJDVFVZd3k5MEYwQXFFa0VZam1KOXlyekdKVC0zTGQtOUZPRUQwZV9tcE5iYlhRVk12Q25GTEQwQTdSNzIiLCJjcnYiOiJQLTUyMSJ9fQ..AXWgvsa6PwWPSS1l.UxfvMIekKvBAMbs.1n9dqJvPZQfM8v2XEkLLQg";
String decryptedValue = getDecryptedValue(encryptedFromDotNet);
System.out.print(decryptedValue);
}
public static String getDecryptedValue(String encryptedFromDotNet ) {
try {
String ecdhKey = "{n"
"t"kty": "EC",n"
"t"d": "AaDyXhcUwH90OvzbYJvocSl7uYlZNRZvgj8yesGjtqUWfxmN50NIFfnBpKohNc3wkYqviScjevczATzibw0Cnlgp",n"
"t"crv": "P-521",n"
"t"x": "AeyTJd9u-0k3ihg5T1OKqc7xlfn-a5WWTwp0yeQLz03lTHotMhiuKYQGez5KgeuODtOyZNmNdcKN6WjlFuMmVlTd",n"
"t"y": "AGum7Ok3MsKuMfrGtYUoeRq09oXwuO5yiMcxDjPbZglLKaZK-Z_kGt3ZcakVavLx46ieXw4agldm9qV6KmBCf6d7"n"
"}";
ECKey ecKey = ECKey.parse(ecdhKey);
JWEObject jweObjectServer = EncryptedJWT.parse(encryptedFromDotNet);
ECDHDecrypter decrypter = new ECDHDecrypter(ecKey.toECPrivateKey());
jweObjectServer.decrypt(decrypter);
return jweObjectServer.getPayload().toString();
} catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
Комментарии:
1. Вы уверены, что ваш токен из dotNet скопирован правильно? Токен JWE обычно состоит из 5 частей, объединенных символом «.». В конце токена я вижу «TUyMSJ9fQ..AXWgvsa6PwWPSS1l.UxfvMIekKvBAMbs.1n9dqJvPZQfM8v2XEkLLQg» (две точки, означающие, что для части 3 токена нет значения (который содержит одноразовый номер для расшифровки GCM). Это может быть веской причиной сбоя
2. @MichaelFehr: на самом деле пустая часть — это # 2 зашифрованный ключ, а для ECDH-ES в режиме «direct» он должен быть пустым: см. rfc7518 4.6. (AXWgvsa6PwWPSS1l является одноразовым номером и составляет 12 байт, как требуется для A256GCM.)
3. Тест с использованием JWCrypto на Python показывает, что шифрование с помощью ECDH-ES, P-521 на Java может быть успешно расшифровано на Python, в то время как соответствующее шифрование в .NET не может быть расшифровано на Python (InvalidTag). С другой стороны, шифрование с помощью ECDH-ES, P-256 в Java и .NET успешно расшифровывается в Python. Таким образом, проблема, похоже, заключается в ошибке в . Сетевая реализация специально для P-521.
4. Ошибка уже известна, см. github.com/dvsekhvalnov/jose-jwt#notes .