<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>taichino.com &#187; programming</title>
	<atom:link href="http://taichino.com/category/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://taichino.com</link>
	<description>永遠のネバーランド</description>
	<lastBuildDate>Sat, 04 Feb 2012 13:33:04 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>[RSAの勉強日記2] Javascriptで暗号化してPythonで復号したい</title>
		<link>http://taichino.com/programming/2667</link>
		<comments>http://taichino.com/programming/2667#comments</comments>
		<pubDate>Sat, 04 Feb 2012 08:21:39 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[pkcs]]></category>
		<category><![CDATA[RSA]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=2667</guid>
		<description><![CDATA[先日、RSAについて解った気になったと書いたんですけど、実際はあんまり解ってなかったので補足等。やりたいのはクライアントで暗号化した情報をサーバで受けて復号したいという事ですね。 鍵の生成をサーバで行って公開鍵をJSのコードに埋める JS側で公開鍵を使って暗号化したデータをサーバに送る サーバで受け取ったデータをPythonで復号 単純な話なはずだったんですけど、上手く行かずにハマりました。 結論から書くと、PyCryptoモジュールがPKCS#1で規定されているのパディング/アンパディングに対応してなかったので自前でアンパディング処理を追加したら上手く行ったという事ですが、学習をかねてもう少し詳しく書いておきます。 本エントリ中の公開鍵・秘密鍵は以下のものを使用しています。他の鍵を使った場合は文中の値は異なります。 PRIVATE KEY: p=312812244098101569570522771086507368199 q=261732496899955705693539027437044751693 n=81873129708674556552097159647951377728324724985548367405770094930146879610907 d=61350191904775909756579327908681267205274632675124298948670533913070326529385 e=65537 PUBLIC KEY: n=81873129708674556552097159647951377728324724985548367405770094930146879610907 e=65537 結局コード見るのがはやいです。まずはPython側ですが、PyCryptoから暗号化処理部分の抜粋したコードを以下に示します。 # pubkey.pyから抜粋 def encrypt(self, plaintext, K): &#34;&#34;&#34;encrypt(plaintext:string&#124;long, K:string&#124;long) : tuple Encrypt the string or integer plaintext. K is a random parameter required by some algorithms. &#34;&#34;&#34; wasString=0 if isinstance(plaintext, types.StringType): plaintext=bytes_to_long(plaintext) ; wasString=1 if isinstance(K, types.StringType): [...]]]></description>
			<content:encoded><![CDATA[<p>先日、<a href="http://taichino.com/engineer-life/2647" title="RSAの勉強日記">RSAについて解った気になったと書いた</a>んですけど、実際はあんまり解ってなかったので補足等。やりたいのはクライアントで暗号化した情報をサーバで受けて復号したいという事ですね。</p>
<ol>
<li>鍵の生成をサーバで行って公開鍵をJSのコードに埋める</li>
<li>JS側で公開鍵を使って暗号化したデータをサーバに送る</li>
<li>サーバで受け取ったデータをPythonで復号</li>
</ol>
<p>単純な話なはずだったんですけど、上手く行かずにハマりました。</p>
<p>結論から書くと、<a href="https://www.dlitz.net/software/pycrypto/" title="pycryptoモジュール" target="_blank">PyCryptoモジュール</a>がPKCS#1で規定されているのパディング/アンパディングに対応してなかったので自前でアンパディング処理を追加したら上手く行ったという事ですが、学習をかねてもう少し詳しく書いておきます。</p>
<p><span id="more-2667"></span></p>
<p>本エントリ中の公開鍵・秘密鍵は以下のものを使用しています。他の鍵を使った場合は文中の値は異なります。</p>
<pre class="brush: text; gutter: true; first-line: 1; highlight: []; html-script: false">
PRIVATE KEY:
  p=312812244098101569570522771086507368199
  q=261732496899955705693539027437044751693
  n=81873129708674556552097159647951377728324724985548367405770094930146879610907
  d=61350191904775909756579327908681267205274632675124298948670533913070326529385
  e=65537
PUBLIC KEY:
  n=81873129708674556552097159647951377728324724985548367405770094930146879610907
  e=65537
</pre>
<p>結局コード見るのがはやいです。まずはPython側ですが、PyCryptoから暗号化処理部分の抜粋したコードを以下に示します。</p>
<pre class="brush: python; gutter: true; first-line: 1; highlight: []; html-script: false">
# pubkey.pyから抜粋
def encrypt(self, plaintext, K):
    &quot;&quot;&quot;encrypt(plaintext:string|long, K:string|long) : tuple
    Encrypt the string or integer plaintext.  K is a random
    parameter required by some algorithms.
    &quot;&quot;&quot;
    wasString=0
    if isinstance(plaintext, types.StringType):
        plaintext=bytes_to_long(plaintext) ; wasString=1
    if isinstance(K, types.StringType):
        K=bytes_to_long(K)
    ciphertext=self._encrypt(plaintext, K)
    if wasString: return tuple(map(long_to_bytes, ciphertext))
    else: return ciphertext

# _slowmath.pyから抜粋
def _encrypt(self, m):
    # compute m**d (mod n)
    return pow(m, self.e, self.n)
</pre>
<p>直線的で解りやすいコードですね。理解の為にencrypt関数に&#8221;a&#8221;を一文字だけ入れた場合の暗号化の流れを観察すると以下のようになります。</p>
<pre class="brush: text; gutter: true; first-line: 1; highlight: []; html-script: false">
a
=&gt; bytes_to_long (バイト列を数値に)
97
=&gt; _encrypt (中でpow。これがいわゆる公開鍵による暗号化)
(52050588761940096487735844075636185108122635599049953266504222754946145963317L,)
=&gt; long_to_bytes (数値を再度バイト列に)
(&#039;s\x13\x96\xd7\xd3\xaf\x92\xf2V\xa3]\x1d:;9O3\xd2\x91\xb7;&quot;\x16\xde\xe7\xf5 \x8a\xdd\x1d\xcd5&#039;,)
</pre>
<p>バイト列を数値に直してから公開鍵による暗号化を行い、再度バイト列に直しています。復号時はこれを逆順で行うわけですね。(もちろん暗号化処理は秘密鍵による復号処理になります。)ここまでは僕の理解通りの処理になっていて何の問題もありませんでした。</p>
<p>一方でJavascriptで行われていた処理を見てみます。ライブラリは<a href="https://ziyan.info/2008/10/javascript-rsa/" title="RSA module with pure Javascript" target="_blank">コチラのrsa.js</a>を使わせて頂いています。色々検索した結果pemをロードできるのはこれしか見つかりませんでした。下記に対応する部分のコードを抜粋します。</p>
<pre class="brush: javascript; gutter: true; first-line: 1; highlight: []; html-script: false">
encrypt: function($data, $pubkey) {
    if (!$pubkey) return false;
    $data = this.pkcs1pad2($data,($pubkey.modulus.bitLength()+7)&gt;&gt;3);
    if(!$data) return false;
    $data = $data.modPowInt($pubkey.encryptionExponent, $pubkey.modulus);
    if(!$data) return false;
    $data = $data.toString(16);
    $data = Hex.decode($data);
    return Base64.encode($data);
},
pkcs1pad2: function($data, $keysize) {
    if($keysize &lt; $data.length + 11)
        return null;
    var $buffer = [];
    var $i = $data.length - 1;
    while($i &gt;= 0 &amp;&amp; $keysize &gt; 0)
        $buffer[--$keysize] = $data.charCodeAt($i--);
    $buffer[--$keysize] = 0;
    while($keysize &gt; 2)
        $buffer[--$keysize] = Math.floor(Math.random()*254) + 1;
    $buffer[--$keysize] = 2;
    $buffer[--$keysize] = 0;
    return new BigInteger($buffer);
}
</pre>
<p>encrypt関数の冒頭で既に様子が違います。暗号化する前の元のデータにpkcs1pad2とかいう謎の処理をかませて、データが変更されています。そしてpkcs1pad2の関数を見ても何をやっているのか全然解りません。関数名からパディングでもやってんのかな位しかわかりません。わずかな希望を胸に、データの暗号化の流れを見てみます。</p>
<pre class="brush: text; gutter: true; first-line: 1; highlight: []; html-script: false">
a
=&gt; pkcs1pad2 (パディング)
3758866564912349439687065567220758327058221768110629839398887525335105633
=&gt; modPowInt (公開鍵暗号化)
14633336708515644111578124792772238970855809995718279846212374275613915803829
=&gt; toString(16)
205a2cd13e395895de49814ec6f9c424f4622f1ffa722f1c88ee23aa521af0b5
=&gt; Hex.decode
バイト列(HTMLで上手く表示できません)
=&gt; Base64.encode
IFos0T45WJXeSYFOxvnEJPRiLx/6ci8ciO4jqlIa8LU=
</pre>
<p>もしかしたらデータは一致するかもという希望は失われました。全然違ったデータになっていますね。困りましたね。要は一口にRSA暗号化といっても、実装によって暗号化・復号処理以外の部分で、データの扱いに違いがあって必ずしも相互にデータを受け渡せるとは限らないという事ですね。</p>
<p>仕方が無いのでpkcs1pad2関数について調べてみると、PKCSというのは<a href="http://ja.wikipedia.org/wiki/PKCS" title="pkcs in wikpedia" target="_blank">Public-Key Cryptography Standards</a>の略で、公開鍵暗号の分野のRFCのようなもののようです。そしてpkcs1というのはPKCS#1のことで、特定の標準仕様を指していて、この中でパディングの方法についても規定されています。</p>
<p>んじゃあ、このPKCSってどの位採用されてんの？と思うわけですが、ざっと調べた感じ事実上デファクトで、perlやrubyのモジュールでは当然のように対応されています。何故かPythonのPyCryptoだけ対応してないという話のようです。</p>
<p>ちょっと調べてみると<a href="http://kfalck.net/2011/03/07/decoding-pkcs1-padding-in-python" title="PyCryptoでPKCS#1を復号" target="_blank">PyCryptoでPKCS#1のデータ復号するときはこうしろという記事</a>が見つかったので、解決しました。まとめがてらPyCryptoでrsa.jsで暗号化したデータを復号する処理を書いておきます。</p>
<pre class="brush: python; gutter: true; first-line: 1; highlight: []; html-script: false">
import Crypto
from Crypto.PublicKey import RSA
import base64

def pkcs1_unpad(text):
    if len(text) &gt; 0 and text[0] == &#039;\x02&#039;:
        # Find end of padding marked by nul
        pos = text.find(&#039;\x00&#039;)
        if pos &gt; 0:
            return text[pos+1:]
    return None

priv = RSA.importKey(open(&#039;priv.pem&#039;, &#039;r&#039;).read())
data = &#039;aoNFe/Y/Nae0wmeY1DUuMTP4bDe4Tib0/fQZynL7UFc=&#039; # encrypted data from js with base 64 encoded
data = base64.b64decode(data)
data = priv.decrypt(data)
data = pkcs1_unpad(data)    # a
</pre>
<p>以上で、Javascriptで暗号化したデータをPythonで復号できました。○○暗号化と一口に言っても実装によって差異があるというのが解って、まぁ良かったと言えば良かったです。PyCryptoでも早く対応して欲しいところです。あと、pkcs1pad2の&#8221;2&#8243;が何を意味しているのか解らないので、誰か知ってたら教えてください。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/2667/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RSAの勉強日記</title>
		<link>http://taichino.com/engineer-life/2647</link>
		<comments>http://taichino.com/engineer-life/2647#comments</comments>
		<pubDate>Wed, 01 Feb 2012 15:50:41 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[技術]]></category>
		<category><![CDATA[RSA]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=2647</guid>
		<description><![CDATA[Javascriptでデータ送る際にデータを暗号化したいなという事で、そうだRSAを使おうと思ったのですが、RSAについて、sshの鍵作る時に出てくる単語で暗号方式？位の理解しかなかったので少し調べてみました。 まず概要の把握ですが、僕は「サルにもわかるRSA暗号」を流してから、「RSA暗号体験入門」を読んだらとりあえず解った気になりました。 次に処理の流れをopensslコマンドで確認してみます。ここでは鍵を生成 => テキストを暗号化 => 復号を確認しました。なお秘密鍵を生成する際のビット数はデフォルトでは512で、普通は1024以上指定するようですが、数が大きくなると確認しづらいので256ビットを指定しています。 $ openssl genrsa -out priv.pem 256 Generating RSA private key, 256 bit long modulus .+++++++++++++++++++++++++++ .................+++++++++++++++++++++++++++ e is 65537 (0x10001) $ openssl rsa -in priv.pem -pubout -out pub.pem writing RSA key $ echo &#34;hello rsa&#34; &#62; hello.txt $ openssl rsautl -encrypt -pubin -inkey pub.pem -in hello.txt -out hello.txt.crypto [...]]]></description>
			<content:encoded><![CDATA[<p>Javascriptでデータ送る際にデータを暗号化したいなという事で、そうだRSAを使おうと思ったのですが、RSAについて、sshの鍵作る時に出てくる単語で暗号方式？位の理解しかなかったので少し調べてみました。</p>
<p><span id="more-2647"></span></p>
<p>まず概要の把握ですが、僕は「<a href="http://www.maitou.gr.jp/rsa/" title="サルにもわかるＲＳＡ暗号" target="_blank">サルにもわかるRSA暗号</a>」を流してから、「<a href="http://www.cybersyndrome.net/rsa/index.html" title="RSA暗号体験入門" target="_blank">RSA暗号体験入門</a>」を読んだらとりあえず解った気になりました。</p>
<p>次に処理の流れをopensslコマンドで確認してみます。ここでは鍵を生成 => テキストを暗号化 => 復号を確認しました。なお秘密鍵を生成する際のビット数はデフォルトでは512で、普通は1024以上指定するようですが、数が大きくなると確認しづらいので256ビットを指定しています。</p>
<pre class="brush: bash; gutter: true; first-line: 1; highlight: []; html-script: false">
$ openssl genrsa -out priv.pem 256
Generating RSA private key, 256 bit long modulus
.+++++++++++++++++++++++++++
.................+++++++++++++++++++++++++++
e is 65537 (0x10001)
$ openssl rsa -in priv.pem -pubout -out pub.pem
writing RSA key
$ echo &quot;hello rsa&quot; &gt; hello.txt
$ openssl rsautl -encrypt -pubin  -inkey pub.pem -in hello.txt -out hello.txt.crypto
$ openssl rsautl -decrypt -inkey priv.pem -in hello.txt.crypto
hello rsa
</pre>
<p>なんとなく流れは掴めた気がしますね。</p>
<p>さて鍵の生成はopensslコマンドでやれば良いとして、それを使って暗号化・復号をプログラムからやりたいですね。そこで次に上で作った秘密鍵・公開鍵をPythonから使ってみます。名前的には<a href="http://pypi.python.org/pypi/rsa" title="rsa module in pypi" target="_blank">rsaモジュール</a>を使いたいのですが、手元では色々と怪しい動きをしていたので、おとなしく<a href="http://pypi.python.org/pypi/pycrypto/2.5" title="PyCrypto in PyPI" target="_blank">PyCrypto</a>を使うのが良さそうです。</p>
<pre class="brush: python; gutter: true; first-line: 1; highlight: []; html-script: false">
import Crypto
from Crypto.PublicKey import RSA

pub = RSA.importKey(open(&#039;pub.pem&#039;, &#039;r&#039;).read())
priv = RSA.importKey(open(&#039;priv.pem&#039;, &#039;r&#039;).read())

text = open(&#039;hello.txt&#039;, &#039;r&#039;).read()
crypto = pub.encrypt(text, &#039;&#039;)
print priv.decrypt(crypto)

print &#039;PRIVATE KEY:\n  p=%s, \n  q=%s, \n  n=%s, \n  d=%s, \n  e=%s&#039; % (priv.p, priv.q, priv.n, priv.d, priv.e)
print &#039;PUBLIC KEY:\n  n=%s, \n  e=%s&#039; % (pub.n, pub.e)
</pre>
<p>これを実行すると以下のようになります。数が大きすぎて良く解らないですが、何となく正常に動いてる気がしますね。</p>
<pre class="brush: text; gutter: true; first-line: 1; highlight: []; html-script: false">
hello rsa world

PRIVATE KEY:
  p=312812244098101569570522771086507368199,
  q=261732496899955705693539027437044751693,
  n=81873129708674556552097159647951377728324724985548367405770094930146879610907,
  d=61350191904775909756579327908681267205274632675124298948670533913070326529385,
  e=65537
PUBLIC KEY:
  n=81873129708674556552097159647951377728324724985548367405770094930146879610907,
  e=65537
</pre>
<p>折角なので学習のため<a href="http://taichino.com/programming/2628" title="合同式の逆元を求める">先ほどのエントリ</a>で書いたmodinvを使って自分でも計算してみます。</p>
<pre class="brush: python; gutter: true; first-line: 1; highlight: []; html-script: false">
&gt;&gt; def calc(base, exp, modulus):
&gt;&gt;     ans = 1
&gt;&gt;     while exp &lt; 0:
&gt;&gt;         if exp &amp; 1:
&gt;&gt;             ans = (ans * base) % modulus
&gt;&gt;         exp &gt;&gt;= 1
&gt;&gt;         exp = int(exp)
&gt;&gt;         base = (base * base) % modulus
&gt;&gt;     return ans
&gt;&gt;
&gt;&gt; (p, q) = (65537, 55079)
&gt;&gt; m = p * q
&gt;&gt; phi = (p - 1) * (q - 1)
&gt;&gt; e = 65537
&gt;&gt; d = modinv(e, phi)
&gt;&gt; orig = 2900
&gt;&gt; encoded = calc(orig, e, m)
&gt;&gt; print encoded
60945415393350116455581236569596858319975698828166554225855598846369380497015
&gt;&gt; decoded = calc(encoded, d, m)
&gt;&gt; print decoded
2900
</pre>
<p>値が大きくなるのでベキ乗計算が少し面倒ですが、暗号化と復号ができました。まだ文字列をどうやって暗号化可能な数値に変換してるのかとか細かくは理解してないですけど何となくつかめた気がしてます。</p>
<p>さて最後にフォーマットについて確認します。opensslで生成した鍵(priv.pem, pub.pem)はPEM形式というやつで、中身はDER形式のデータをbase64でエンコードしたもののようです。例えば上で生成したファイルは下記のような姿をしています。</p>
<pre class="brush: text; gutter: true; first-line: 1; highlight: []; html-script: false">
-----BEGIN RSA PRIVATE KEY-----
MIGqAgEAAiEAtQKMmuoZNSc0jZe/TDf1p3bQraYwXvBkOdFSwJAkIBsCAwEAAQIh
AIei+mOXKf53e1ziqhleEXgAni7HKueUV/bWLRzb+D1pAhEA61VyYLHy31RSLJ3l
aWXfBwIRAMTn2GbiUscRRmBm9aiR3U0CEDnyEzS9/EiDUayMwHVAUTcCEBgXDWC4
+8ujD2sn7ZIsFlkCECAVBGiJ4VrYG6HTGgTflU4=
-----END RSA PRIVATE KEY-----
</pre>
<p>このファイルをDER形式に変換してみます。やはりopensslコマンドを使用します。</p>
<pre class="brush: bash; gutter: true; first-line: 1; highlight: []; html-script: false">
$ openssl rsa -inform PEM -outform DER -in priv.pem -out priv.der
</pre>
<p>変換後のDERファイルの内容をやはりopensslコマンドで読みます。この数値が大きい時に使われる表現をもとの数字に戻す方法が解らないのでどなたかご存知であれば教えてください。</p>
<pre class="brush: bash; gutter: true; first-line: 1; highlight: []; html-script: false">
$ openssl rsa -inform DER -in priv.der -text -noout
Private-Key: (256 bit)
modulus:
    00:b5:02:8c:9a:ea:19:35:27:34:8d:97:bf:4c:37:
    f5:a7:76:d0:ad:a6:30:5e:f0:64:39:d1:52:c0:90:
    24:20:1b
publicExponent: 65537 (0x10001)
privateExponent:
    00:87:a2:fa:63:97:29:fe:77:7b:5c:e2:aa:19:5e:
    11:78:00:9e:2e:c7:2a:e7:94:57:f6:d6:2d:1c:db:
    f8:3d:69
prime1:
    00:eb:55:72:60:b1:f2:df:54:52:2c:9d:e5:69:65:
    df:07
prime2:
    00:c4:e7:d8:66:e2:52:c7:11:46:60:66:f5:a8:91:
    dd:4d
exponent1:
    39:f2:13:34:bd:fc:48:83:51:ac:8c:c0:75:40:51:
    37
exponent2:
    18:17:0d:60:b8:fb:cb:a3:0f:6b:27:ed:92:2c:16:
    59
coefficient:
    20:15:04:68:89:e1:5a:d8:1b:a1:d3:1a:04:df:95:
    4e
</pre>
<p>全然細かい事は調べれてないのですが、何となくRSAの概要が把握できた気になっていて、コード追うくらいはできそうなのでこの辺にしておきます。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/engineer-life/2647/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pythonで合同式の逆元を求める</title>
		<link>http://taichino.com/programming/2628</link>
		<comments>http://taichino.com/programming/2628#comments</comments>
		<pubDate>Wed, 01 Feb 2012 03:41:17 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[アルゴリズム]]></category>
		<category><![CDATA[拡張ユークリッドの互除法]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=2628</guid>
		<description><![CDATA[RSAをおさらいしていたら、合同式の逆元を求める必要がありました。合同式の逆元は拡張ユークリッドの互除法を使うと求められるのですが、逆元を求める際にどう拡張ユークリッドの互除法を使えば良いのか解らなくて、手間取ったのでメモしておきます。コードはPythonです。 一応解きたい式を書いておくと以下になります。 まず拡張ユークリッドの互除法をWikipedia通りに書きます。Wikipediaの擬似コードは何故かgcdの値を返してなかったのでgcdも返すように変更しました。 def egcd&#40;a, b&#41;: &#40;x, lastx&#41; = &#40;0, 1&#41; &#40;y, lasty&#41; = &#40;1, 0&#41; while b != 0: q = a // b &#40;a, b&#41; = &#40;b, a % b&#41; &#40;x, lastx&#41; = &#40;lastx - q * x, x&#41; &#40;y, lasty&#41; = &#40;lasty - q * y, y&#41; return &#40;lastx, lasty, a&#41; 次にこのegcdを使って合同式の逆元を求める訳ですが、どうにも解りやすい説明が見つからなくて困りました。色々見て回った結果、ここでもWikipediaの「Modular [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://ja.wikipedia.org/wiki/RSA%E6%9A%97%E5%8F%B7" title="RSA暗号" target="_blank">RSA</a>をおさらいしていたら、合同式の逆元を求める必要がありました。合同式の逆元は拡張ユークリッドの互除法を使うと求められるのですが、逆元を求める際にどう拡張ユークリッドの互除法を使えば良いのか解らなくて、手間取ったのでメモしておきます。コードはPythonです。</p>
<p>一応解きたい式を書いておくと以下になります。<br />
<img src='http://taichino.com/wp-content/plugins/wp-latexrender/pictures/8677d4cbaa413dabf10a16213a62cab6.gif' title='\mathfrak{a}x \equiv 1\ \pmod{\mathfrak{m}}' alt='\mathfrak{a}x \equiv 1\ \pmod{\mathfrak{m}}' align=absmiddle> </p>
<p><span id="more-2628"></span></p>
<p>まず拡張ユークリッドの互除法を<a href="http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm" title="拡張ユークリッドの互除法" target="_blank">Wikipedia通り</a>に書きます。Wikipediaの擬似コードは何故かgcdの値を返してなかったのでgcdも返すように変更しました。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> egcd<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: black;">&#40;</span>x, lastx<span style="color: black;">&#41;</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#40;</span>y, lasty<span style="color: black;">&#41;</span> = <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> b <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
        q = a // b
        <span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span> = <span style="color: black;">&#40;</span>b, a <span style="color: #66cc66;">%</span> b<span style="color: black;">&#41;</span>
        <span style="color: black;">&#40;</span>x, lastx<span style="color: black;">&#41;</span> = <span style="color: black;">&#40;</span>lastx - q <span style="color: #66cc66;">*</span> x, x<span style="color: black;">&#41;</span>
        <span style="color: black;">&#40;</span>y, lasty<span style="color: black;">&#41;</span> = <span style="color: black;">&#40;</span>lasty - q <span style="color: #66cc66;">*</span> y, y<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>lastx, lasty, a<span style="color: black;">&#41;</span></pre></div></div>

<p>次にこのegcdを使って合同式の逆元を求める訳ですが、どうにも解りやすい説明が見つからなくて困りました。色々見て回った結果、ここでもWikipediaの「<a href="http://en.wikipedia.org/wiki/Modular_multiplicative_inverse" title="合同式の逆元" target="_blank">Modular multiplicative inverse</a>」が一番解りやすかったです。ページに書かれている通りegcdを使って逆元を求めます。</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># ax ≡ 1 (mod m)</span>
<span style="color: #ff7700;font-weight:bold;">def</span> modinv<span style="color: black;">&#40;</span>a, m<span style="color: black;">&#41;</span>:
    <span style="color: black;">&#40;</span>inv, q, gcd_val<span style="color: black;">&#41;</span> = egcd<span style="color: black;">&#40;</span>a, m<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> inv <span style="color: #66cc66;">%</span> m</pre></div></div>

<p>上記のmodinvで冒頭の式中のxを求められました。結果だけ見るとなんでもないですね。アルゴリズムが苦手なのでもっと精進します。</p>
<p>アルゴリズム系はWikipediaが便利すぎますね。そしてPythonはWikipediaに張られている擬似コードがほぼ機械的な修正のみで動くので素晴らしいです。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/2628/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SWI-PrologをC言語から叩く</title>
		<link>http://taichino.com/engineer-life/2558</link>
		<comments>http://taichino.com/engineer-life/2558#comments</comments>
		<pubDate>Sat, 07 Jan 2012 20:08:50 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[技術]]></category>
		<category><![CDATA[liswipl]]></category>
		<category><![CDATA[prolog]]></category>
		<category><![CDATA[swi-prolog]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=2558</guid>
		<description><![CDATA[「７つの言語 ７つの世界」の3つ目の言語がPrologなんですけど、触ってみると結構面白くて、とりあえずの感想としてはルールの表現力がハンパ無く高いなという事です。良く例で挙げられていますが、数独を解いたり、麻雀の手役を確認したりといった、一定のルールに基づいた処理を他の言語と比べてかなり楽に書けそうです。 これはちょっと習得しておきたいなと思うものの、上述のような特定の処理以外は他の言語と比べてあまりに貧弱です。今回使用した処理系の標準ライブラリはこれだけしかありません。 なので必要に応じてPrologを別の言語から使うという方が現実的なのかなということで、とりあえずPythonインターフェースを試したのですが、動かなかったので仕方なしにC言語から使ってみる事にしました。なお処理系はSWI-Prologというのを使う事にしました。(手元だとGNU Prologが日本語で文字化けを起こしました。) まず以下のPrologのコードを見てください。ドラクエの道具屋(アリアハン)です。 % shop.pl item&#40;やくそう, 8&#41;. item&#40;どくけしそう, 10&#41;. item&#40;キメラのつばさ, 25&#41;. item&#40;おなべのフタ, 50&#41;. &#160; available&#40;G, X&#41; :- item&#40;X, G0&#41;, G0 =＜ G. availableという述語を定義していて、持ち金(G)を指定してクエリを投げると、購入可能なアイテムが得られます。Prologからの実行は以下のようになります。 ?- [&#039;shop.pl&#039;]. % shop.pl compiled 0.00 sec, 2,216 bytes true. ?- available(10, X). X = やくそう; X = どくけしそう; false. ?- available(100, X). X = やくそう; X = どくけしそう; [...]]]></description>
			<content:encoded><![CDATA[<p>「<a href="http://www.amazon.co.jp/gp/product/4274068579/ref=as_li_ss_tl?ie=UTF8&#038;tag=creatorsland-22&#038;linkCode=as2&#038;camp=247&#038;creative=7399&#038;creativeASIN=4274068579">７つの言語 ７つの世界</a><img src="http://www.assoc-amazon.jp/e/ir?t=creatorsland-22&#038;l=as2&#038;o=9&#038;a=4274068579" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />」の3つ目の言語がPrologなんですけど、触ってみると結構面白くて、とりあえずの感想としてはルールの表現力がハンパ無く高いなという事です。良く例で挙げられていますが、数独を解いたり、麻雀の手役を確認したりといった、一定のルールに基づいた処理を他の言語と比べてかなり楽に書けそうです。</p>
<p>これはちょっと習得しておきたいなと思うものの、上述のような特定の処理以外は他の言語と比べてあまりに貧弱です。今回使用した処理系の標準ライブラリは<a href="http://www.swi-prolog.org/pldoc/index.html" title="SWI-Prologのライブラリ" target="_blank">これ</a>だけしかありません。</p>
<p>なので必要に応じてPrologを別の言語から使うという方が現実的なのかなということで、とりあえず<a href="http://code.google.com/p/pyswip/" title="pyswip" target="_blank">Pythonインターフェース</a>を試したのですが、動かなかったので仕方なしにC言語から使ってみる事にしました。なお処理系は<a href="http://www.swi-prolog.org/" title="swi-prolog" target="_blank">SWI-Prolog</a>というのを使う事にしました。(手元だとGNU Prologが日本語で文字化けを起こしました。)</p>
<p><span id="more-2558"></span></p>
<p>まず以下のPrologのコードを見てください。ドラクエの道具屋(アリアハン)です。</p>

<div class="wp_syntax"><div class="code"><pre class="prolog" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">% shop.pl</span>
item<span style="color: #009900;">&#40;</span>やくそう<span style="color: #339933;">,</span> <span style="color: #800080;">8</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
item<span style="color: #009900;">&#40;</span>どくけしそう<span style="color: #339933;">,</span> <span style="color: #800080;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
item<span style="color: #009900;">&#40;</span>キメラのつばさ<span style="color: #339933;">,</span> <span style="color: #800080;">25</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
item<span style="color: #009900;">&#40;</span>おなべのフタ<span style="color: #339933;">,</span> <span style="color: #800080;">50</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span>
&nbsp;
available<span style="color: #009900;">&#40;</span>G<span style="color: #339933;">,</span> X<span style="color: #009900;">&#41;</span> <span style="color: #339933;">:-</span>
	item<span style="color: #009900;">&#40;</span>X<span style="color: #339933;">,</span> G0<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
	G0 <span style="color: #339933;">=</span>＜ G<span style="color: #339933;">.</span></pre></div></div>

<p>availableという述語を定義していて、持ち金(G)を指定してクエリを投げると、購入可能なアイテムが得られます。Prologからの実行は以下のようになります。</p>
<pre class="brush: text; gutter: true; first-line: 1; highlight: []; html-script: false">
?- [&#039;shop.pl&#039;].
% shop.pl compiled 0.00 sec, 2,216 bytes
true.

?- available(10, X).
X = やくそう;
X = どくけしそう;
false.

?- available(100, X).
X = やくそう;
X = どくけしそう;
X = キメラのつばさ;
X = おなべのフタ.
</pre>
<p>これをC言語から使う訳ですが、<a href="http://www.swi-prolog.org/pldoc/refman/" title="SWI-Prolog公式ドキュメント" target="_blank">公式ドキュメント</a>によると以下のような手順になります。</p>
<ol>
<li><strong>C言語から使用したいPrologの述語が記述されたplファイルを準備する</strong>(今回はshop.pl)</li>
<li><strong>Prologを叩くC言語のファイルを準備する</strong>(今回はmain.cpp)</li>
<li><strong>SWI-Prologにバンドルされているswipl-ldというツールでビルドして実行ファイルを作成</strong></li>
</ol>
<p>本来はPrologで使用する述語もC言語側から追加したいのですが、今回はまぁ良しとします。さて手順1のshop.plはもう準備できているので手順2から進める事にします。</p>
<p><strong>手順2</strong><br />
C言語のコードを書きます。大した処理でもないのですが、まぁ情報が無いので苦労しました。処理の流れは、PL_initializeで初期化して、PL_Predicateでクエリに必要なpredicate_tオブジェクト(SQLみたいなイメージ)を構築します。作成したpredicateをPL_open_queryでPrologにクエリを投げて、PL_get_charsなんかで結果を取得するというものです。</p>
<pre class="brush: cpp; gutter: true; first-line: 1; highlight: []; html-script: false">
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;SWI-Prolog.h&gt;

int main(int argc, char **argv) {
    if (argc == 1) {
        printf(&quot;Usage: shop [持ち金]\n&quot;);
        exit(0);
    }

    // initialize
    char* program = argv[0];
    char* plav[2] = { program, NULL };
    if (!PL_initialise(1, plav)) {
        PL_halt(1);
    }

    // build query
    int money = atoi(argv[1]);
    predicate_t pred = PL_predicate(&quot;available&quot;, 2, NULL);
    term_t h0 = PL_new_term_refs(2);
    term_t h1 = h0 + 1;
    PL_put_integer(h0, money);

    // exec query
    qid_t qid = PL_open_query(NULL, PL_Q_NORMAL, pred, h0);
    while (PL_next_solution((qid))) {
        char *s = NULL;
        PL_get_chars(h1, &amp;s, CVT_ALL|REP_UTF8);
        printf(&quot;%s\n&quot;, s);
    }
    PL_close_query(qid);

    // cleanup
    PL_cleanup(1);

    return 0;
}
</pre>
<p>とにかく情報が無いのが一番困りました。唯一サンプルコードが見つかったのが<a href="http://www.montefiore.ulg.ac.be/~lens/prolog/prolog.html" title="libswiplのサンプル" target="_blank">コチラのページ</a>です。フランス語ですけど。少しハマったのがPL_get_charsで文字列を取得する際には上記のフラグを指定しないと文字列として取得できないという事です。あとPL_open_queryからPL_close_queryまでを一纏めにしたPL_call_predicateを使うと、何故か想定通りの挙動をしませんでした。</p>
<p><strong>手順3</strong><br />
次にビルドします。これは簡単ですね。</p>
<pre class="brush: bash; gutter: true; first-line: 1; highlight: []; html-script: false">
$ swipl-ld -o shop main.cpp shop.pl
$ ls
main.cpp        shop            shop.pl
</pre>
<p>ところでswipl-ldは幾つかのビルド処理を一纏めにしているユーティリティです。内部で何が起こっているかは-vオプションを追加すると見れます。詳細は調べてませんがswiplに何やら怪しい処理をさせていますね。気が向いたらもう少し突っ込みたいところです。</p>
<pre class="brush: bash; gutter: true; first-line: 1; highlight: []; html-script: false">
$ swipl-ld -v -o shop main.cpp shop.pl
        eval `swipl --dump-runtime-variables`
                CC=&quot;gcc&quot;
                PLBASE=&quot;/usr/lib/swipl-5.6.63&quot;
                PLARCH=&quot;i386-darwin10.8.0&quot;
                PLLIBS=&quot;-lpl&quot;
                PLLIB=&quot;-lpl&quot;
                PLCFLAGS=&quot;-no-cpp-precomp -pthread -fno-common&quot;
                PLLDFLAGS=&quot;-O3 -pthread&quot;
                PLSOEXT=&quot;dylib&quot;
                PLTHREADS=&quot;yes&quot;
        g++ -c -no-cpp-precomp -pthread -fno-common -D_REENTRANT -D__SWI_PROLOG__ -D__SWI_EMBEDDED__ -I/usr/lib/swipl-5.6.63/include -o main.o main.cpp
        g++ -o shop -O3 -pthread main.o -L/usr/lib/swipl-5.6.63/lib/i386-darwin10.8.0 -lpl -lpl
        swipl -f none -F none -g true -t &quot;consult([&#039;shop.pl&#039;]),qsave_program(&#039;pltmp-98271&#039;,[goal=&#039;\$welcome&#039;,toplevel=prolog,init_file=none])&quot;
% shop.pl compiled 0.00 sec, 5,272 bytes
% halt
        cat pltmp-98271 &gt;&gt; shop
        chmod 755 shop
        rm main.o
        rm pltmp-98271
</pre>
<p>以上で実行ファイルshopが生成されました。早速実行してみます。ライセンスとかが出力されて不満ですが、まぁ最低限の挙動は示していますね。</p>
<pre class="brush: bash; gutter: true; first-line: 1; highlight: []; html-script: false">
$ ./shop 10
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 5.6.63)
Copyright (c) 1990-2008 University of Amsterdam.
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).

やくそう
どくけしそう
</pre>
<p>以上、SWI-PrologをC言語から触ってみました。GNU Prologの場合は少しインターフェースが異なるようなので注意してください。まぁ正直Cから使えても仕方が無いのでPythonから使えない理由を少し探ってみたいと思います。Pythonの他に、<a href="http://search.cpan.org/~salva/Language-Prolog-Yaswi-0.19/Yaswi.pm" title="PerlのSWI-Prologのインターフェース" target="_blank">Perlにもインターフェース</a>が用意されているようですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/engineer-life/2558/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OSXのdylibを作ってみる</title>
		<link>http://taichino.com/programming/2533</link>
		<comments>http://taichino.com/programming/2533#comments</comments>
		<pubDate>Sat, 07 Jan 2012 05:14:04 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[dylib]]></category>
		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=2533</guid>
		<description><![CDATA[OSXで共有ライブラリを触ったことがなかったので、試しにdylibを作ってみました。Linuxだと.soですがOSXだと.dylibのようですね。フォーマットの差異については調べていません。Appleの「Dynamic Library Programming」というドキュメントのさわりだけ参考にしました。 まずdylib側のコードです。ただのHelloWorldですね。 /** * hello.c */ #include &#60;stdio.h&#62; void hello_dylib() { printf(&#34;hello dylib world!\n&#34;); } これをdylibにコンパイルします。-dynamiclibオプションを指定すると直接dylibを生成できます。簡単ですね。一応otoolでできたdylibを確認するとfiletypeがDYLIBになっています。 $ gcc -dynamiclib hello.c -o libhello.dylib $ ls hello.c libhello.dylib $ otool -vh libhello.dylib libhello.dylib: Mach header magic cputype cpusubtype caps filetype ncmds sizeofcmds flags MH_MAGIC_64 X86_64 ALL 0x00 DYLIB 9 1128 NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS できたdylibを実際に使ってみます。dlopen, [...]]]></description>
			<content:encoded><![CDATA[<p>OSXで共有ライブラリを触ったことがなかったので、試しにdylibを作ってみました。Linuxだと.soですがOSXだと.dylibのようですね。フォーマットの差異については調べていません。Appleの「<a href="http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/DynamicLibraries/000-Introduction/Introduction.html" title="Dynamic Library Programming" target="_blank">Dynamic Library Programming</a>」というドキュメントのさわりだけ参考にしました。</p>
<p><span id="more-2533"></span></p>
<p>まずdylib側のコードです。ただのHelloWorldですね。</p>
<pre class="brush: cpp; gutter: false; first-line: 1; highlight: []; html-script: false">
/**
 * hello.c
 */
#include &lt;stdio.h&gt;

void hello_dylib() {
    printf(&quot;hello dylib world!\n&quot;);
}
</pre>
<p>これをdylibにコンパイルします。-dynamiclibオプションを指定すると直接dylibを生成できます。簡単ですね。一応otoolでできたdylibを確認するとfiletypeがDYLIBになっています。</p>
<pre class="brush: bash; gutter: false; first-line: 1; highlight: []; html-script: false">
$ gcc -dynamiclib hello.c -o libhello.dylib
$ ls
hello.c libhello.dylib
$ otool -vh libhello.dylib
libhello.dylib:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00       DYLIB     9       1128   NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS
</pre>
<p>できたdylibを実際に使ってみます。dlopen, dlsymでdylibをロード、関数ポインタを取得して実行しているだけです。</p>
<pre class="brush: cpp; gutter: false; first-line: 1; highlight: []; html-script: false">
/**
 * main.c
 */
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;dlfcn.h&gt;

typedef void (*func)();

int main() {
    void* module = dlopen(&quot;libhello.dylib&quot;, RTLD_LAZY);
    if (!module) {
	exit(EXIT_FAILURE);
    }

    func f = dlsym(module, &quot;hello_dylib&quot;);
    if (dlerror()) {
	goto ERR;
    }

    printf(&quot;hello_dylib loaded \n&quot;);
    f();    // 実行

    dlclose(module);
    return 0;

  ERR:
    dlclose(module);
    exit(EXIT_FAILURE);
}
</pre>
<p>ビルドして実行します。</p>
<pre class="brush: bash; gutter: false; first-line: 1; highlight: []; html-script: false">
$ gcc main.c
$ ./a.out
hello_dylib loaded
hello dylib world!
</pre>
<p>上記ドキュメントを眺めると、きちんと使うには色々課題があるようですが、とりあえず雰囲気だけはつかめたので良しとします。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/2533/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

