如何通过命令行在Xcode中登录Apple ID? [英] How to sign in to Apple ID in Xcode via command line?

查看:287
本文介绍了如何通过命令行在Xcode中登录Apple ID?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我继承了Xcode设置,该设置构建了一个使用自动签名进行开发的iOS应用.我现在的任务是为此项目构建一些CI设置,但是无需更改实际的Xcode项目.这意味着我暂时无法切换为手动签名.

由于该项目在本地运行良好,所以我没想到这会成为一个大问题,但是事实证明,自动签名(显然是事后看来)需要将您的Xcode登录到Apple ID中(Xcode => Preferences) =>帐户),该帐户应用于自动创建证书.

是否可以通过命令行将Apple ID添加到Xcode?


这是我已经做过的:

我已经环顾四周,但是无法通过Google找到任何明显的答案.在StackOverflow上,这里的所有问题和答案总是提到只需快速打开Xcode并输入您的凭据",不幸的是,这不适用于我们的CI设置.

我找到了 Jenkins的"Xcode插件" ,可让您导入可以从Xcode导出的.developerprofile.但是我的Java真的很生锈,我无法完全理解这个仅"是导入配置文件和身份,还是帐户列表.

我自己玩着.developerprofile,它似乎在.zip文件中包括了帐户信息(以及所有证书等),因此您可以提取文件.其中还包括accounts.keychainaccounts.plist,但是它们都使用密码进行了加密-我不知道该如何使用它来获取真实数据以进一步进行调查.

如果添加新的Apple ID,我还试图找出Xcode最初将信息保存在何处:似乎将帐户名和密码以及一些令牌放入登录"(com.apple.gs.xcode.auth.com.apple.account.AppleIDAuthentication.token)和"iCloud"中"钥匙串(Xcode-AlternateDSIDXcode-Token).我也无法手动创建钥匙串"访问中的现有条目,因为在手动创建应用程序密码时,访问控制"->该项目的访问组:"总是不同的.将项目复制到要导出的新钥匙串中也不起作用,因为iCloud钥匙串不允许我将内容复制到新钥匙串中(即使在iCloud中禁用了钥匙串同步之后,该钥匙串也被命名为本地"项目").

解决方案

首先,我不确定您要做什么是一个好主意.

请记住,如果要设置Xcode以在每个版本上自动请求iOS开发者证书 ,并且该版本在不同的机器上执行(例如,托管的CI,例如Travis或Azure Pipelines) ),那么您的iOS开发者证书将每次被吊销并重新生成.

(我认为)更好的选择是通过开发人员配置文件导出iOS开发证书和配置文件,然后在构建环境中导入开发证书和配置文件.然后,如果需要,更新您的Xcode项目以使用您刚导入的证书和配置文件.

我认为Fastlane已经可以做很多事情了.如果您正在寻找灵感,Azure Pipelines具有类似的功能.一个具有安装配置文件的任务,一个其中安装证书和其中一个构建一个Xcode项目,并允许您覆盖对产品进行签名时使用的证书和配置文件.


话虽如此,accounts.plistaccounts.keychain可能包含您要查找的信息.这两个文件都使用AES加密进行了加密.

使用以下参数,使用PBKDF2(基于密码的密钥派生功能2)从密码中派生用于加密文件的密钥:

  • 散列函数:SHA256
  • 密码:您的密码
  • 盐:使用UTF8编码的密码的字节表示形式
  • 哈希迭代次数:33333
  • 密钥长度:10

魔术数字"是Apple的SecKeyDeriveFromPassword函数使用的默认值,如此处所述, 在此处实现

一旦有了加密密钥,就可以解密文件.您将需要一个初始化向量(IV),它也是Apple使用的默认值-一个完全由零组成的16字节数组.

在C语言中,您应该能够使用如下使用代码来生成加密密钥:

 CFStringRef password = CFSTR("verysecretstuff");
const char* saltBytes = CFStringGetCStringPtr(password, kCFStringEncodingUTF8);
CFDataRef salt = CFDataCreate(NULL, saltBytes, CFStringGetLength(password));

int keySizeInBits = kSecAES128;
CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeInBits);

int rounds = 33333;
CFNumberRef numberOfRounds = CFNumberCreate(NULL, kCFNumberIntType, &rounds);

CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(NULL, 3, NULL, NULL);
CFDictionaryAddValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES);
CFDictionaryAddValue(parameters, kSecAttrKeySizeInBits, keySize);
CFDictionaryAddValue(parameters, kSecAttrPRF, kSecAttrPRFHmacAlgSHA256);
CFDictionaryAddValue(parameters, kSecAttrRounds, numberOfRounds);
CFDictionaryAddValue(parameters, kSecAttrSalt, salt);

CFErrorRef error = NULL;
SecKeyRef key = SecKeyDeriveFromPassword(password, parameters, &error);
 

要解密数据,请使用:

 const UInt *bytes = NULL; // Encrypted data
CFDataRef data = CFDataCreate(NULL, bytes, length);

CFErrorRef error = NULL;
SecTransformRef transform = SecDecryptTransformCreate(key, &error);
if ( transform == NULL )
{
    CFShow(error);
    CFRelease(error);
}

SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, &error);
SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, &error);
SecTransformSetAttribute(transform, kSecTransformInputAttributeName, data, &error);
CFDataRef result = SecTransformExecute(transform, &error);

CFShow(result);

CFRelease(result);
CFRelease(data);
CFRelease(transform);
 

希望有帮助!

I inherited a Xcode setup that builds an iOS app that uses Automatic Signing for the development builds. I now have the task to build some CI setup for this project, but without changing the actual Xcode project. This means I can't switch to manual signing for now.

As the project is building fine locally, I didn't expect this to be a big problem, but it turns out Automatic Signing (obviously, in hindsight) needs your Xcode to be signed into the Apple ID (Xcode => Preferences => Accounts) that should be used for automatically creating certificates.

Is there a way to add an Apple ID to Xcode via the command line?


This is what I already did:

I looked around already, but could not find any obvious answers via Google. All the questions and answers here on StackOverflow always mention "Just quickly open Xcode and enter your credentials" which unfortunately does not work on our CI setup.

I found this Jenkins "Xcode Plugin" that lets you import a .developerprofile that you can export from Xcode. But my Java is really rusty and I couldn't fully understand if this "only" imports profiles and identities, or also the list of accounts.

Playing around with an .developerprofile myself, it seems to include the account information (and all the certificates etc.) in a .zip file, so you can extract the files. That also includes a accounts.keychain and accounts.plist, but those are both encrypted with the password - which I don't know how to use to get to the real data to investigate there further.

I also tried to find out where Xcode originally saves the information if you add a new Apple ID: It seems to put the account names and passwords, and some token, into your "login" (com.apple.gs.xcode.auth.com.apple.account.AppleIDAuthentication.token) and "iCloud" keychain (Xcode-AlternateDSID and Xcode-Token). I also couldn't recreate the existing entries in Keychain access manually, as "Access Control" -> "Access group for this item:" was always different when creating an application password manually. Copying the items into a new keychain to be exported also didn't work, as the iCloud keychain doesn't let me copy stuff over to a new one (even after disabling keychain sync in iCloud, so the keychain is named "local items").

解决方案

First off, I'm not sure that what you are trying to do is a good idea.

Keep in mind that if you are going to set up Xcode to automatically request iOS developer certificates on every build, and that build executes on different machines (say, hosted CI such as Travis or Azure Pipelines), your iOS developer certificate will be revoked and regenerated every time.

A much better option (in my opinion) is to export your iOS development certificates and provisioning profiles via your developer profile, and import the development certificate and provisioning profile in your build environment. Then, if needed, update your Xcode project to use the certificate and profile you've just imported.

I think Fastlane can already do pretty much all that. If you're looking for inspiration, Azure Pipelines has similar functionality. The have a task which installs a provisioning profile, one which installs a certificate and one which builds an Xcode project and allows you to override the certificate and provisioning profiles used when signing your product.


Having said that, the accounts.plist and the accounts.keychain probably contain the information you are looking for. Both files are encrypted using AES encryption.

The key used to encrypt the file is derived from the password using PBKDF2 (Password-Based Key Derivation Function 2), using these parameters:

  • Hashing function: SHA256
  • Password: Your password
  • Salt: The byte representation of your password, using UTF8-encoding
  • Number of hashing iterations: 33333
  • Key length: 10

The 'magic numbers' are the default values used by Apple's SecKeyDeriveFromPassword function, as described here and implemented here

Once you have your encryption key, you can decrypt the file. You'll need an initialization vector (IV), which again is the default value used by Apple - a 16-byte array consisting entirely of zeros.

In C, you should be able to use use code like this to generate the encryption key:

CFStringRef password = CFSTR("verysecretstuff");
const char* saltBytes = CFStringGetCStringPtr(password, kCFStringEncodingUTF8);
CFDataRef salt = CFDataCreate(NULL, saltBytes, CFStringGetLength(password));

int keySizeInBits = kSecAES128;
CFNumberRef keySize = CFNumberCreate(NULL, kCFNumberIntType, &keySizeInBits);

int rounds = 33333;
CFNumberRef numberOfRounds = CFNumberCreate(NULL, kCFNumberIntType, &rounds);

CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(NULL, 3, NULL, NULL);
CFDictionaryAddValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeAES);
CFDictionaryAddValue(parameters, kSecAttrKeySizeInBits, keySize);
CFDictionaryAddValue(parameters, kSecAttrPRF, kSecAttrPRFHmacAlgSHA256);
CFDictionaryAddValue(parameters, kSecAttrRounds, numberOfRounds);
CFDictionaryAddValue(parameters, kSecAttrSalt, salt);

CFErrorRef error = NULL;
SecKeyRef key = SecKeyDeriveFromPassword(password, parameters, &error);

To decrypt the data, use:

const UInt *bytes = NULL; // Encrypted data
CFDataRef data = CFDataCreate(NULL, bytes, length);

CFErrorRef error = NULL;
SecTransformRef transform = SecDecryptTransformCreate(key, &error);
if ( transform == NULL )
{
    CFShow(error);
    CFRelease(error);
}

SecTransformSetAttribute(transform, kSecEncryptionMode, kSecModeCBCKey, &error);
SecTransformSetAttribute(transform, kSecPaddingKey, kSecPaddingPKCS7Key, &error);
SecTransformSetAttribute(transform, kSecTransformInputAttributeName, data, &error);
CFDataRef result = SecTransformExecute(transform, &error);

CFShow(result);

CFRelease(result);
CFRelease(data);
CFRelease(transform);

Hope it helps!

这篇关于如何通过命令行在Xcode中登录Apple ID?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆