char* AWSClient::createSignature(const char* toSign) { /* Allocate memory for the signature */ char* signature = new char[HASH_HEX_LEN + 1](); /* Create the signature key */ /* + 4 for "AWS4" */ int keyLen = strlen(awsSecKey) + 4; char* key = new char[keyLen + 1](); sprintf(key, "AWS4%s", awsSecKey); /* repeatedly apply hmac with the appropriate values. See * http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html * for algorithm. */ char* k1 = hmacSha256(key, keyLen, awsDate, strlen(awsDate)); delete[] key; char* k2 = hmacSha256(k1, SHA256_DEC_HASH_LEN, awsRegion, strlen(awsRegion)); delete[] k1; char* k3 = hmacSha256(k2, SHA256_DEC_HASH_LEN, awsService, strlen(awsService)); delete[] k2; char* k4 = hmacSha256(k3, SHA256_DEC_HASH_LEN, "aws4_request", 12); delete[] k3; char* k5 = hmacSha256(k4, SHA256_DEC_HASH_LEN, toSign, strlen(toSign)); delete[] k4; /* Convert the chars in hash to hex for signature. */ for (int i = 0; i < SHA256_DEC_HASH_LEN; ++i) { sprintf(signature + 2 * i, "%02lx", 0xff & (unsigned long) k5[i]); } delete[] k5; return signature; }
Status Login::makeEdgeLogin(JsonPtr &result, const std::string &appId, const std::string &pin) { result = JsonPtr(); // Try 1: Use what we have: makeEdgeLoginLocal(result, appId).log(); // Failure is fine if (result) return Status(); // Try 2: Sync with the server: ABC_CHECK(update()); makeEdgeLoginLocal(result, appId).log(); // Failure is fine if (result) return Status(); // Try 3: Make a new login: { DataChunk loginKey; ABC_CHECK(randomData(loginKey, DATA_KEY_LENGTH)); JsonBox parentBox; ABC_CHECK(parentBox.encrypt(loginKey, dataKey_)); // Make the access credentials: DataChunk loginId; DataChunk loginAuth; ABC_CHECK(randomData(loginId, scryptDefaultSize)); ABC_CHECK(randomData(loginAuth, scryptDefaultSize)); JsonBox loginAuthBox; ABC_CHECK(loginAuthBox.encrypt(loginAuth, loginKey)); // Set up the outgoing Login object: LoginReplyJson server; ABC_CHECK(server.appIdSet(appId)); ABC_CHECK(server.loginIdSet(base64Encode(loginId))); ABC_CHECK(server.loginAuthBoxSet(loginAuthBox)); ABC_CHECK(server.parentBoxSet(parentBox)); LoginStashJson stash = server.clone(); ABC_CHECK(server.set("loginAuth", base64Encode(loginAuth))); // Set up the PIN, if we have one: if (pin.size()) { DataChunk pin2Key; ABC_CHECK(randomData(pin2Key, 32)); const auto pin2Id = hmacSha256(store.username(), pin2Key); const auto pin2Auth = hmacSha256(pin, pin2Key); // Create pin2Box: JsonBox pin2Box; ABC_CHECK(pin2Box.encrypt(loginKey, pin2Key)); // Create pin2KeyBox: JsonBox pin2KeyBox; ABC_CHECK(pin2KeyBox.encrypt(pin2Key, loginKey)); // Set up the server login: ABC_CHECK(server.set("pin2Id", base64Encode(pin2Id))); ABC_CHECK(server.set("pin2Auth", base64Encode(pin2Auth))); ABC_CHECK(server.pin2BoxSet(pin2Box)); ABC_CHECK(server.pin2KeyBoxSet(pin2KeyBox)); ABC_CHECK(stash.pin2KeySet(base64Encode(pin2Key))); } // Write to server: AuthJson authJson; ABC_CHECK(authJson.loginSet(*this)); ABC_CHECK(loginServerCreateChildLogin(authJson, server)); // Save to disk: LoginStashJson stashJson; ABC_CHECK(stashJson.load(paths.stashPath())); if (!stashJson.children().ok()) ABC_CHECK(stashJson.childrenSet(JsonArray())); ABC_CHECK(stashJson.children().append(stash)); ABC_CHECK(stashJson.save(paths.stashPath())); } ABC_CHECK(makeEdgeLoginLocal(result, appId).log()); if (!result) return ABC_ERROR(ABC_CC_Error, "Empty edge login after creation."); return Status(); }