我在PKCS7上有一张收据,是我从iOS应用程序中获得的。 Apple says this is a PKCS7 structure以及其中有关过去经常性购买的信息。
我有raw receipt here,用Base64编码。
我已将此有效负载与我的密钥一起发送给Apple and got this response。基于WWDC视频和文档,我相信我应该能够直接阅读此收据,而无需将其发送给苹果。
我猜测BC中的PEMReader是解析它的正确起点,但是我不确定如何实际使用它。我已经扫描了字符串“PKCS”的BC源代码,并查看了单元测试,但是我所看到的都是从PEMReader转换为另一种格式。
using (var stream1 = new MemoryStream(receipt.Data))
using (var stream2 = new StreamReader(stream1))
{
var pp = new PemReader(stream2);
pp.ReadObject();
}
问题
自我注意:我打算用它来检查实际的二进制文件以查看ApplicationUsername是否包含在收据中,但由于某种原因,在发布服务器时JSON结果中没有返回。 (苹果方面的问题?)
答案 0 :(得分:3)
我使用 Java 7 和 BouncyCastle 1.56 制作了这个。
对于下面的代码,请考虑pemString
是您提供的PEM字符串。但我不得不做一些修改:
所以我的PEM看起来像:
-----BEGIN PKCS7-----
MIIv5gYJKoZIhvcNAQcCoIIv1zCCL9MCAQExCzAJBgUrDgMCGgUAMIIfhwYJKoZI
hvcNAQcBoIIfeASCH3Qxgh9wMAoCAQgCAQEEAhYAMAoCARQCAQEEAgwAMAsCAQEC
AQEEAwIBADALAgELAgEBBAMCAQAwCwIBDwIBAQQDAgEAMAsCARACAQEEAwIBADAL
....
gdTu2uzkTyT+vcBlaLHK1ZpjKozsBds7ys6Q4EFp7OLxtJTj7saEDYXCNQtXBjwl
UfSGvQkXeIbsaqSPvOVIE83K3ki5i64gccA=
-----END PKCS7-----
对于下面的代码,我遵循了Apple的文档中的定义:
ReceiptAttribute ::= SEQUENCE {
type INTEGER,
version INTEGER,
value OCTET STRING
}
Payload ::= SET OF ReceiptAttribute
代码:
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DLSequence;
import org.bouncycastle.asn1.DLSet;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
String pemString = // PEM String as described above
PemReader reader = new PemReader(new StringReader(pemString));
PemObject pemObject = reader.readPemObject();
reader.close();
CMSSignedData s = new CMSSignedData(pemObject.getContent());
byte[] content = (byte[]) s.getSignedContent().getContent();
ASN1InputStream in = new ASN1InputStream(content);
// Payload: a SET of ReceiptAttribute
DLSet set = (DLSet) DLSet.fromByteArray(in.readObject().getEncoded());
int size = set.size();
for (int i = 0; i < size; i++) {
// ReceiptAttribute is a SEQUENCE
DLSequence seq = (DLSequence) set.getObjectAt(i);
// value is the third element of the sequence
DEROctetString oct = (DEROctetString) seq.getObjectAt(2);
ASN1Object obj = readObject(oct.getOctets()); // *** see comments below ***
}
in.close();
// readObject method
public ASN1Object readObject(byte[] b) throws IOException {
ASN1InputStream in = null;
try {
in = new ASN1InputStream(b);
return in.readObject();
} catch (Exception e) {
// if error occurs, just return the octet string
return new DEROctetString(b);
} finally {
in.close();
}
}
变量obj
将是ReceiptAttribute
的内容,并且可能会有很大变化 - 我见过DERIA5String
,DERUTF8String
,ASN1Integer
和很多其他的。由于我不知道该字段的所有可能值,我认为由您来检查每个值。