Firefox Sync issues
I want to read the bookmarks and history from Firefox Sync accounts in one of my iOS Apps and I got it working for all "new" accounts (those with an email as login name), but it fails for old accounts (those where the user could still create their own login name). And I'm not sure what's the problem. I had many difficulties to find all the relevant details in the Firefox Sync API documentation, I often had to search elsewhere for the information, So I guess I'm still missing some important information.
What I do is the following:
I have the login name, password and sync-key. The first step is to get the "weave node", the server where the users data is stored. We get this information from
https://auth.services.mozilla.com/user/1.0/[loginname]/node/weave"
and using the loginname and password for basic authentication for this request. The first problem here was that the "[loginname]" was never accepted. I found out that when the loginname is an email address, it must be SHA1 and base32 encoded. I didn't find this information in the API documentation, I did find it in a blog elsewhere. For older accounts where the login name is not an email address, it seems that it must not be encoded via SHA1 and base32.
So my first question is, when exactly is the SHA1-base32 encoding necessary? Only when the login name is an email address, or also when the old-style login name contains certain characters (in case one could use any special characters in the first place)?
This first step works well. I do get the "weave node" for old and new accounts just fine, so loginname and password is accepted and seems to be encoded correctly (at least in my test cases with SHA1/base32 for new accounts and "raw" data for old accounts).
The next step would be to retrieve the keys for decrypting the bookmarks data. I get this data from
https://[Weave node]/1.1/[login name]/storage/crypto/keys
again with basic authentication.
I do get the JSON response just fine which includes the "ciphertext", "iv" and "hmac" from which I should be able to create the AES keys to decrypt the data.
But decrypting the keys does only work for new accounts (login name is an email address) and fails for old accounts. And this is my second question: What do I need to do开发者_运维知识库 exactly to reliably be able to get the keys for all accounts?
AFAIK what I supposed to do is to use the sync-key and the login name and create an encryption key which can be used to decrypt the ciphertext from above. So this would be in pseudo code look like this:
encryptionkey = HMAC-SHA256(sync_key, "Sync-AES_256_CBC-HMAC256" + loginname + "\x01")
Where the sync-key is the base32 decoded value from the string that was entered by the user and the loginname is either the raw login name (old accounts) or the SHA1/Base32 encoded string from the loginname (new accounts).
And to decode the "ciphertext" I'm doing this (Objective 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);
Now "decryptedPayload" contains the decrypted information about the AES keys. This works fine for new accounts, but decrypting fails for old accounts (CCCrypt returns kCCDecodeError). What do I miss? What am I doing wrong?
精彩评论