问题描述
如果公司营业额大于50亿,GST委员会已批准实施企业对企业(B2B)发票的“电子发票”或“电子发票”。 gst门户API的参考:einv-apisandbox.nic.in/index.html
我必须使用APP密钥对加密的SEK进行解密,并使用解密的SEK对json数据进行编码以发布到Einvoice生成,并且我找到了Java和C#的示例代码,并且我已经在PHP中进行了转换,但不幸的是未能获得所需的输出
就我而言,加密的SEK为:oRvKfBtmgNTSuk/oXUhiLOjXi45jiWA2oKNxhhQM3UH2o/32YWGLbUjK1/dohPe3
APP键: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;
}
}
对称加密(AES)(在Java中)
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,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));
}
对称解密(AES)(在PHP中)
function decrypt($key,$str)
{
$str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$str,MCRYPT_MODE_ECB);
$pad = ord($str[($len = strlen($str)) - 1]);
$len = strlen($str);
$pad = ord($str[$len-1]);
return base64_encode( substr($str,strlen($str) - $pad));
}
解决方法
在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,$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编码密文(JS+hxYf64FMHThrhoIejqk3VjGwFw+GTYzUyVKc6GEOLKERVuvaNY91zPdo829r0
)的值相同。
注意:
- 未使用已弃用的 mcrypt 。而是使用 openssl 。
- 除了安全性方面, openssl 还具有优于 mcrypt 的优势,即隐式使用了PKCS7填充,类似于C#/ Java代码。 mcrypt 应用零填充,因此用户定义的填充是必需的,而 openssl 已废弃。
- 该密钥不是从SHA256传递的密钥派生的,而是直接应用的,类似于C#/ Java代码。
您可能还需要尝试使用邮递员工具。我实现了相同的功能,并且能够连接NIC系统,但是根据他们提供的文档,使用OpenSSL或其他加密工具无法实现相同的加密。
现在我转到基于GSP的API连接解决方案,您可以从以下位置检查这些内容
https://github.com/sujianalytics/gst-e-invoicing-sap
它是开源的,但与您的问题无关,可能需要根据您的要求进行一些升级。