在 Golang 中解密 RSA/ECB/NoPadding 字节数组

问题描述 投票:0回答:1

我有一个 Java 代码,我可以在其中发送带有扰码密钥的包:

protected void write()
{
    writeC(0x00);
    writeD(_sessionId);
    writeD(PROTOCOL_VERSION);
    writeB(_publicKey); --- > scrambled key
    writeB(UNKNOWN_GG);
    writeB(_blowfishKey);
    writeC(0x00);
}

在我的Java代码中,我可以使用以下解密方法正确解密加扰密钥:

public void run()
{
    final LoginClient client = getClient();
    
    byte[] decrypted = null;
    try
    {
        final Cipher rsaCipher = Cipher.getInstance("RSA/ECB/nopadding");
        rsaCipher.init(Cipher.DECRYPT_MODE, client.getRSAPrivateKey());
        decrypted = rsaCipher.doFinal(_raw, 0x00, 0x80);
    }
    catch (GeneralSecurityException e)
    {
        LOGGER.error("Failed to generate a cipher.", e);
        client.close(LoginFail.REASON_ACCESS_FAILED);
        return;
    }
    
    try
    {
        final String user = new String(decrypted, 0x5E, 14).trim().toLowerCase();
        final String password = new String(decrypted, 0x6C, 16).trim();

        LoginController.getInstance().retrieveAccountInfo(client, user, password);
    }
    catch (Exception e)
    {
        LOGGER.error("Failed to decrypt user/password.", e);
        client.close(LoginFail.REASON_ACCESS_FAILED);
    }
}

在 Java 中,使用以下输入即可正确解密:

乱码密钥:

[124, 168, 24, 242, 228, 213, 212, 54, 235, 100, 160, 114, 163, 61, 75, 218, 182, 245, 166, 34, 214, 132, 15, 71, 135, 194, 141, 227, 38, 1, 217, 145, 203, 135, 209, 137, 111, 33, 54, 34, 57, 0, 189, 243, 199, 219, 109, 56, 15, 225, 143, 59, 176, 108, 76, 204, 232, 133, 216, 126, 70, 30, 115, 74, 25, 0, 133, 38, 128, 16, 28, 183, 155, 24, 188, 86, 117, 191, 135, 36, 211, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75]

Java 私钥:

SunRsaSign RSA private CRT key, 1024 bits
  params: null
  modulus: 91851415039980683673835443907833548355613725060429787547716446884026400945844827342368025805543719063805785824109075005634172820422680533076648130137521254244221874431195148950936257983839718841574094615493929797376689026996944801887459231860502077721291214210394902757594184173778070286729141127782416296193
  private exponent: 6487635995240407475566233880851450254636860602479965310563184653343274943593934811905055029279061836006484620592961353145255138101173202734513392349460393317252650745961877082056763589015732603463063131507792018004450541681668317154023863374611531824451608552071840032997073721859882730955156029598795586149
Chave privada (formato Go):
&rsa.PrivateKey{
  PublicKey: rsa.PublicKey{
    N: big.NewInt(0).SetBytes(new byte[] {0, -126, -52, -2, 101, -128, 16, 28, -73, -101, 24, -68, 86, 117, 15, -21, 104, 31, -91, 104, -39, 6, -74, -92, -120, 101, -41, 42, 113, 111, 55, -48, -49, 105, 35, -74, 47, -15, 107, -117, -41, -43, -7, 43, 125, -37, 34, 53, 103, -6, 92, -102, -128, 75, -67, -88, -128, -27, 6, -17, -79, 101, 126, -38, 75, 101, -88, -99, -44, 100, -59, -56, -127, 112, 124, 28, 36, -42, 25, 0, -123, 38, 80, -50, -5, -48, 50, -85, -49, -30, 21, -89, -110, 73, 54, 9, 94, -94, -92, 103, -90, -98, 74, -67, -11, -20, -7, -106, -114, 28, -7, 88, 95, -11, -67, 21, -69, -5, -47, -28, 76, 13, -125, 55, -49, 35, 96, -87, 1, }),
    E: 65537,
  },
  D: big.NewInt(0).SetBytes(new byte[] {9, 61, 27, 118, -27, -35, -67, 121, -122, 125, -17, -57, -105, -117, 33, 80, -128, 115, -71, 125, 34, -55, 65, -61, -44, -107, -89, 12, -50, 19, 62, 47, 120, 56, -86, -124, -90, 99, -73, 67, -18, 124, 36, 3, 70, -72, 26, -41, -106, 74, 118, 43, 59, -82, 80, -71, -111, -13, -76, 120, 110, 55, -48, -119, 74, -39, 58, 44, -63, -103, -73, -80, 57, 1, 64, -60, -33, -53, -21, 53, -45, -7, -42, 113, 60, 12, 38, 24, -66, 9, -111, 18, -108, -38, 30, 114, -77, -83, -9, 34, 88, -44, -114, -79, -54, -17, 44, 2, -36, -117, -74, 122, -62, -103, 14, 115, -39, 18, 73, -69, -77, -62, -111, -127, -102, -12, 90, 101, }),
}

要解密的字节数组:

[89, 250, 193, 103, 219, 4, 129, 208, 181, 30, 127, 250, 147, 113, 64, 25, 187, 96, 88, 15, 64, 93, 100, 141, 42, 89, 13, 157, 253, 187, 118, 154, 150, 132, 238, 224, 22, 98, 35, 252, 92, 253, 138, 6, 38, 142, 170, 247, 136, 19, 231, 48, 52, 228, 22, 222, 81, 242, 182, 109, 96, 209, 7, 187, 213, 237, 218, 147, 238, 28, 25, 217, 81, 200, 219, 76, 214, 232, 238, 193, 78, 252, 180, 45, 182, 150, 220, 157, 194, 11, 57, 195, 20, 174, 13, 123, 69, 72, 81, 112, 49, 143, 3, 67, 216, 86, 11, 234, 48, 210, 254, 136, 201, 238, 1, 222, 134, 178, 102, 230, 102, 137, 145, 236, 197, 2, 120, 106]

但是,当我尝试使用 crypto/rsa 包在 Golang 中复制解密过程时,我遇到了问题。 Go 的实现如下所示:

func NewScrambledKeyPairTest(bits int) (ScrambledKeyPair, error) {
    scrambledModulusJava := []byte{124, 168, 24, 242, 228, 213, 212, 54, 235, 100, 160, 114, 163, 61, 75, 218, 182, 245, 166, 34, 214, 132, 15, 71, 135, 194, 141, 227, 38, 1, 217, 145, 203, 135, 209, 137, 111, 33, 54, 34, 57, 0, 189, 243, 199, 219, 109, 56, 15, 225, 143, 59, 176, 108, 76, 204, 232, 133, 216, 126, 70, 30, 115, 74, 25, 0, 133, 38, 128, 16, 28, 183, 155, 24, 188, 86, 117, 191, 135, 36, 211, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75}
    privateKey := &rsa.PrivateKey{
        PublicKey: rsa.PublicKey{
            N: big.NewInt(0).SetBytes([]byte{
                0, 130, 204, 254, 101, 128, 16, 28, 185, 155, 24, 188, 86, 117, 15, 235, 104, 31, 165, 104, 217, 6, 182, 164, 136, 101, 215, 42, 113, 111, 55, 208, 207, 105, 35, 182, 47, 241, 107, 139, 215, 213, 249, 43, 125, 219, 34, 53, 103, 250, 92, 154, 128, 75, 189, 168, 128, 229, 6, 239, 177, 101, 126, 218, 75, 101, 168, 157, 212, 100, 197, 200, 129, 112, 124, 28, 36, 214, 25, 0, 133, 38, 80, 206, 251, 208, 50, 171, 207, 226, 21, 169, 146, 73, 54, 9, 94, 162, 164, 103, 166, 158, 74, 189, 245, 236, 249, 150, 142, 28, 249, 88, 95, 245, 189, 21, 187, 251, 209, 228, 76, 13, 131, 55, 207, 35, 96, 169, 1,
            }),
            E: 65537,
        },
        D: big.NewInt(0).SetBytes([]byte{
            9, 61, 27, 118, 229, 221, 189, 121, 134, 125, 239, 199, 151, 139, 33, 80, 128, 115, 185, 125, 34, 201, 65, 195, 212, 149, 167, 12, 206, 19, 62, 47, 120, 56, 170, 132, 166, 99, 185, 67, 238, 124, 36, 3, 70, 184, 26, 215, 150, 74, 118, 43, 59, 174, 80, 185, 145, 243, 180, 120, 110, 55, 208, 137, 74, 217, 58, 44, 193, 153, 183, 176, 57, 1, 64, 196, 223, 203, 235, 53, 211, 249, 214, 113, 60, 12, 38, 24, 190, 9, 145, 18, 148, 218, 30, 114, 179, 173, 247, 34, 88, 212, 142, 177, 202, 239, 44, 2, 220, 139, 182, 122, 194, 153, 14, 115, 217, 18, 73, 187, 179, 194, 145, 129, 154, 244, 90, 101,
        }),
    }

    return ScrambledKeyPair{
        Pair:             privateKey,
        ScrambledModulus: scrambledModulusJava,
    }, nil
}


func (p RequestLogin) Run(client *clients.Client, rand io.Reader) error {
    privateKey := client.PrivateKey()

    c := new(big.Int).SetBytes(p.raw)
    m := new(big.Int)
    m.Exp(c, privateKey.D, privateKey.N)
    em := m.Bytes()

    user := string(em[0x5E : 0x5E+14])
    pwd := string(em[0x6C : 0x6C+16])

    return nil
}

但是我没有成功解密这些字节:

[89, 250, 193, 103, 219, 4, 129, 208, 181, 30, 127, 250, 147, 113, 64, 25, 187, 96, 88, 15, 64, 93, 100, 141, 42, 89, 13, 157, 253, 187, 118, 154, 150, 132, 238, 224, 22, 98, 35, 252, 92, 253, 138, 6, 38, 142, 170, 247, 136, 19, 231, 48, 52, 228, 22, 222, 81, 242, 182, 109, 96, 209, 7, 187, 213, 237, 218, 147, 238, 28, 25, 217, 81, 200, 219, 76, 214, 232, 238, 193, 78, 252, 180, 45, 182, 150, 220, 157, 194, 11, 57, 195, 20, 174, 13, 123, 69, 72, 81, 112, 49, 143, 3, 67, 216, 86, 11, 234, 48, 210, 254, 136, 201, 238, 1, 222, 134, 178, 102, 230, 102, 137, 145, 236, 197, 2, 120, 106]

这些字节在Java中解密后的值是这样的:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 97, 100, 109, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

但在 Golang 中我不能,因为在 Java 中我使用的是: Cipher.getInstance("RSA/ECB/nopadding"); e 在 Golang 中,我还没有找到任何无需填充即可解密字节切片的函数。

java go rsa
1个回答
0
投票

您的代码不能直接执行,并且您没有准确描述问题是什么(错误的结果,异常......)。当我用您的数据运行解密(模幂)时:

ciphertextBytes := ([]byte{89, 250, 193, 103, 219, 4, 129, 208, 181, 30, 127, 250, 147, 113, 64, 25, 187, 96, 88, 15, 64, 93, 100, 141, 42, 89, 13, 157, 253, 187, 118, 154, 150, 132, 238, 224, 22, 98, 35, 252, 92, 253, 138, 6, 38, 142, 170, 247, 136, 19, 231, 48, 52, 228, 22, 222, 81, 242, 182, 109, 96, 209, 7, 187, 213, 237, 218, 147, 238, 28, 25, 217, 81, 200, 219, 76, 214, 232, 238, 193, 78, 252, 180, 45, 182, 150, 220, 157, 194, 11, 57, 195, 20, 174, 13, 123, 69, 72, 81, 112, 49, 143, 3, 67, 216, 86, 11, 234, 48, 210, 254, 136, 201, 238, 1, 222, 134, 178, 102, 230, 102, 137, 145, 236, 197, 2, 120, 106})[0:128]
modulusInt := "91851415039980683673835443907833548355613725060429787547716446884026400945844827342368025805543719063805785824109075005634172820422680533076648130137521254244221874431195148950936257983839718841574094615493929797376689026996944801887459231860502077721291214210394902757594184173778070286729141127782416296193"
privateExpInt := "6487635995240407475566233880851450254636860602479965310563184653343274943593934811905055029279061836006484620592961353145255138101173202734513392349460393317252650745961877082056763589015732603463063131507792018004450541681668317154023863374611531824451608552071840032997073721859882730955156029598795586149"

c := new(big.Int)
c.SetBytes(ciphertextBytes)
n := new(big.Int)
n.SetString(modulusInt, 10)
d := new(big.Int)
d.SetString(privateExpInt, 10)

decrypted := new(big.Int).Exp(c, d, n).Bytes()
fmt.Println(hex.EncodeToString(decrypted)) // 24000061646d696e00000000000000000061646d696e000000000000000000000000000000

我得到了正确的结果(十六进制编码):

24000061646d696e00000000000000000061646d696e000000000000000000000000000000

与 Java 代码结果的唯一区别在于,Java 代码自动用 0x00 值从前面填充结果直至密钥大小/模数,而直接模幂当然不会发生这种情况。

要解决此问题,您只需填充自己以使索引正确,例如:

decryptedPadded := append(make([]byte, 128-len(decrypted)), decrypted...)
fmt.Println(hex.EncodeToString(decryptedPadded[0x5E : 0x5E+14])) // 61646d696e000000000000000000
fmt.Println(string(decryptedPadded[0x5E : 0x5E+14])) // admin

安全性:正如评论中已经提到的,没有填充的 RSA 加密是不安全的。此外,现在应使用至少 2048 位(256 字节)的密钥大小。

© www.soinside.com 2019 - 2024. All rights reserved.