Is there anybody who can fix this problem:
For MAS receipt check we need the CertTolls from MacOSLib. We need only these definition, parameters, declares and methods:
Private Const SampleReceipt As String = "MIIOBQYJKoZIhvcNAQcCoIIN9jCCDfICAQExCzAJBgUrDgMCGgUAMIIBogYJKoZIhvcNAQcBoIIB …
Protected Enum Keys
kReceiptBundleIdentifer
kReceiptBundleIdentiferData
kReceiptVersion
kReceiptOpaqueValue
kReceiptHash
Private Enum ATTRS
zero
ATTR_START
BUNDLE_ID
VERSION
OPAQUE_VALUE
HASH
ATTR_END
length as Int32
type as Int32
data as Ptr
flags as Int32
asn1 as CString
length as Int32
state as Int32
detached as Int32
type as Ptr
d as Ptr
version as Ptr
md_algs as Ptr
cert as Ptr
crl as Ptr
signer_info as Ptr
contents as Ptr
Protected Sub SelfTest()
// Call this function just to test whether the verification code works in general
#if TargetMacOS
dim f as FolderItem
f = SpecialFolder.Temporary.Child(“selftest-data”)
BinaryStream.Create(f,true).Write(DecodeBase64(SampleReceipt))
dim d as Dictionary
d = ReadReceipt(f)
f.Delete
if d = nil then raise new RuntimeException // selftest failed
dim guid as String
guid = DeviceGUID
if guid = "" then
MsgBox "Oops - no DeviceGUID on this computer?"
end if
guid = HexBytesToData (Array("00", "17", "f2", "c4", "bc", "c0"))
if not IsValid (guid, d, "com.example.sampleApp") then
raise new RuntimeException // selftest failed
end
#endif
End Sub
Protected Function DeviceGUID() As String
// The Mac’s GUID is the MAC address from network interface “en0”, see https://developer.apple.com/devcenter/mac/documents/validating.html
dim mac as String = SystemInformationMBS.MACAddressString
dim bytes() as String = mac.Split(":")
if bytes.Ubound = 5 then
return HexBytesToData (bytes)
end if
End Function
Protected Function HexBytesToData(bytes() as String) As MemoryBlock
dim mb as new MemoryBlock(6)
for i as Integer = 0 to 5
mb.Byte(i) = Val("&h"+bytes(i))
next
return mb
End Function
Protected Function IsValid(guid as String, receipt as Dictionary, bundleID as String) As Boolean
// Returns true if the given receipt (which comes from ‘ReadReceipt’) is valid
// for the given GUID (which is a unique code for a particular machine)
#if TargetMacOS
declare sub SHA1 lib “/usr/lib/libcrypto.dylib” (d as Ptr, n as Int32, md as Ptr)
if receipt <> nil then
dim input as MemoryBlock
input = guid + receipt.Value(Keys.kReceiptOpaqueValue) + receipt.Value(Keys.kReceiptBundleIdentiferData)
dim hash as new MemoryBlock(20) ' SHA_DIGEST_LENGTH
SHA1 (input, input.Size, hash)
dim hashFromReceipt as String = receipt.Value(Keys.kReceiptHash)
if StrComp (hash, hashFromReceipt, 0) = 0 then
return receipt.Value(Keys.kReceiptBundleIdentifer) = bundleID
end if
end if
#endif
End Function
Protected Function ReadReceipt(certFile as FolderItem) As Dictionary
// This function reads certain entries from the App’s certification receipt file
#if TargetMacOS
declare function d2i_PKCS7_fp lib “/usr/lib/libcrypto.dylib” (fp as Int32, p7 as Ptr) as Ptr
declare sub PKCS7_free lib “/usr/lib/libcrypto.dylib” (p7 as Ptr)
declare function OBJ_obj2nid lib “/usr/lib/libcrypto.dylib” (ASN1_OBJECT as Ptr) as Int32
declare function ASN1_get_object lib “/usr/lib/libcrypto.dylib” (ByRef pp as Ptr, ByRef plength as Int32, ByRef ptag as Int32, ByRef pclass as Int32, omax as Int32) as Int32
dim result as Dictionary
if certFile = nil then return nil
dim bs as BinaryStream
try
bs = BinaryStream.Open(certFile)
catch exc as RuntimeException
return nil
end
dim fp as Int32 = bs.Handle(BinaryStream.HandleTypeFilePointer)
if fp = 0 then return nil
dim p7 as Ptr = d2i_PKCS7_fp (fp, nil)
bs.Close
bs = nil
if p7 = nil then return nil
// is it signed?
dim nid as Int32 = OBJ_obj2nid (p7.PKCS7.type)
if nid <> 22 then goto bail1
// is data?
nid = OBJ_obj2nid (p7.PKCS7.d.PKCS7_SIGNED.contents.PKCS7.type)
if nid <> 21 then goto bail1
dim octets as Ptr = p7.PKCS7.d.PKCS7_SIGNED.contents.PKCS7.d
dim p, e as Ptr
p = octets.ASN1_STRING.data
dim l as Integer = octets.ASN1_STRING.length
e = p + Ptr(l)
dim res, type, xclass, length as Integer
res = ASN1_get_object(p, length, type, xclass, e - p)
if type <> 17 then goto bail1 ' V_ASN1_SET
result = new Dictionary
while p < e
call ASN1_get_object (p, length, type, xclass, e - p)
if type <> 16 then
exit ' V_ASN1_SEQUENCE
end
dim seq_end as Ptr = p + Ptr(length)
dim attr_type, attr_version as Integer
// Attribute type
call ASN1_get_object (p, length, type, xclass, seq_end - p)
if type = 2 and length = 1 then ' V_ASN1_INTEGER
attr_type = p.Byte(0)
end
p = p + Ptr(length)
// Attribute version
call ASN1_get_object (p, length, type, xclass, seq_end - p)
if type = 2 and length = 1 then ' V_ASN1_INTEGER
attr_version = p.Byte(0)
end
p = p + Ptr(length)
// Only parse attributes we're interested in
if ATTRS(attr_type) > ATTRS.ATTR_START and ATTRS(attr_type) < ATTRS.ATTR_END then
dim key as Keys
call ASN1_get_object (p, length, type, xclass, seq_end - p)
if type = 4 then ' V_ASN1_OCTET_STRING
// Bytes
if ATTRS(attr_type) = ATTRS.BUNDLE_ID or ATTRS(attr_type) = ATTRS.OPAQUE_VALUE or ATTRS(attr_type) = ATTRS.HASH then
select case ATTRS(attr_type)
case ATTRS.BUNDLE_ID
// This is included for hash generation
key = Keys.kReceiptBundleIdentiferData
case ATTRS.OPAQUE_VALUE
key = Keys.kReceiptOpaqueValue
case ATTRS.HASH
key = Keys.kReceiptHash
end select
dim mb as MemoryBlock = p
result.Value(key) = mb.StringValue(0, length)
end
// Strings
if ATTRS(attr_type) = ATTRS.BUNDLE_ID or ATTRS(attr_type) = ATTRS.VERSION then
dim str_type, str_length as Integer
dim str_p as Ptr = p
call ASN1_get_object (str_p, str_length, str_type, xclass, seq_end - str_p)
if str_type = 12 then ' V_ASN1_UTF8STRING
dim mb as MemoryBlock = str_p
dim str as String = mb.StringValue(0,str_length).DefineEncoding(Encodings.UTF8)
select case ATTRS(attr_type)
case ATTRS.BUNDLE_ID
key = Keys.kReceiptBundleIdentifer
case ATTRS.VERSION
key = Keys.kReceiptVersion
end select
result.Value(key) = str
end
end
end
p = p + Ptr(length)
end if
// Skip any remaining fields in this SEQUENCE
while p < seq_end
call ASN1_get_object (p, length, type, xclass, seq_end - p)
p = p + Ptr(length)
wend
wend
bail1:
PKCS7_free (p7)
return result
#endif
End Function
In the app open event we check the receipt with:
if not CertTools.IsValid (CertTools.DeviceGUID, CertTools.ReadReceipt(f), “de.pps4me.MASTestApp”) then
declare sub exit_ lib “System” alias “exit” (code as Integer)
exit_ (173)
end if
If I try to build my app in 64 Bit, I got these errors:
CertTools.ReadReceipt, line 41
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
res = ASN1_get_object (p, length, type, xclass, e-p)
CertTools.ReadReceipt, line 46
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
call ASN1_get_object (p, length, type, xclass, seq_end - p)
CertTools.ReadReceipt, line 56
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
res = ASN1_get_object (p, length, type, xclass, e-p)
CertTools.ReadReceipt, line 63
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
call ASN1_get_object (p, length, type, xclass, seq_end - p)
CertTools.ReadReceipt, line 73
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
call ASN1_get_object (p, length, type, xclass, seq_end - p)
CertTools.ReadReceipt, line 94
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
call ASN1_get_object (str_p, str_length, str_type, class, sequined - str_p)
CertTools.ReadReceipt, line 114
Expected (Ptr, Int32, Int32, Int32, Int32), but these arguments are (Ptr, Integer, Integer, Integer, Int64)
call ASN1_get_object (str_p, str_length, str_type, class, sequined - str_p)