Pythonã使ã£ã¦é«éç´ æ°å¤å®ããã¦ã¿ã
ã¿ãªãããç´ æ°ãæ°ãã¦ã¾ããï¼
ãç´ æ°ãã¯ï¼ã¨èªåã®æ°ã§ããå²ããã¨ã®ã§ããªãå¤ç¬ãªæ°åã
æå·åã§ããããä¹±æ°ãä½ããããå¿ãè½ã¡çããããã¦ãç§éã«åæ°ãä¸ãã¦ããã¾ãã
ç´ æ°ã¨ããã°ãã¨ã©ãã¹ããã¹ã®ãµãããã§ãããããã¯å¤§ããæ¡ã®ç´ æ°ãçæãããã¨ããã¨ãã¨ãã§ããªãæéãæãã¾ãã
ä»åã¯ãã©ããªå¤§ããªæ¡ã®ç´ æ°ã§ãé«éã§ç´ æ°å¤å®ããããã°ã©ã ãä½ã£ã¦ã¿ã¾ãã
åºæ¬ã¯ããã§ã«ãã¼ã®å°å®çã
ç´ æ°å¤å®ã®åºæ¬ã¯ããã§ã«ãã¼ã®å°å®çãã§ããæ°å¼ã¯ï¼è¡ã ãã®ããç°¡åãªãã®ã§ãã
a^(p-1) mod p ã®çãã1以å¤ãªãpã¯åææ°ã§ãã
ãã ããaã¨pãç´ ã®é¢ä¿ï¼æå¤§å ¬ç´æ°ã1)ã§ãããã¨
2ã¤ã®æ°ããã¹ãå°ä½ç®ããã¦çãã1以å¤ãªãåææ°(not ç´ æ°)ã¨ããäºã§ãã
aã«2ã代å
¥ãã¦qãç´ æ°ãªãçãã1ã«ãªãããã£ãããã ãã§ãç°¡åã§ããï¼
def is_prime(q): q = abs(q) if q == 2: return True if q < 2 or q&1 == 0: return False return pow(2, q-1, q) == 1
弿°ã«ç´ æ°ã代å
¥ããã¨Trueãè¿ãã¾ãã
Pythonã®ã¹ãä¹é¢æ°pow()ã§ããã第3弿°ã代å
¥ããã¨ã¹ãå°ä½ç®ãã¦ããã¾ãï¼ãªãã¦ããããè¨èªãªã®ãããã
ï¼ãã£ã¨ä¸ã§ã¯é«éãªã¢ã³ã´ã¡ãªä¹ç®ããã¦ããã¦ããã¯ãï¼ï¼
ãã£ãããã ãã§ããã¿ãªããæãã¤ããç´ æ°ãå
¥ãã¦éãã§ã¿ã¦ãã ããã
>>> is_prime(5) True >>> is_prime(9) False >>> is_prime(19) True >>> is_prime(45877878467) True
ãããªçãã³ã¼ããªã®ã«ãã¡ããã¨åºæ¥ã¦ã¾ããï¼ï¼
ã¡ãªã¿ã«ãã§ã«ãã¼ã®å°å®çã使ã£ãç´ æ°å¤å®ãããã§ã«ãã¼ãã¹ããã¨è¨ãã¾ãã
æ¹è¯çãã§ã«ãã¼ãã¹ã
ãæè»½ï¼é«éãªãã§ã«ãã¼ãã¹ãã§ãããéå¤§ãªæ¬ é¥ãããã¾ãã
ãã¤ã¯ããã¾ã«ç´ æ°ãããªãæ°ããã§ã«ãã¼ãã¹ãéã£ã¡ããã¾ããããâ
ãã§ã«ãã¼ãã¹ããéã£ã¡ããåææ°ããçç´ æ°ãã¨ããã¾ãã
a=2ã®ã¨ã2ã10,000ã¾ã§éã§ç´ æ°ãå¤å®ããã¨1,250åã®ç´ æ°åè£ãæ¤åºãã¾ããããã¡22åãçç´ æ°ã§ãã®ã§ç´1.76%ã®ç¢ºçã§èª¤å¤å®ããã¾ãã
以ä¸a=2ã®ã¨ãã®10,000ã®çç´ æ°ã§ãã
341,561,645,1105,1387,1729,1905,2047,2465,2701,2821,3277,
4033,4369,4371,4681,5461,6601,7957,8321,8481,8911
ãã¦ãa=2ã®çç´ æ°ã341ãã§ãããa=3ã®æã¯ã©ãã§ããããï¼
>>> pow(3, 341-1, 341) 56
ã¡ããã¨åææ°ã¨å¤å®ãã¦ãã¾ãããaã®å¤ãå¤ããã¨å¤å®çµæãå¤ãããã§ããã
ãªãã°ãaã®å¤ãå¤ããªãã100åããããã¹ããã¡ããã°ãæ£ç¢ºãªç´ æ°ãåºãããããªãã§ããããã
以ä¸ãæ¹è¯çã®ãã§ã«ãã¼ãã¹ãã§ãã
def is_prime2(q,k=100): q = abs(q) if q == 2: return True if q < 2 or q&1 == 0: return False for i in xrange(3,k): x,y = q,i while y: x, y = y, x % y if x != 1: continue if pow(i, q-1, q) != 1: return False return True
aã®å¤ã第2弿°kã®åã ãåãã¾ãã®ã§ãããaã¨qã¯æå¤§å
¬ç´æ°ã1ã®é¢ä¿ã§ãªããã°ãããªãã®ã§ãã¦ã¼ã¯ãªããã®äºé¤æ³ãã使ã£ã¦ãã§ãã¯ããã¦ãã¾ãã
ãã£ãããååã®ãã§ã«ãã¼ãã¹ãã§æ¼ããçç´ æ°ããã¹ããã¦ã¿ã¾ãããã
pseudoprime = [341,561,645,1105,1387,1729,1905,2047,2465,2701, 2821,3277,4033,4369,4371,4681,5461,6601,7957,8321, 8481,8911] for x in pseudoprime: if is_prime2(x): print(x) #---åºåçµæ 561 1105 1729 2465 2821 6601 8911
ã»ã»ã»ã²ã§ã¼ï¼ï¼ãããããæããçç´ æ°ãããï¼ï¼
ãã©ã¼ã»ã©ãã³(Miller-Rabin)ãã¹ã
ã»ã»ã»ã²ã§ã¼ï¼ï¼ãããããæããçç´ æ°ãããï¼ï¼
(å
é±ããã®ã¤ã¥ãï¼
ãããããå®ã¯ãããªãã®ç¥ã£ã¦ãã
561ã¨ãã®æ°åã¯ãã«ã¼ãã¤ã±ã«æ°ãã£ã¦è¨ã£ã¦ãaã«ã©ããªå¤ãå
¥ã£ã¦ããã§ã«ãã¼ãã¹ããåæ ¼ãã¡ãããã¤ãã§ãã
ã«ã¼ãã¤ã±ã«æ°ã¯ç¡éã«ãããã¨ãç¥ããã¦ãã¦ãç°¡åãªå¤å¥æ¹æ³ã¯åå¨ãã¾ããã
ãã£ããé«éãªãã§ã«ãã¼ãã¹ãã§ãããã«ã¼ãã¤ã±ã«æ°ã®ããã§ä½¿ããªããªãã®ã¯æããã§ãããã
ããã§ç»å ´ããã®ããã§ã«ãã¼ãã¹ãã®æ¹è¯çã§ãããããã©ã¼ã»ã©ãã³ãã¹ããã§ãã
ãã©ã¼ã»ã©ãã³ãã¹ããç°¡åã«èª¬æããã¨ãå¤å®ãããæ£ã®å¥æ°ãqã¨ããå ´åã
q - 1 = 2^s * d
(ä½ãsã¯æ£æ´æ°ãdã¯å¥æ°ã¨ããï¼
ã®å¼ãè§£ããsã¨dãæ±ãã¾ãã
ããã¦ã1ãq-1ã¾ã§ã®éã®æ°ãé©å½ã«é¸ã³aã¨ãããpow(a,d,q) != 1ããTrueã ã£ãå ´åã0ãs-1ã¾ã§ã®ã«ã¦ã³ã¿ãrã¨ãããã¹ã¦ã®ãpow(a, 2**(r*d), d)!=-1ããTrueã«ãªãã¨ãqã¯åææ°ã¨å¤æã§ãã¾ãã
æã
ã誤ã£ã夿ãä¸ãaãç¾ãã¾ãããä½åãaãã©ã³ãã ã§é¸ã¶ãã¨ã«ãã誤ã確çãä¸ãã¾ãã
以ä¸ããã©ã¼ã»ã©ãã³ãã¹ãã®é¢æ°ã§ãã
#coding:utf8 import random def is_prime3(q,k=50): q = abs(q) #è¨ç®ããã¾ã§ããªãå¤å®ã§ãããã®ã¯ã¯ãã if q == 2: return True if q < 2 or q&1 == 0: return False #n-1=2^s*dã¨ãï¼ä½ãaã¯æ´æ°ãdã¯å¥æ°)ãdãæ±ãã d = (q-1)>>1 while d&1 == 0: d >>= 1 #å¤å®ãkåç¹°ãè¿ã for i in xrange(k): a = random.randint(1,q-1) t = d y = pow(a,t,q) #[0,s-1]ã®ç¯å²ãã¹ã¦ããã§ã㯠while t != q-1 and y != 1 and y != q-1: y = pow(y,2,q) t <<= 1 if y != q-1 and t&1 == 0: return False return True
ããã§ã¯è©¦ãã¦ã¿ã¾ãããã
>>> is_prime3(13) True >>> is_prime3(561) False >>> is_prime3(8911) False >>> is_prime3(45877878467) True
ã§ãã¾ããï¼
çç´ æ°ã¨ã«ã¼ãã¤ã±ã«æ°ããã¡ããã¨è¦ç ´ã£ã¦ã¾ããã
ã§ãããã©ã¼ã»ã©ãã³ãã¹ããçµå±ã¯ç¢ºççç´ æ°å¤å®ã§ããã¾ãã®ã§ãéãæªãã¨å¤å®ãééãã¦ãã¾ãã¾ãã
ããããis_prime3()ã®ç¬¬2弿°kã«å¤§ããæ°ãè¨å®ããäºã§ãééã確çãä¸ããäºãã§ãã¾ãã
ã¡ãªã¿ã«ééãã確çã¯ã4^-kãã¨ãªã£ã¦ãã¾ããkã«50ãè¨å®ããã¨ããã¨1/1267650600228229401496703205376ã¨ãªãã¾ãã
éã«ééã£ãå ´é¢ã«ééããæ¹ãã©ããã¼ã ã¨æãã¾ãã
ã¾ã¨ã
確ççç´ æ°å¤å®ã®ãã©ã¼ã»ã©ãã³ãã¹ãã§ããããã®ã¶ãããªãé«éã§ãã
çé¢ç®ã«ç´ æ°å¤å®ãããä¸ççµãããªãæ¡æ°ã¾ã§ãä¸ç¬ã§å¤æãããã¨ãã§ããã®ã§ãã
ä¾ãã°ã以ä¸ã®ããã«300æ¡ã®ç´ æ°ãç°¡åã«å¤å¥å¯è½ã§ãã
1049261498049476504856419608432108674896402341867409604
1684060461674968406126850469654006353403205485749261498
0494765048564196084321086748964023418674096041684060461
6749684061268504696540063534032054857492614980494765048
5641960843210867489640234186740960416840604616749684061
2685046965400635340329729
ããã§ã¯æ¬¡åã¯ç´ æ°ã使ã£ã¦ãããããæ¥½ããäºããã¦ã¿ããã¨ãããã¾ãã
RSA暗号で「ふっかつのじゅもん」を作る(1) - Pashango’s Blogã¸ç¶ãã¾ãã