how to encrypt and sign iphone mobile configuration file using Ruby

后端 未结 2 1884
不知归路
不知归路 2021-01-01 05:41

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

2条回答
  •  盖世英雄少女心
    2021-01-01 06:17

    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
                }
    

    **

    Encryption

    **

    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)
    

    **

    Signing

    **

    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.

提交回复
热议问题