Почему я получаю ошибку при расшифровке JWE между Java и Go - PullRequest
1 голос
/ 16 апреля 2019

Я не могу зашифровать / расшифровать в 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;
        }
    }

}

Код, показанный на рисунке, демонстрирует работу на языке. Закомментированные строки являются результатом запуска с другого языка

...