プリント基板設計・シミュレーション

TOP > アポロレポート > コラム > 第7回 プログラミングについて 『XORの怪』
コラム
2022/06/16

第7回 プログラミングについて 『XORの怪』

アポロレポート

『XORの怪』


XORの怪。XORについては多分誰でもが分っていることと思います。そう排他的論理和という面倒な日本語に訳されているブール代数の考え方です。実は私は学生のときには確か授業でブール代数というものを勉強したような気がするのですが、実際にXORをプログラムで使うようになったのは、プログラムを書くようになって随分とたった頃のことでした。というのもXORの理屈は知ってはいたのですが、その性質を良く分っていなかったのです。退屈しのぎにFORTRANのマニュアルをめくっていたとき、たまたま目に入った演算子の.XOR.で遊んでいるうちにその性質が分り、それからよく使うようになりました。

 それではそのXORの性質とは一体どういったものでしょうか。

 main()
 {
  int i;

  i=1;

  i^=1;
  printf("%d\n",i);

  i^=1;
  printf("%d\n",i);
}

というプログラムを実行してみると、その結果は

 0
 1

となるのです。別の値で試してみると、

 main()
 {
  int i;

  i=12345;

  i^=54321;
  printf("%d\n",i);

  i^=54321;
  printf("%d\n",i);
  }

その結果は、

 -7160
 12345

となるのです。そうです、同じ値で2度XORを実行すると元の値に戻ってしまうのです。今から思えばXORを考えた人や、コンピュータの命令とかプログラミング言語を作った人は偉いなあと感心させられます。ちょっと考えただけではどうでもいいような機能ですから。

 それではこのXORはプログラムの中でどの様に使うかといえば、最も頻度が高いのは(私のことですが)オン/オフのトグルスイッチです。簡単に言えば変数の値を0と1とで切り替えるときです。最初のプログラムの例がそれです。呼び出される度に変数の値を0と1に交互に切り替える関数を作るときには、

 alternate_status()
 {
  static int sw=0;

  if(sw==0)sw=1;
  else   sw=0;

  return sw;
 }

と書くのもいいのですが、

 alternate_status()
 {
  static int sw=0;

  return sw^=1;
 }

と書いた方がよりスマートな表現になるのです。もっとも0、1、2と3つの値を切り替えるときには、MOD(剰余)を使うかIF文を使いますが、XORの方がIF文より実行スピードが速いのは確かです。

 それ以外のXORの使い方は2番目のプログラムの例がそれです。有名なところではグラフィックスがからんだプログラムのとき、描画モードをXORにして線分を描画し、更に同じ線を描画すると元の絵に戻るので、これを利用してラバーバンドやドラッキングなどを簡単に実現することができる訳です。もっとも、最初にXORモードで白い
線を描画しても白い線分が表現されるのではなく、下絵の各ピクセルの値とXORを行なうので、下絵が不気味な感じで透けて見えるのです。

 余談ですが、XORでの不気味な表示がどうしても嫌いなときには、別の方法でラバーバンドを実現することもできます。現在のワークステーションやパソコンではビットマップのコピー機能がありますのでこの機能を利用します。実際の画面の表示と同じもう1つ別のビットマップを作っておきます。通常の絵はこの両方に描画し、ラバーバンドは画面のビットマップのみに描画し、次の描画の前に裏のビットマップからコピーするのです。そうすれば白は白で描画されます。ただしこの方法は通常の絵は両方のビットマップに描画しなければならないので描画速度は低下します。また裏のビットマップからコピーするとき、範囲が広いとコピーに時間がかかってしまうという欠点もあります。XORかビットマップのコピーのどちらを使うかはコンピュータのパワーを考慮しなければなりません。

 さて、この主体性のない怪しげなXORですが、怪しげな性格の人ならばもっと別の使い方を思い付くことでしょう。1度XORを行なうと怪しげな状態になるということは、図形だけではなく文字とかいろいろなデータまでも怪しげにできるということになるのです。

 5、6年前の頃のことですが、以前私が基板設計のCAD部門を担当していたとき、基板の穴明けデータ(NCドリルのデータと業界では呼んでいる)のフォーマットで苦労したことがあります。CADシステムを使って基板の設計が終了した後、基板のプリントパターンのフィルムを作るためのデータ(ガーバーデータと業界では呼んでいる)と、基板に穴を明けるデータを出力しなければなりません。プリントパターンのフィルム用のデータは、どこの業者に作成を依頼しても作画できるほどフォト作画機の性能が向上していてデータのフォーマットの互換は問題にはならなかったのですが、ドリルのデータとなるとなかなか互換がとれずに、個々に基板メーカーに合わせたフォーマットでデータを出力していたのです。それも紙テープでジコジコと。
 業者に渡すデータができあがると資材部から発注する訳ですが、この資材部が自分の部署の都合や発注先の都合に合わせて基板メーカーを変更するのです。ということはそのしわ寄せがCAD部門にフィードバックされて、発注先に合わせたフォーマットのデータを再びジコジコと紙テープに出力することになるのです。これでは担当者はたまったものではありません。通常この手の出力データは提出した後は消去しますので、計算のやり直しとなるのです。オフセット値の変更、面取りピッチの設定など結構神経を使うのです。

 当時、すでに紙テープというのは過去の遺物になりつつあった頃で、日本国内で紙テープのリーダ/パンチャを作っているメーカーもごくわずかになっていました。そこで当然のなりゆきで紙テープを止めてフロッピーディスクにすることにしました。しかしながら紙テープに出力していたデータをそのままフロッピーディスクに書き込んでもメディアが変わることでジコジコの時間が減るだけがメリットで、メーカー変更時のフォーマット変更の面倒な作業がなくなりません。そこで、そのフロッピーディスクに基本となるドリルのデータとフォーマット変換のプログラムを入れて、基板メーカーが自分の使いたいフォーマットに変換すれば問題はすべて解決できるだろうと思い付いたのです。
 VAX用にFORTRANで書いたフォーマット変換のプログラムを、C言語でDOS用に書き換えてハタと気が付いたことがありました。プログラムはコピーフリーでドリルの基本データは座標と穴径が羅列されたテキストファイルという単純なものですので、フロッピーディスクをもらった方は無料でフォーマット変換プログラムが手に入ることになり徳をすることになります。プログラムにプロテクションをかけれない。これは困ったことになった!
 1週間程考えた末に気が付いたのはデータにプロテクションをかければいいということです。プロテクションと言えば大袈裟で、実際には今回の話題のXORを使ってフロッピーディスクに書き込む基本データを怪しげにすることです。ある規則でXORをかけておきプログラムの実行時に復元すれば、プログラムをいくらコピーされても心配はありません。この機能をプログラムに追加することで、発注先の基板メーカーを気にせずに出力作業ができ、紙テープからフロッピーディスクへのメディアの変更と、メーカー変更に伴う作業がなくなり初期の目的を完璧に実現できたのでした。

 XORで単純に怪しげにするとただ何となく怪しげになるだけで、上記の怪しげにしたデータもその怪しげの仕方が分ってしまえば、簡単に元に戻せてしまうのです。

 16進数で表現するのでちょっと分りずらいかも知れませんが次の例を見て見ましょう。

いまデータファイル test.dat の内容が次のようになっていたとします。

abcdefghijklmnopqrstuvwxyz
aaaaaaaaaaaaabbbbbbbbbbbbb
11111111111111111111111111

このファイルを16進数でダンプすると、

00000000 61 62 63 64 65 66 67 68-69 6A 6B 6C 6D 6E 6F 70  abcdefghijklmnop
00000010 71 72 73 74 75 76 77 78-79 7A 0D 0A 61 61 61 61  qrstuvwxyz..aaaa
00000020 61 61 61 61 61 61 61 61-61 62 62 62 62 62 62 62  aaaaaaaaabbbbbbb
00000030 62 62 62 62 62 62 0D 0A-31 31 31 31 31 31 31 31  bbbbbb..11111111
00000040 31 31 31 31 31 31 31 31-31 31 31 31 31 31 31 31  1111111111111111
00000050 31 31 0D 0A                    11..

このファイルを 'A'(61h)でXORを行なってみると、

00000000 20 23 22 25 24 27 26 29-28 2B 2A 2D 2C 2F 2E 31  #"%$'&)(+*-,/.1
00000010 30 33 32 35 34 37 36 39-38 3B 4C 4B 20 20 20 20  032547698;LK  
00000020 20 20 20 20 20 20 20 20-20 23 23 23 23 23 23 23      #######
00000030 23 23 23 23 23 23 4C 4B-70 70 70 70 70 70 70 70  ######LKpppppppp
00000040 70 70 70 70 70 70 70 70-70 70 70 70 70 70 70 70  pppppppppppppppp
00000050 70 70 4C 4B                    ppLK

となり、なんとなく怪しげになりました。それではもう少し複雑な値で行なってみましょう。次は 'ABC'(616263h)でXORを行なうと、

00000000 20 20 20 25 27 25 26 2A-2A 2B 29 2F 2C 2C 2C 31   %'%&**+)/,,,1
00000010 33 31 32 36 36 37 35 3B-38 38 4E 4B 23 22 20 23  3126675;88NK#" #
00000020 22 20 23 22 20 23 22 20-23 21 23 20 21 23 20 21  " #" #" #!# !# !
00000030 23 20 21 23 20 21 4C 48-72 70 73 72 70 73 72 70  # !# !LHrpsrpsrp
00000040 73 72 70 73 72 70 73 72-70 73 72 70 73 72 70 73  srpsrpsrpsrpsrps
00000050 72 70 4F 49                    rpOI

少しは前の例よりも複雑にはなりました。しかしこれでもまだなんとなく怪しげですね。これ以上やってもきりがありませんので、これくらいにしておきましょう。

 この考えをもとにしたのが、弊社で作成した暗号化/復号化アーカイバのプログラムPFL・WINPFLなのです。試しに同じデータを 'ABC' をパスワードとしてロックすると

00000000 43 59 52 44 79 52 B4 9B-9E E6 25 78 4E 1D D0 75  CYRDyRエ屓.%xN.ミu
00000010 DF 20 AA 04 E2 42 E7 3A-27 B4 FC 3E B1 35 B2 6E  ゚ ェ.磽.:'エ.>ア5イn
00000020 C3 13 41 70 55 49 5C 67-BE 44 B9 5D 50 E8 A3 01  テ.ApUI\gセDケ]P陬.
00000030 45 94 F6 8F 5F B5 EA 06-6D A5 1D 1B 7E 94 0B 81  E尾柔オ..m・..~...
00000040 CA 23 F8 9D 33 BE 4C 79-A6 07 91 70 7C 0F BF 6C  .#..3セLyヲ.叢|.ソl
00000050 46 76 58 E6 AB F6 C5 2D-AF D5 DA CF 31 0F CA E3  FvX讚..-ッユレマ1.ハ綛
00000060 58 09 6E CD 0D 5B 03 9E-69 61 91 4E D2 0A 20 CA  .nヘ.[.枴a鮮メ. ハ
00000070 5D 35 61 82 4E A8 E0 01-FD E1 56 71 56 9A 71 0D  ]5a..ィ...畄qV嘔.
00000080 E7 D7 7B 1A 9B 47 E2 B6-A5 DD 01 AC BD CB C8 11  釋{.姆筝・ン.ャスヒネ.
00000090 8C 46 53 A4 94 37 4E 75-A8 F4 B4 CA BE 63 94 D2  熊S、.7Nuィ..ハセc挽
000000A0 6F 22 64 10 C0 C1 C1 9A-CE 96 99 EC 75 FF 45 BB  o"d.タチチ墅侭...Eサ
000000B0 5B 1C EB 3E 45 68 B2 C4-D8 BC 22 10 D1 2B 74 02  [..>Ehイトリシ".ム+t.
000000C0 E8 EF 15 72 76 EC 02 F5-35 83 53 55 1E ED 33 2E  韵.rv...5ゴU..3.
000000D0 53 FD 4C 83 BA 2C 43 CD-A0 96 65 99 A6 64 8D 16  S.L..,Cヘ.貌勗d..
000000E0 A6 D4 92 10 0A 6E 0F 9B-72 CD F1 09 4A 2B B2 C2  ヲヤ...n.孑ヘ..J+イツ
000000F0 E1 3D 26 FD AF 4A B5 C9-42 93 A2 C1 3B B5 B6 6C  .=&.ッJオノB討チ;オカl
00000100 C5 D6 C4 17 68 10 E1 67-A5 96 76 30 89 BF 0E AA  ナヨト.h.疊・没0価.ェ
00000110 61 9E 66 71 D2 B0 76 83-9E 98 2D A0 B4 E1     a枅qメーv...-.エ.

となります。ダンプの内容を眺めていても何も分りませんが、ファイルの先頭にはパスワード、次にロックされているファイルの情報、最後にファイルの内容が入っています。そこでダンプの最後を見ても、先ほどの例とは違って同じ文字の繰返しは何もありません。またこのプログラムは同じデータを同じパスワードでロックしても必ずしも同じ
アーカイバを作成するとは限りません。

 最後にPFL・WINPFLの内容の概要を説明しましょう。

暗号/復号を行なうプログラムを作って欲しいという要望は、かれこれ1年程前からありました。この要望がでてきたのは弊社がデータやメイルの交換を電子的に行なうようになってからです。しかし実際にプログラムを作り始めたのは半年程後になってからです。処理スピードの考えるとXORを使って怪しげにすることは決めてはいたのですが、どのようなパターンでXORを行なうかの考えがまとまらなかったのです。実はそのパターン(非可逆性の)の生成方法を考えるのに時間を費やしていたのです。

 PFL・WINPFLは、人間が指定する最大80文字の原始パスワード、このパスワードからXORを行なうために生成される20~80バイトの内部パターン、そしてこの内部パターンから生成される最大512バイトのアーカイバファイルに書き込まれる可変長の外部パターンの3つのパターンを持っています。ここでは、可変長パターンの生成方法についての詳細は述べませんが、最大80バイトの内部パターンの隣どうしの文字の値の差に応じて文字と文字の間を埋めていく方法をとっています。
 またパスワードが同じときには同じ外部パターンを生成してしまいますので、パターンを生成したときの時間を外部パターンの最後に追加し、これを使って更にXORを行ないます。このようにして生成された外部パターンは非可逆性で、このパターンから原始パスワードを生成することは不可能になります。
 内部パターンでXORを行なったとき、もしロックするデータが同じ文字の羅列であったとすると、内部パターンの長さに応じて周期的に同じ値のパターンを生成してしまいますので、内部パターンについても1周期ごとに変化するようになっています。

 暗号化/復号化については上記のように非可逆性のアルゴリズムとなっていますが、PFL・WINPFLはアーカイバソフトですので、プログラムの操作性、アーカイバファイルへの入出力、ファイルの時間の管理等が大切なプログラムの機能の要素です。
開発にはこの機能を実現することにほとんどの時間を費やしました。

 だんだん余談になってしまいました。怪しげなXORについて他におもしろい使い方があったら教えて下さい。それではまた次回。



そのお悩み、
アポロ技研に話してみませんか?

アポロ技研でワンランク上の物創りへ!
そのお悩み、アポロ技研に話してみませんか?