[OAuth][mobile][socialapp][java] Shift-JISにおける「ミ」問題、%7E問題(signatureの検証に失敗するケース)

某GR社や某De社のモバイルソーシャルアプリ開発で詰まるポイントがあるようなので、まとめ。ただし、遭遇したケースについてのみなので、網羅性はありません。

事象

クライアント端末から送信されてくるformの内容に "%7E"(半角チルダ文字"~") が含まれているとき、oauth signatureの検証に失敗する。
たとえばG社の場合、G社から送られてきているoauth signatureと、自サーバ側で生成したoauth signatureが異なってしまう、ということ。
⇒BaseStringの生成がおかしいのだろう

結論(急いでいる人のための結論)

BaseString生成時に "%7E" は "~" にunescapeしておく。
たとえば カタカナの"ミ" は Shift-JISでは "%83%7E" で送信されてくるが、この部分だけをBaseString向けにエンコードすると "%2583~" となる、ということ。

詳細

今回、これを解決できたのは (TwitterID)chrno001さんのPOSTがあったからこそです。ありがとうございました!

で、調べてみると、RFC5849の3.6. Percent Encodingに、

2. The values are then escaped using the [RFC3986] percent-encoding
(%XX) mechanism as follows:

* Characters in the unreserved character set as defined by
[RFC3986], Section 2.3 (ALPHA, DIGIT, "-", ".", "_", "~") MUST
NOT be encoded.

* All other characters MUST be encoded.

* The two hexadecimal characters used to represent encoded
characters MUST be uppercase.

つまり %7Eの "~" 以外にもエンコードしちゃいけない文字がある、と。注意しましょう。
RFC3986 2.3. Unreserved Charactersにも書いてあります。

RFC3986 compliantなエンコーダがあればいいのですが、今回のプロジェクトはJavaだったので、それについて少し調べてみた。

そもそも、この2つのエンコーダは URL用エンコーダということで RFC3986準拠とは書いてませんね*1

そのほか

Shift-JIS使うなよ、と言われてもG社から指定されているので仕方ありません。。。

*1:これでいくと "*" もヤバそうだが...