ios - 如何通过命令行在 Xcode 中登录 Apple ID?

标签 ios xcode macos terminal

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

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

有没有办法通过命令行将 Apple ID 添加到 Xcode?


这是我已经做过的:

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

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

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

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

最佳答案

首先,我不确定您尝试做的是不是一个好主意。

请记住,如果您要将 Xcode 设置为在每次构建时自动请求 iOS 开发人员证书,并且该构建在不同的机器上执行(例如,托管 CI,例如 Travis 或 Azure Pipelines ),您的 iOS 开发者证书将每次被撤销和重新生成。

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

我认为 FaSTLane 已经可以做到这一切了。如果您正在寻找灵感,Azure Pipelines 具有类似的功能。有一个任务installs a provisioning profile ,一个installs a certificate还有一个builds an Xcode project and allows you to override the certificate and provisioning profiles used when signing your product .


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

用于加密文件的 key 是使用 PBKDF2(基于密码的 key 派生函数 2)从密码派生的,使用这些参数:

  • 哈希函数:SHA256
  • 密码:您的密码
  • Salt:密码的字节表示,使用 UTF8 编码
  • 哈希迭代次数:33333
  • key 长度:10

“魔数(Magic Number)”是 Apple 的 SecKeyDeriveFromPassword 函数使用的默认值,as described hereimplemented here

获得加密 key 后,即可解密文件。您将需要一个初始化向量 (IV),这也是 Apple 使用的默认值 - 一个完全由零组成的 16 字节数组。

在 C 中,您应该能够使用这样的代码来生成加密 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);

要解密数据,请使用:

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);

希望对您有所帮助!

关于ios - 如何通过命令行在 Xcode 中登录 Apple ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54787309/

相关文章:

objective-c - 如何将 NSLayoutConstraint 添加到以编程方式创建的 NSView 子类的 subview 中?

java - 在 Mac 上使用 CodeRunner IDE 运行 Java 项目

ios - 如何获取 PDF 格式的 UITableView 快照

ios - 多重纹理的最有效方法-iOS,OpenGL ES2,优化

ios - 是否可以将 NSMutableArray 存储在 NSObject 中?

ios - 如何使用照片框架获取引用网址的文件名?

objective-c - 一个工作区中的多个 pod

xcode - 在 Xcode6 中将 Swift 文件导入其他 Swift 文件

xcode - XCode7.2.1崩溃并出现以下错误

objective-c - 在 Objective-C 中调用指定的初始化器之后如何执行额外的初始化? ( self =[ self ...)