Я не могу зашифровать / расшифровать в Java и Go, используя кривые P521, ECDH-ES и A256GCM, используя те же значения для кривых X, Y и D. Когда я пытаюсь получить зашифрованное значение из Go и Decrypt в Java это терпит неудачу или наоборот это терпит неудачу с:
Go: square / go-jose: ошибка в криптографическом примитиве
Java: сбой расшифровки AES / GCM / NoPadding: проверка Mac в GCM завершилась неудачей
Любая причина, почему это не работает?
!!! Обновление !!! Я также добавил код для анализа JWK для создания моей KeyPair в Go. (Я использовал программу Java и распечатал пару ключей в json).
Что я заметил, так это то, что иногда зашифрованное значение Java можно анализировать в Go, а иногда нет. Я думаю, что в расшифровке GCM есть что-то, что может не работать в Go.
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/x509"
"encoding/pem"
"fmt"
"log"
"math/big"
"os"
b64 "encoding/base64"
//"github.com/contiamo/jwt"
gojose "gopkg.in/square/go-jose.v2"
//jwtgo "github.com/dgrijalva/jwt-go"
)
func main() {
testgojmx()
}
func testgojmx() {
plaintext := []byte("test string")
xEnc := "AVuFsno89wJ5xT2z63iznxVO8H5gsfcHmS1XJ_JbfEzIsudqjrvKGrzxJT96-dmP_NY7KeMvyJEUInmqcqCWbzcQ"
yEnc := "ANv5hayQ3_TwMcFqPrtw-a9wNkfQuynuWhhbWOXYvGArdvibDGYRIRx3O5gAjfyumpibZFQ0K0jrjb09YP3AVbtc"
dEnc := "AGPoHUdXajyyRLV0bAokQTnDzlO7Kjs1zSucSu69CGfSwpg7oXSxlfptApD-5O47d1PX3y0ag5228XsPFXVzYnH0"
x := new(big.Int)
temp, _ := b64.URLEncoding.DecodeString(xEnc)
x = x.SetBytes(temp)
y := new(big.Int)
temp, _ = b64.URLEncoding.DecodeString(yEnc)
y = y.SetBytes(temp)
d := new(big.Int)
temp, _ = b64.URLEncoding.DecodeString(dEnc)
d = d.SetBytes(temp)
privkey := new(ecdsa.PrivateKey)
privkey.PublicKey.Curve = elliptic.P521()
privkey.D = d
privkey.PublicKey.X = x
privkey.PublicKey.Y = y
//javaKey := `{"kty":"EC","d":"AGPoHUdXajyyRLV0bAokQTnDzlO7Kjs1zSucSu69CGfSwpg7oXSxlfptApD-5O47d1PX3y0ag5228XsPFXVzYnH0","crv":"P-521","x":"AVuFsno89wJ5xT2z63iznxVO8H5gsfcHmS1XJ_JbfEzIsudqjrvKGrzxJT96-dmP_NY7KeMvyJEUInmqcqCWbzcQ","y":"ANv5hayQ3_TwMcFqPrtw-a9wNkfQuynuWhhbWOXYvGArdvibDGYRIRx3O5gAjfyumpibZFQ0K0jrjb09YP3AVbtc"}`
//jwkSet, err := jwk.ParseString(javaKey)
//if err != nil {
// panic(err)
//}
//key, err := jwkSet.Keys[0].Materialize()
//if err != nil {
// panic(err)
//}
//privkey := key.(*ecdsa.PrivateKey)
fmt.Printf("X: %d\nY: %d\nD: %d\n", privkey.X, privkey.Y, privkey.D)
encrypter, err := gojose.NewEncrypter(gojose.A256GCM, gojose.Recipient{Algorithm: gojose.ECDH_ES, Key: privkey.Public()}, nil)
if err != nil {
panic(err)
}
encrypted, err := encrypter.Encrypt(plaintext)
if err != nil {
panic(err)
}
fmt.Printf("encrypted = %v\n", encrypted.Header)
compact, err := encrypted.CompactSerialize()
if err != nil {
panic(err)
}
//compact = "eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTUyMSIsIngiOiJBRUFNS2ZGQ3p5NlY2WmdPdEFjSEh1c0VEM0syUC1aZmdrd2xLWmxtRFJaeGVLcTh4dUx0cXJDTzFycWx5Wkh5MXpfOEVmWXFNM0F6YlI3UGNhQVdCTURkIiwieSI6IkFMUWpEQjNLWWpLQ2twUUsxd0VUVmtvbXZ1ZDRkT05LeXhMeFJVcGpsQ0ZNSnl1bXFlUjJvc0d4N0w3UC1aU19vemJDTnhLaWU1RVQtdlNXUXczRmNLMDAifSwiZW5jIjoiQTI1NkdDTSIsImFsZyI6IkVDREgtRVMifQ..4pyFf4sd5muL9Ony.TOMCKHHWd20nPU8.NN6MFByRemeyNa50yJGVUQ"
fmt.Printf("Compact Encrypted: %v\n", compact)
msg, _ := gojose.ParseEncrypted(compact)
fmt.Printf("Message from Encrypted: %v\n", msg.Header)
decrypted, err := msg.Decrypt(privkey)
fmt.Printf("Decrtyped: %s\n", decrypted)
}
@SpringBootApplication
public class EcdhjweApplication implements CommandLineRunner {
private static Logger LOG = LoggerFactory
.getLogger(EcdhjweApplication.class);
static ECKey exposedJWK = generateECKeyJwk();
public static void main(String[] args) {
SpringApplication.run(EcdhjweApplication.class, args);
}
@Override
public void run(String... args) {
LOG.info("EXECUTING : command line runner");
try {
System.out.println("D: \n" + exposedJWK.toECPrivateKey().getS());
System.out.println("X: \n" + exposedJWK.toECPublicKey().getW().getAffineX());
System.out.println("Y: \n" + exposedJWK.toECPublicKey().getW().getAffineY());
} catch (JOSEException e) {
e.printStackTrace();
}
System.out.println("======================== Encrypting ================================");
String encryptedRequest = null;
try {
encryptedRequest = encryptJWE("test string", exposedJWK.toECPublicKey());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Encrypted Requested::: " + encryptedRequest);
//encryptedRequest = "eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSIsImVwayI6eyJrdHkiOiJFQyIsImNydiI6IlAtNTIxIiwieCI6IkFOSXluNGRoZTd1UkpLWDJzTkVGaVU1dDFEYmR4ZUE5UjRReGVRdk1IXy1GZ2VLWWhNSk9uR1k0LWRzMEtVbjQtRlJfZVhuNl9HLWpqWEdGaThYVGdwVjUiLCJ5IjoiQUxYVkpaMEZmcHhaQzd6andhbEdWWjdyNTJxZlg5VmNsRnY4eWlsQ1pqY3lJbnlYT1BEVlhoWDlPYVU4R1ppeVVmOU1mQndSaTAzOUNMajdiQ0duM1lPRCJ9fQ.._ASNMu9mjl02agPG.QPV7DKPV77hiLJ8.SBGhv8JRJTl_adfFNxgO0Q";
System.out.println("======================== Decrypting Request ================================");
String decryptedDetails = null;
try {
decryptedDetails = decryptJWE(encryptedRequest, exposedJWK.toECPrivateKey());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Decrypted Request:::" + decryptedDetails);
}
//private static String encryptJWE(JSONObject payload, ECPublicKey ecPublicKey) throws Exception {
private static String encryptJWE(String payload, ECPublicKey ecPublicKey) throws Exception {
// Build JWE header
JWEHeader header = new JWEHeader.Builder(JWEAlgorithm.ECDH_ES, EncryptionMethod.A256GCM)
.build();
// Build JWE Object
JWEObject jweObjectClient = new JWEObject(header, new Payload(payload));
// Set Public Key, Encrypt
ECDHEncrypter encrypter = new ECDHEncrypter(ecPublicKey);
encrypter.getJCAContext().setContentEncryptionProvider(BouncyCastleProviderSingleton.getInstance());
jweObjectClient.encrypt(encrypter);
return jweObjectClient.serialize();
}
private static String decryptJWE(String vcnRequestJWE, ECPrivateKey ecPrivateKey) throws Exception {
// Parse JWE & validate headers
JWEObject jweObject = EncryptedJWT.parse(vcnRequestJWE);
// Set PrivateKey and Decrypt
ECDHDecrypter decrypter = new ECDHDecrypter(ecPrivateKey);
decrypter.getJCAContext().setContentEncryptionProvider(BouncyCastleProviderSingleton.getInstance());
jweObject.decrypt(decrypter);
return jweObject.getPayload().toString();
}
public static ECKey generateECKeyJwk() {
try {
// Generate EC key pair with P-521 curve
String x = "AVuFsno89wJ5xT2z63iznxVO8H5gsfcHmS1XJ_JbfEzIsudqjrvKGrzxJT96-dmP_NY7KeMvyJEUInmqcqCWbzcQ";
String y = "ANv5hayQ3_TwMcFqPrtw-a9wNkfQuynuWhhbWOXYvGArdvibDGYRIRx3O5gAjfyumpibZFQ0K0jrjb09YP3AVbtc";
String d = "AGPoHUdXajyyRLV0bAokQTnDzlO7Kjs1zSucSu69CGfSwpg7oXSxlfptApD-5O47d1PX3y0ag5228XsPFXVzYnH0";
return new ECKey.Builder(Curve.P_521, new Base64URL(x), new Base64URL(y))
.d(new Base64URL(d))
.build();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Код, показанный на рисунке, демонстрирует работу на языке. Закомментированные строки являются результатом запуска с другого языка