douping7105 2019-04-16 15:03
浏览 271

为什么在Java和Go之间解密JWE时出现错误

I am not able to encrypt/decrypt within Java and Go using Curve P521, ECDH-ES, and A256GCM using the same values for curve X, Y, and D. When I try to take the encrypted value from Go and Decrypt in Java it fails or vice versa it fails with:

Go: square/go-jose: error in cryptographic primitive

Java: AES/GCM/NoPadding decryption failed: mac check in GCM failed

Any reason why this isn't working?

!!!Update!!! I have also added code to parse a JWK to create my KeyPair in Go. (I used the java program and printed the keypair to json).

What I notice is that sometimes the Java encrypted value can be parsed in Go and sometimes it can't. It is my thought that there is something in the GCM decryption that might not be working quite right in 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
Y: %d
D: %d
", 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
", encrypted.Header)

    compact, err := encrypted.CompactSerialize()
    if err != nil {
        panic(err)
    }

    //compact = "eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTUyMSIsIngiOiJBRUFNS2ZGQ3p5NlY2WmdPdEFjSEh1c0VEM0syUC1aZmdrd2xLWmxtRFJaeGVLcTh4dUx0cXJDTzFycWx5Wkh5MXpfOEVmWXFNM0F6YlI3UGNhQVdCTURkIiwieSI6IkFMUWpEQjNLWWpLQ2twUUsxd0VUVmtvbXZ1ZDRkT05LeXhMeFJVcGpsQ0ZNSnl1bXFlUjJvc0d4N0w3UC1aU19vemJDTnhLaWU1RVQtdlNXUXczRmNLMDAifSwiZW5jIjoiQTI1NkdDTSIsImFsZyI6IkVDREgtRVMifQ..4pyFf4sd5muL9Ony.TOMCKHHWd20nPU8.NN6MFByRemeyNa50yJGVUQ"

    fmt.Printf("Compact Encrypted: %v
", compact)

    msg, _ := gojose.ParseEncrypted(compact)
    fmt.Printf("Message from Encrypted: %v
", msg.Header)

    decrypted, err := msg.Decrypt(privkey)

    fmt.Printf("Decrtyped: %s
", 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: 
" + exposedJWK.toECPrivateKey().getS());
            System.out.println("X: 
" + exposedJWK.toECPublicKey().getW().getAffineX());
            System.out.println("Y: 
" + 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;
        }
    }

}

The code as shown shows demonstrates working within the language. The commented out strings are the result of a run from the other language

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 求解 yolo算法问题
    • ¥15 虚拟机打包apk出现错误
    • ¥30 最小化遗憾贪心算法上界
    • ¥15 用visual studi code完成html页面
    • ¥15 聚类分析或者python进行数据分析
    • ¥15 逻辑谓词和消解原理的运用
    • ¥15 三菱伺服电机按启动按钮有使能但不动作
    • ¥15 js,页面2返回页面1时定位进入的设备
    • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
    • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。