I have a unsigned mobileconfig file in xml format (template) generated by iphone configuration utility. I would like to encrypt and sign it using openssl and be able to inst
The link you mentioned talks only about signing the iPhone configuration profile. Does atleast signing a profile works for you?
You can verify that signature generated by your code is correct using openssl command line utility. Write the generated signature to a file and use following command to verify signature and extract original data from pkcs#7 signature.openssl smime -verify -inform DER -in signed_config.p7s -signer your_signing_certificate -out data.txt
Incase if still anybody is having issues with signing and encrypting the profile with Ruby, following answer would be useful.
I have used OpenSSL module available in Ruby and Plist gem.
Consider a passcode restriction profile.
passcode_payload ={
'PayloadUUID' => 'RANDOM_STRING_UUID',
'PayloadOrganization' => 'PayloadOrganization',
'PayloadVersion' => 1,
'PayloadIdentifier' => 'com.test.PayloadIdentifier',
'PayloadType' => 'Configuration',
'PayloadDisplayName' => 'PayloadDisplayName',
'PayloadRemovalDisallowed' => false
}
passcode_payload_content = {
'PayloadDescription' => 'PayloadDescription',
'PayloadDisplayName' => 'PayloadDisplayName',
'PayloadIdentifier' => 'PayloadIdentifier',
'PayloadOrganization' => 'PayloadOrganization',
'PayloadType' => 'com.apple.mobiledevice.passwordpolicy',
'PayloadUUID' => "RANDOM_STRING_UUID",
'PayloadVersion' => 1,
'allowSimple' => true,
'forcePIN' => true
'maxPINAgeInDays' => 20,
'minComplexChars' => 1,
'minLength' => 4,
'requireAlphanumeric' => true
}
**
**
Usually for a normal profile the passcode_payload_content
goes into the passcode_payload['PayloadContent']
as array of dictionaries.
passcode_payload['PayloadContent'] = [passcode_payload_content]
But for an encrypted profile, PayloadContent
should be removed and EncryptedPayloadContent
should be used as per the configuration profile key reference document.
from the doc,
To encrypt a profile do the following:
- Remove the
PayloadContent
array and serialize it as a proper plist.- Note that the top-level object in this plist is an array, not a dictionary.
- CMS-encrypt the serialized plist as enveloped data. Serialize the encrypted data in DER format.
- Set the serialized data as the value of as a Data plist item in the profile, using the key
EncryptedPayloadContent
Since top level object in the plist should be an array
passcode_payload_content_array = [passcode_payload_content]
Serializing to proper plist
to_be_encrypted_plist = passcode_payload_content_array.to_plist
Encrypting the certificate payload content,
device_certificate = OpenSSL::X509::Certificate.new File.read('deviceIdentityCertificate.pem')
encrypted_payload = OpenSSL::PKCS7.encrypt([device_certificate],to_be_encrypted_plist, OpenSSL::Cipher::Cipher::new("des-ede3-cbc"),OpenSSL::PKCS7::BINARY)
Add encrypted payload content to the original payload in der format
passcode_payload['EncryptedPayloadContent'] = StringIO.new(encrypted_payload.to_der)
**
**
signed_passcode_profile = OpenSSL::PKCS7.sign(SSL_CERTIFICATE, SSL_KEY, passcode_payload.to_plist, [], OpenSSL::PKCS7::BINARY)
At last, you can use
send_data signed_passcode_profile.to_der, :type => "application/x-apple-aspen-config"
to send the payload.