当前位置: 首页 > 知识库问答 >
问题:

带PKCS7填充的AES 256

林博厚
2023-03-14

如果公司营业额大于50亿卢比,GST理事会已批准将企业对企业(B2B)发票的“电子发票”或“电子发票”实施到GST系统。参考商品及服务税门户 API :einv-apisandbox.nic.in/index.html

我必须使用APP密钥对加密的SEK进行解密,并使用解密的SEK对json数据进行编码,以便发布Einvoice Generation,我找到了java和C#的示例代码,我已经用PHP进行了转换,但不幸的是,未能获得所需的输出

在我的案例中,加密的SEK是:oRvKfBtmgNTSuk/oXUhiLOjXi45jiWA2oKNxhhQM3UH2o/32YWGLbUjK1/dohPe3

APP Key: FAO1PoKaLgd11xMRWTiL2cggAfx9QMwM

对称解密(AES)(java中)

public static String decrptyBySyymetricKey(String encryptedSek, byte[] appKey)
{
    Key aesKey = new SecretKeySpec(appKey, "AES"); // converts bytes(32 byte random generated) to key
    try {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // encryption type = AES with padding PKCS5
        cipher.init(Cipher.DECRYPT_MODE, aesKey); // initiate decryption type with the key
        byte[] encryptedSekBytes = Base64.decodeBase64(encryptedSek); // decode the base64 encryptedSek to bytes
        byte[] decryptedSekBytes = cipher.doFinal(encryptedSekBytes); // decrypt the encryptedSek with the initialized cipher containing the key(Results in bytes)
        String decryptedSek = Base64.encodeBase64String(decryptedSekBytes); // convert the decryptedSek(bytes) to Base64 StriNG
        return decryptedSek; // return results in base64 string
    }catch(Exception e) {
        return "Exception; "+e;
    }
}

对称加密(在爪哇中)

public static string EncryptBySymmetricKey(string text, string sek)
    {
    //Encrypting SEK
    try
    {
      byte[] dataToEncrypt = Convert.FromBase64String(text);
      var keyBytes = Convert.FromBase64String(sek);
      AesManaged tdes = new AesManaged();
      tdes.KeySize = 256;
      tdes.BlockSize = 128;
      tdes.Key = keyBytes;
      tdes.Mode = CipherMode.ECB;
      tdes.Padding = PaddingMode.PKCS7;
      pICryptoTransform encrypt__1 = tdes.CreateEncryptor();
      byte[] deCipher = encrypt__1.TransformFinalBlock(dataToEncrypt, 0, dataToEncrypt.Length);
      tdes.Clear();
      string EK_result = Convert.ToBase64String(deCipher);
      return EK_result;
   }
   catch (Exception ex)
    {
      throw ex;
   }
 }

对称加密(AES)(在PHP中)

function encrypt($data, $key)
{
    $padding = 16 - (strlen($data) % 16);
    $data .= str_repeat(chr($padding), $padding);
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, hash('SHA256', $key, true), $data, MCRYPT_MODE_ECB));
 }

对称解密

function decrypt($key, $str) 
{
    $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, hash('SHA256', $key, true), $str, MCRYPT_MODE_ECB);
    $pad = ord($str[($len = strlen($str)) - 1]);
    $len = strlen($str);
    $pad = ord($str[$len-1]);
    
    return base64_encode( substr($str, 0, strlen($str) - $pad));
}

共有2个答案

马坚白
2023-03-14

您可能还需要尝试使用邮递员工具。我实现了相同的功能,并且能够连接NIC系统,但根据他们提供的文档,不可能使用OpenSSL或其他加密工具实现相同的加密。

现在我转向基于GSP的API连接解决方案,您可以从中检查这些东西

https://github.com/sujianalytics/gst-e-invoicing-sap

它是开源的,但与您的问题无关,可能需要根据您的需求进行升级。

胡国兴
2023-03-14

在PHP中,可以使用AppKey对会话密钥(SEK)进行解密,如下所示:

function decrptyBySymmetricKey($encSekB64, $appKey) {
    $sek = openssl_decrypt($encSekB64, "aes-256-ecb", $appKey, 0);                  // the SEK
    $sekB64 = base64_encode($sek);                                                  // the Base64 encoded SEK
    return $sekB64;
}

在PHP中使用SEK加密数据是可能的,如下所示:

function encryptBySymmetricKey($dataB64, $sekB64){
    $data = base64_decode($dataB64);                                                // the data to encrypt
    $sek = base64_decode($sekB64);                                                  // the SEK
    $encDataB64 = openssl_encrypt($data, "aes-256-ecb", $sek, 0);                   // the Base64 encoded ciphertext
    return $encDataB64;
}

这两种功能都可以用以下数据进行测试:

$appKey = 'fao1PoKaLgd11xMrWTiL2cggAfx9QMwM';                                       // the 32 bytes AppKey
$encSekB64 = 'oRvKfBtmgNTSuk/oXUhiLOjXi45jiWA2oKNxhhQM3UH2o/32YWGLbUjK1/dohPe3';    // the Base64 encoded encrypted SEK 
$dataB64 = 'VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==';          // the base64 encoded data
$sekB64 = decrptyBySymmetricKey($encSekB64, $appKey);                               // the Base64 encoded SEK   
$encDataB64 = encryptBySymmetricKey($dataB64, $sekB64);                             // the Base64 encoded ciphertext
echo $sekB64 . "\n";                                                                // zVoede7m2nnvMHcWYIfKhrvsilSFEZYiltJmxVQQnAQ=
echo $encDataB64;                                                                   // JS+hxYf64FMHThrhoIejqk3VjGwFw+GTYzUyVKc6GEOLKERVuvaNY91zPdo829r0

Java方法decryptBySymmetricKey返回

byte[] appKey = "fao1PoKaLgd11xMrWTiL2cggAfx9QMwM".getBytes(StandardCharsets.UTF_8);
String encSekB64 = "oRvKfBtmgNTSuk/oXUhiLOjXi45jiWA2oKNxhhQM3UH2o/32YWGLbUjK1/dohPe3";
String sekB64 = decryptBySymmetricKey(encSekB64, appKey);

Base64 编码 SEK 的值相同 (zVoede7m2nnvMHCWYIfKhrvsilsFEZYILTJmxVQQnAQ=).

同样,C#方法EncryptBySymmetricKey(在问题中错误地标记为Java函数)返回

string dataB64 = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==";
string sekB64 = "zVoede7m2nnvMHcWYIfKhrvsilSFEZYiltJmxVQQnAQ=";
string encDataB64 = EncryptBySymmetricKey(dataB64, sekB64);

Base64编码密文的值相同(< code > JS hxyf 64 fmhtrhoiejqk 3 vjgwfw gtyzuyvkc 6 geolkervuvany 91 zpdo 829 r 0 )。

注:

    < li >不使用不推荐使用的mcrypt。相反,openssl被应用。 < li >除了安全方面,openssl比mcrypt更有优势,它隐式使用PKCS7填充,类似于C#/Java代码。mcrypt应用零填充,因此用户定义的填充是必要的,这在openssl中已经过时了。 < li >该密钥不是从通过SHA256传递的密钥派生的,而是直接应用的,类似于C#/Java代码。
 类似资料:
  • 我刚刚开始学习用于AES加密/解密的充气城堡。我使用的是带有256位密钥的。 BC可以成功地加密和解密文本,但是在解密之后,我注意到总是有一些空填充(0x00),因此无法进行哈希比较。例如,假设原始输入字符串为,解密的字节数组始终为: 为什么填充不是?有没有什么方法可以确定加密后的填充长度(可能是0),以便在加密前得到完全相同的字符串?

  • 我目前使用< code > AES/CBC/PKCS 5 Padding 对Java文件进行加密,密钥大小为256字节,但在搜索时,我在stack exchange PKCS # 5-PKCS # 7 Padding上发现了它, PKCS#5填充是8字节块大小的PKCS#7填充的子集 所以我想知道 > < li >对于上述配置,< code > AES/CBC/pkcs 7 padding 的性能

  • 我有两个视图,适合在屏幕的顶部和底部,我有一个回收器视图,将坐在他们之间,但有一个视图,很多与回收器视图垂直包装。类似这样的东西 我必须使用约束布局来实现这一点。我尝试过使用打包链来实现这一点,但这将视图放在屏幕的中心,而不是与顶视图对齐。

  • 要求: 我有一个Ruby on rails应用程序,我需要执行以下操作。 以下字符串应使用3DES算法和工作密钥加密。ABJGTU9的加密值将是vV51P0OGXt0= 工作密钥为 A5157A0D77B24AEA868AD73288366826 以下文献中提到的3DES算法使用以下步骤进行数据加密: i.使用CBC密码模式和PKCS7填充的密钥的左侧部分加密数据。ii.使用CBC密码模式和无填充

  • 我对我当前尝试访问的API的加密有以下要求: < li>PKCS7填充方法 < li>CBC加密模式 < li>AES密钥大小256,块大小128 每次我提交带有加密的API时,API似乎都有问题(不幸的是没有产生错误)。 问题: PKCS7填充方法到底是什么,可以用php实现? AES 256很好,但是块大小到底是什么意思? IV到底是做什么的?

  • 我需要使用AES-256-CBC和PKCS7填充加密用户和密码,以连接到它不是我的.NET服务器应用程序。 首先,我使用Diffie-Hellman算法获得了公共服务器密钥,遵循本网站上的说明: https://doc.developer.milestonesys.com/mipsdkmobile/index.html?base=content_0.html 从服务器获取公钥的代码是: 一旦我拿到