How to add custom encryption to gRPC C++?

Viewed 350

I'm trying to add custom encryption in gRPC C++ client.

In some port like Python there are serializer params for unary_unary calls.

I've seen some issue saying it could be archived by using custom Codec but that's not possible in C++.

So is there any chance that I could add custom encryption with gRPC C++ API?

1 Answers

Posting my partitial solution here. I can encrypt the request payload but I can't decrypt the response body. I created a Inceptor and hook all methods.

class TestInterceptor: public grpc::experimental::Interceptor {
    void Intercept(grpc::experimental::InterceptorBatchMethods* methods) override {
        const uint8_t aes_key[] = "0123456789123456";
        const uint8_t aes_iv[] = "0123456789123456";
        if (methods->QueryInterceptionHookPoint(grpc::experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)) {
            auto s1 = methods->GetSerializedSendMessage();
            std::vector<grpc::Slice> v;
            s1->Dump(&v);
            size_t l = 0;
            for (const auto& s: v) {
                l += s.size();
            }
            ustring buf;
            buf.resize(l);
            size_t ptr = 0;
            for (const auto& s: v) {
                memcpy(buf.data() + ptr, s.begin(), s.size());
                ptr += s.size();
            }

            // encrypt
            ustring crypted = Crypto::aes_encrypt(buf, aes_key, aes_iv);
            grpc::Slice new_slice(crypted.data(), crypted.size());
            grpc::ByteBuffer s2(&new_slice, 1);
            s1->Swap(&s2);
        }
        if (methods->QueryInterceptionHookPoint(grpc::experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)) {
            char* s2 = (char *) methods->GetRecvMessage();
        }
        methods->Proceed();
    }
};

class TestInterceptorFactory: public grpc::experimental::ClientInterceptorFactoryInterface {
    grpc::experimental::Interceptor* CreateClientInterceptor(grpc::experimental::ClientRpcInfo* info) override {
        auto *m = info->method();
        return new TestInterceptor();
    }
};

For the channel creation, simply pass the interceptor.

    std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface> fac_ptr = std::make_unique<TestInterceptorFactory>();
    std::vector<std::unique_ptr<grpc::experimental::ClientInterceptorFactoryInterface>> vec = {};
    vec.push_back(std::move(fac_ptr));
    m_channel = grpc::experimental::CreateCustomChannelWithInterceptors(
            "example.com",
            channel_credentials,
            channel_arguments,
            std::move(vec)
    );
Related