您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

kronecker.c 5.0 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /* ====================================================================
  2. * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in
  13. * the documentation and/or other materials provided with the
  14. * distribution.
  15. *
  16. * 3. All advertising materials mentioning features or use of this
  17. * software must display the following acknowledgment:
  18. * "This product includes software developed by the OpenSSL Project
  19. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  20. *
  21. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  22. * endorse or promote products derived from this software without
  23. * prior written permission. For written permission, please contact
  24. * openssl-core@openssl.org.
  25. *
  26. * 5. Products derived from this software may not be called "OpenSSL"
  27. * nor may "OpenSSL" appear in their names without prior written
  28. * permission of the OpenSSL Project.
  29. *
  30. * 6. Redistributions of any form whatsoever must retain the following
  31. * acknowledgment:
  32. * "This product includes software developed by the OpenSSL Project
  33. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  34. *
  35. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  36. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  38. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  39. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  41. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  42. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  43. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  44. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  45. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  46. * OF THE POSSIBILITY OF SUCH DAMAGE.
  47. * ====================================================================
  48. *
  49. * This product includes cryptographic software written by Eric Young
  50. * (eay@cryptsoft.com). This product includes software written by Tim
  51. * Hudson (tjh@cryptsoft.com). */
  52. #include <openssl/bn.h>
  53. #include "internal.h"
  54. /* least significant word */
  55. #define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
  56. /* Returns -2 for errors because both -1 and 0 are valid results. */
  57. int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
  58. int i;
  59. int ret = -2;
  60. BIGNUM *A, *B, *tmp;
  61. /* In 'tab', only odd-indexed entries are relevant:
  62. * For any odd BIGNUM n,
  63. * tab[BN_lsw(n) & 7]
  64. * is $(-1)^{(n^2-1)/8}$ (using TeX notation).
  65. * Note that the sign of n does not matter. */
  66. static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
  67. BN_CTX_start(ctx);
  68. A = BN_CTX_get(ctx);
  69. B = BN_CTX_get(ctx);
  70. if (B == NULL) {
  71. goto end;
  72. }
  73. if (!BN_copy(A, a) ||
  74. !BN_copy(B, b)) {
  75. goto end;
  76. }
  77. /* Kronecker symbol, imlemented according to Henri Cohen,
  78. * "A Course in Computational Algebraic Number Theory"
  79. * (algorithm 1.4.10). */
  80. /* Cohen's step 1: */
  81. if (BN_is_zero(B)) {
  82. ret = BN_abs_is_word(A, 1);
  83. goto end;
  84. }
  85. /* Cohen's step 2: */
  86. if (!BN_is_odd(A) && !BN_is_odd(B)) {
  87. ret = 0;
  88. goto end;
  89. }
  90. /* now B is non-zero */
  91. i = 0;
  92. while (!BN_is_bit_set(B, i)) {
  93. i++;
  94. }
  95. if (!BN_rshift(B, B, i)) {
  96. goto end;
  97. }
  98. if (i & 1) {
  99. /* i is odd */
  100. /* (thus B was even, thus A must be odd!) */
  101. /* set 'ret' to $(-1)^{(A^2-1)/8}$ */
  102. ret = tab[BN_lsw(A) & 7];
  103. } else {
  104. /* i is even */
  105. ret = 1;
  106. }
  107. if (B->neg) {
  108. B->neg = 0;
  109. if (A->neg) {
  110. ret = -ret;
  111. }
  112. }
  113. /* now B is positive and odd, so what remains to be done is to compute the
  114. * Jacobi symbol (A/B) and multiply it by 'ret' */
  115. while (1) {
  116. /* Cohen's step 3: */
  117. /* B is positive and odd */
  118. if (BN_is_zero(A)) {
  119. ret = BN_is_one(B) ? ret : 0;
  120. goto end;
  121. }
  122. /* now A is non-zero */
  123. i = 0;
  124. while (!BN_is_bit_set(A, i)) {
  125. i++;
  126. }
  127. if (!BN_rshift(A, A, i)) {
  128. goto end;
  129. }
  130. if (i & 1) {
  131. /* i is odd */
  132. /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */
  133. ret = ret * tab[BN_lsw(B) & 7];
  134. }
  135. /* Cohen's step 4: */
  136. /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */
  137. if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) {
  138. ret = -ret;
  139. }
  140. /* (A, B) := (B mod |A|, |A|) */
  141. if (!BN_nnmod(B, B, A, ctx)) {
  142. ret = -2;
  143. goto end;
  144. }
  145. tmp = A;
  146. A = B;
  147. B = tmp;
  148. tmp->neg = 0;
  149. }
  150. end:
  151. BN_CTX_end(ctx);
  152. return ret;
  153. }