我想从我的一个iOS应用程序中读取Firefox Sync帐户中的书签和历史记录,我让它适用于所有“新”帐户(那些使用电子邮件作为登录名的帐户),但是对于旧帐户(那些帐户失败)用户仍然可以创建自己的登录名称)。而且我不确定是什么问题。我在Firefox Sync API文档中找到所有相关细节时遇到了很多困难,我经常不得不在别处搜索这些信息,所以我想我仍然缺少一些重要的信息。
我所做的是以下内容:
我有登录名,密码和同步密钥。第一步是获取“编织节点”,即存储用户数据的服务器。我们从
获取此信息https://auth.services.mozilla.com/user/1.0/[loginname]/node/weave"
并使用登录名和密码进行此请求的基本身份验证。这里的第一个问题是“[loginname]”从未被接受。我发现当loginname是一个电子邮件地址时,它必须是SHA1和base32编码。我没有在API文档中找到这些信息,我确实在其他地方的博客中找到了它。对于登录名不是电子邮件地址的旧帐户,似乎不能通过SHA1和base32进行编码。
所以我的第一个问题是,什么时候需要SHA1-base32编码?仅当登录名是电子邮件地址时,或者当旧式登录名包含某些字符时(如果首先可以使用任何特殊字符)?
这第一步效果很好。我确实为旧账户和新账户获得了“编织节点”,所以 登录名和密码被接受并且似乎被正确编码(至少在我的测试用例中 新帐户使用SHA1 / base32,旧帐户使用“原始”数据。
下一步是检索用于解密书签数据的密钥。我从
获得这些数据https://[Weave node]/1.1/[login name]/storage/crypto/keys
再次使用基本身份验证。
我确实得到了JSON响应,其中包括“密文”,“iv”和“hmac”,我可以从中创建AES密钥来解密数据。
但解密密钥仅适用于新帐户(登录名是电子邮件地址),旧帐户失败。这是我的第二个问题:我需要做些什么才能可靠地获取所有帐户的密钥?
AFAIK我应该做的是使用sync-key和登录名,并创建一个加密密钥,可以用来解密上面的密文。所以这将是伪代码 看起来像这样:
encryptionkey = HMAC-SHA256(sync_key, "Sync-AES_256_CBC-HMAC256" + loginname + "\x01")
其中sync-key是用户输入的字符串中的base32解码值 loginname是原始登录名(旧帐户)或loginname(新帐户)中的SHA1 / Base32编码字符串。
要解码“密文”我正在这样做(目标C):
NSString *decryptedPayload = nil;
NSData *encryptionkey = ... // See above, just encapsuled as NSData object.
NSData *cipherdata = [cyphertext base64DecodedData];
NSData *ivdata = [iv base64DecodedData];
size_t bufferSize = ([cipherdata length] + kCCBlockSizeAES128);
void *buffer = calloc(bufferSize, sizeof(uint8_t));
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
[encryptionkey bytes], [encryptionkey length],
[ivdata bytes],
[cipherdata bytes], [cipherdata length],
buffer, bufferSize, &numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
NSData *decryptedData = [NSData dataWithBytes:buffer length:numBytesDecrypted];
decryptedPayload = [NSString stringWithData:resData];
}
free(buffer);
现在“decryptedPayload”包含有关AES密钥的解密信息。这适用于新帐户,但旧帐户的解密失败(CCCrypt返回kCCDecodeError)。我错过了什么?我做错了什么?