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;
}
Exemplo n.º 2
0
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();
}