Firefox同步问题

Firefox同步问题,firefox,encryption,sync,Firefox,Encryption,Sync,我想在我的一个iOS应用程序中读取Firefox Sync帐户的书签和历史记录,我让它适用于所有“新”帐户(使用电子邮件作为登录名的帐户),但对于旧帐户(用户仍然可以创建自己的登录名的帐户)它失败了。我不确定是什么问题。我很难在Firefox Sync API文档中找到所有相关细节,我经常不得不在别处搜索这些信息,所以我想我仍然缺少一些重要信息 我所做的是: 我有登录名、密码和同步密钥。第一步是获取“weave节点”,即存储用户数据的服务器。我们从 https://auth.services.m

我想在我的一个iOS应用程序中读取Firefox Sync帐户的书签和历史记录,我让它适用于所有“新”帐户(使用电子邮件作为登录名的帐户),但对于旧帐户(用户仍然可以创建自己的登录名的帐户)它失败了。我不确定是什么问题。我很难在Firefox Sync API文档中找到所有相关细节,我经常不得不在别处搜索这些信息,所以我想我仍然缺少一些重要信息

我所做的是:

我有登录名、密码和同步密钥。第一步是获取“weave节点”,即存储用户数据的服务器。我们从

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密钥来解密数据

但解密密钥只对新帐户有效(登录名是电子邮件地址),而对旧帐户无效。这是我的第二个问题:我需要做什么才能可靠地获得所有帐户的密钥

我想做的是使用同步密钥和登录名,创建一个加密密钥,可以用来解密上面的密文。这将是伪代码 像这样:

 encryptionkey = HMAC-SHA256(sync_key, "Sync-AES_256_CBC-HMAC256" + loginname + "\x01")
其中,sync键是用户输入的字符串中的base32解码值 loginname是原始登录名(旧帐户)或loginname(新帐户)中的SHA1/Base32编码字符串

为了破解“密文”,我正在做这个(目标C):

现在,“decryptedPayload”包含关于AES密钥的解密信息。这适用于新帐户,但对旧帐户解密失败(CCCrypt返回kCCDecodeError)。我错过了什么?我做错了什么

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