⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rabinmiller.c

📁 IBE是一种非对称密码技术
💻 C
📖 第 1 页 / 共 2 页
字号:

    /* The Rabin-Miller test starts out by representing the prime
     * candidate as
     *    candidate = 1 + (mVal * 2^expo)
     * This is what's going on.
     *    Find candidate - 1, this is an even number (candidate is odd)
     *    How many trailing 0's are there in the binary representation
     *      of candidate - 1. That's expo.
     *    Shift candidate right expo bits, that's now mVal.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &mVal);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->MpIntToMpInt (primeCandidate, mVal);
    if (status != 0)
      break;

    /* Find primeCandidate - 1. We'll use it for comparison purposes
     * later.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &candidateMinusOne);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->MpIntToMpInt (primeCandidate, candidateMinusOne);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->SetBit (candidateMinusOne, 0, 0);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &randVal);
    if (status != 0)
      break;

    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->CreateMpInt ((Pointer)mpCtx, &zVal);
    if (status != 0)
      break;

    /* Find the number of trailing 0's. After subtracting 1, the 0'th
     * bit is 0, so start looking at bit position 1. Use index as a
     * temp variable.
     */
    for (expo = 1; expo < primeSizeBits; ++expo)
    {
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->GetBit (mVal, expo, &index);
      if (status != 0)
        break;
      if (index == 1)
        break;
    }

    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    if (expo >= primeSizeBits)
      status = VT_ERROR_MP_INT_RANGE;
    if (status != 0)
      break;

    /* Step 2, find expo and mVal, we have expo, but the MpInt mVal is
     * currently equal to candidate - 1. Shift it right expo bits and
     * we have mVal.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->ShiftRightBits (mVal, expo);
    if (status != 0)
      break;

    /* Perform the Rabin-Miller algorithm the prescribed number of
     * times.
     */
    for (index = 0; index < iterationCount; ++index)
    {
      /* Step 3, get a random number < candidate.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = GetRandomValue (
        libCtx, mpCtx, primeCandidate, buffer, bufferSize);
      if (status != 0)
        break;

      VOLT_SET_FNCT_LINE (fnctLine)
      buffer[0] &= 0x7f;
      status = mpCtx->OctetStringToMpInt (0, buffer, bufferSize, randVal);
      if (status != 0)
        break;

      /* Step 4, find zVal = (randVal ^ mVal) mod candidate
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->ModExp (randVal, mVal, primeCandidate, zVal);
      if (status != 0)
        break;

      /* Step 5, if zVal == 1 or zVal == candidate - 1, the test passes
       * this iteration.
       */
      VOLT_SET_FNCT_LINE (fnctLine)
      status = mpCtx->MpIntToInt (zVal, 1, &value);
      if (status != VT_ERROR_MP_INT_RANGE)
      {
        if (status != 0)
          break;

        if (value == 1)
          continue;
      }
      else
      {
        VOLT_SET_FNCT_LINE (fnctLine)
        status = mpCtx->Compare (zVal, candidateMinusOne, &compareResult);
        if (status != 0)
          break;

        if (compareResult == 0)
          continue;
      }

      /* Step 6, square zVal, make a comparison (step 5), then loop.
       */
      for (count = 1; count < expo; ++count)
      {
        VOLT_SET_FNCT_LINE (fnctLine)
        status = mpCtx->Square (zVal, randVal);
        if (status != 0)
          break;

        VOLT_SET_FNCT_LINE (fnctLine)
        status = mpCtx->ModReduce (randVal, primeCandidate, zVal);
        if (status != 0)
          break;

        /* Step 5 comparison, if zVal now == candidate - 1, this
         * iteration passes, move on to the next random number.
         */
        VOLT_SET_FNCT_LINE (fnctLine)
        status = mpCtx->Compare (zVal, candidateMinusOne, &compareResult);
        if (status != 0)
          break;

        if (compareResult == 0)
          break;

        /* If zVal is now 1, we know the candidate is not prime.
         */
        VOLT_SET_FNCT_LINE (fnctLine)
        status = mpCtx->MpIntToInt (zVal, 1,&value);
        if (status != VT_ERROR_MP_INT_RANGE)
        {
          if (status != 0)
            break;

          /* Set expo to count to skip the rest of the zVal^2 tests, we
           * know the number is not prime.
           */
          if (value == 1)
            count = expo;
        }
        status = 0;
      }
      if (status != 0)
        break;

      /* If we broke out of the step 6 loop early, the comparison was
       * equal, we can move on to the next iteration.
       * If we looped step 6 every time and found no match, this number
       * is not prime. Exit the Rabin-Miller iterations.
       */
      if (count >= expo)
        break;
    }
    if (status != 0)
      break;

    /* If we didn't break out of the loop early, we did every
     * iteration, which means the number passes.
     */
    if (index >= iterationCount)
      *isPrime = 1;

  } while (0);

  /* We cleared the low order bit for comparison purposes, set it back.
   */
  mpCtx->SetBit (primeCandidate, 0, 1);

  if (buffer != (unsigned char *)0)
    Z2Free (buffer);

  mpCtx->DestroyMpInt (&candidateMinusOne);
  mpCtx->DestroyMpInt (&mVal);
  mpCtx->DestroyMpInt (&zVal);
  mpCtx->DestroyMpInt (&randVal);

  VOLT_LOG_ERROR_COMPARE (
    status, (VtLibCtx)libCtx, status, errorType, fnctLine,
    "VoltRabinMillerTest", (char *)0)

  return (status);
}

int VoltCheckRelativePrime (
   VoltMpIntCtx *mpCtx,
   VoltMpInt *relativePrime,
   VoltMpInt *prime,
   VoltMpInt *temp1,
   VoltMpInt *temp2,
   unsigned int *relPrime
   )
{
  int status;
  unsigned int bitLen;
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  /* Initialize to true, if they turn out not to be relatively prime,
   * we'll reset it.
   */
  *relPrime = 1;

  do
  {
    /* Find prime / relativePrime. If the remainder is 1, then p - 1
     * would not be relatively prime.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->Divide (prime, relativePrime, temp1, temp2);
    if (status != 0)
      break;

    /* If the bitLen of the remainder is not 1, the remainder cannot be
     * 1, so the values are relatively prime.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->GetBitLength (temp2, &bitLen);
    if (status != 0)
      break;

    if (bitLen != 1)
      break;

    /* The bit length is 1, but there is a very slight chance that the
     * remainder is 0. That would mean prime (actually a prime
     * candidate) is a multiple of relativePrime. Even though the
     * chance is slim, we have to program for the possibility.
     * Use bitLen as a temp variable.
     */
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->GetBit (temp2, 0, &bitLen);
    if (status != 0)
      break;

    /* If the bit is 0, the remainder is 0, so p - 1 and relativePrime
     * are indeed relatively prime.
     */
    if (bitLen != 0)
      *relPrime = 0;

  } while (0);

  VOLT_LOG_ERROR_INFO_COMPARE (
    status, 0, mpCtx, status, 0, 0,
    (char *)0, "VoltCheckRelativePrime", fnctLine, (char *)0)

  return (status);
}

static int GetRandomValue (
   VoltLibCtx *libCtx,
   VoltMpIntCtx *mpCtx,
   VoltMpInt *primeCandidate,
   unsigned char *buffer,
   unsigned int bufferLen
   )
{
  int status;
  unsigned int sign, pLen, bytesNeeded, copyCount, offset, digestLen;
  VtAlgorithmObject digester = (VtAlgorithmObject)0;
  unsigned char *pBuf = (unsigned char *)0;
  unsigned char digest[20];
  VOLT_DECLARE_ERROR_TYPE (errorType)
  VOLT_DECLARE_FNCT_LINE (fnctLine)

  do
  {
    /* Get the primeCandidate into a buffer.
     */
    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->MpIntToOctetString (
      primeCandidate, &sign, (unsigned char *)0, 0, &pLen);
    if (status == 0)
      status = VT_ERROR_GENERAL;
    if (status != VT_ERROR_BUFFER_TOO_SMALL)
      break;

    VOLT_SET_ERROR_TYPE (errorType, VT_ERROR_TYPE_PRIMARY)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = VT_ERROR_MEMORY;
    pBuf = (unsigned char *)Z2Malloc (pLen, VOLT_MEMORY_SENSITIVE);
    if (pBuf == (unsigned char *)0)
      break;

    VOLT_SET_ERROR_TYPE (errorType, 0)
    VOLT_SET_FNCT_LINE (fnctLine)
    status = mpCtx->MpIntToOctetString (
      primeCandidate, &sign, pBuf, pLen, &pLen);
    if (status != 0)
      break;

    status = VtCreateAlgorithmObject (
      (VtLibCtx)libCtx, VtAlgorithmImplSHA1, (Pointer)0, &digester);
    if (status != 0)
      break;

    /* As long as there are bytes needed, digest.
     */
    bytesNeeded = bufferLen;
    offset = 0;
    do
    {
      copyCount = bytesNeeded;
      if (bytesNeeded >= 20)
        copyCount = 20;
      bytesNeeded -= copyCount;

      status = VtDigestInit (digester);
      if (status != 0)
        break;

      status = VtDigestUpdate (digester, pBuf, pLen);
      if (status != 0)
        break;

      status = VtDigestFinal (
        digester, buffer, bufferLen, digest, sizeof (digest), &digestLen);
      if (status != 0)
        break;

      Z2Memcpy (buffer + offset, digest, copyCount);
      offset += copyCount;

    } while (bytesNeeded != 0);

  } while (0);

  Z2Memset (digest, 0, sizeof (digest));

  if (pBuf != (unsigned char *)0)
    Z2Free (pBuf);

  VtDestroyAlgorithmObject (&digester);

  VOLT_LOG_ERROR_COMPARE (
    status, (VtLibCtx)libCtx, status, errorType, fnctLine,
    "GetRandomValue", (char *)0)

  return (status);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -