在CUDA上尝试使用RSA加密

时间:2019-04-17 10:50:12

标签: c cuda gpu nvcc

我正在尝试使用CUDA使用RSA算法来加速加密。我无法在内核函数中正确执行幂模运算。

我正在使用AWS 9.0版本V9.0.176上的Cuda编译工具进行编译。

#include <cstdio>
#include <math.h>
#include "main.h"

// Kernel function to encrypt the message (m_in) elements into cipher (c_out)
__global__
void enc(int numElements, int e, int n, int *m_in, int *c_out)
{
    int index = blockIdx.x * blockDim.x + threadIdx.x;
    int stride = blockDim.x * gridDim.x;

    printf("e = %d, n = %d, numElements = %d\n", e, n, numElements);
    for (int i = index; i < numElements; i += stride)
    {
// POINT OF ERROR //
        // c_out[i] = (m_in[i]^e) % n;     //**GIVES WRONG RESULTS**
         c_out[i] = __pow(m_in[i], e) % n; //**GIVES, error: expression must have integral or enum type**
    }


}
// This function is called from main() from other file.
int* cuda_rsa(int numElements, int* data, int public_key, int key_length)
{
    int e = public_key;
    int n = key_length;

    // Allocate Unified Memory – accessible from CPU or GPU
    int* message_array;
    cudaMallocManaged(&message_array, numElements*sizeof(int));
    int* cipher_shared_array;       //Array shared by CPU and GPU
    cudaMallocManaged(&cipher_shared_array, numElements*sizeof(int));

    int* cipher_array = (int*)malloc(numElements * sizeof(int));

    //Put message array to be encrypted in a managed array
    for(int i=0; i<numElements; i++)
    {
        message_array[i] = data[i];
    }

    // Run kernel on 16M elements on the GPU
    enc<<<1, 1>>>(numElements, e, n, message_array, cipher_shared_array);

    // Wait for GPU to finish before accessing on host
    cudaDeviceSynchronize();

    //Copy into a host array and pass it to main() function for verification. 
    //Ignored memory leaks.
    for(int i=0; i<numElements; i++)
    {
        cipher_array[i] = cipher_shared_array[i];
    }
    return (cipher_array);
}

请帮助我解决此错误。 如何在CUDA内核上实现功率模(如下)?

(x ^ y) % n;

我将非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

在C或C ++中,这是

(x^y) 

不会将x提高到y的幂。 It performs a bitwise exclusive-or operation。这就是为什么您第一次意识到并没有给出正确答案的原因。

在C或C ++中,模运算符:

%

only defined for integer arguments。即使您将整数传递给__pow()函数,该函数的返回结果仍是double(即浮点数,而不是整数数)。

我不知道您需要执行的数学运算的详细信息,但是例如,如果将__pow的结果强制转换为int,则该编译错误将消失。 对于您希望执行的任何算术运算来说,这可能有效或无效。 (例如,您可能希望将其转换为“长”整数)。

这样做之后,您将遇到另一个编译错误。最简单的方法是使用pow()而不是__pow()

c_out[i] = (int)pow(m_in[i], e) % n;

如果您实际上是在尝试使用the CUDA fast-math intrinsic,则应该使用__powf而不是__pow

c_out[i] = (int)__powf(m_in[i], e) % n;

请注意,快速数学内在函数通常会降低精度。

由于这些加幂功能正在执行浮点算术(即使您传递的是整数),也有可能获得一些可能出乎意料的结果。例如,如果将5乘以2的幂,则有可能获得24.9999999999而不是25。如果仅将其强制转换为整数,则将截断为24。因此,您可能需要研究将结果四舍五入到最接近的整数,而不是强制转换。但是,我还没有研究您想要执行的数学。