Skip to content

Instantly share code, notes, and snippets.

@teaplanet
Created July 29, 2010 10:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save teaplanet/497821 to your computer and use it in GitHub Desktop.
Save teaplanet/497821 to your computer and use it in GitHub Desktop.
package oauth
import java.net.URLEncoder
import java.util.Random
import java.security.Key
import javax.crypto.spec.SecretKeySpec
import javax.crypto.Mac
import sun.misc.BASE64Encoder
object OAuthEcho {
private val TwitterTokenURL = "http://twitter.com/oauth/request_token"
def mkTwitterRequestTokenURL(consumerKey:String, consumerSecret:String, oAuthToken:String=""):String = {
val params = Map("oauth_consumer_key" -> consumerKey,
"oauth_signature_method" -> "HMAC-SHA1",
"oauth_nonce" -> nonce,
"oauth_timestamp" -> timestamp,
"oauth_version" -> "1.0")
val signature = sign(params, consumerSecret, oAuthToken)
val oAuthParams = params.map { case(k, v) => "%s=%s".format(k, v) }.mkString("&")
"%s?%s&oauth_signature=%s".format(TwitterTokenURL, oAuthParams, signature)
}
/** 署名を作成する。
* キーを生成するための値は "consumerSecret&oAuthToken" であるが、oAuthTokenが存在しない場合もある。
* oAuthTokenが存在しない場合は "consumerSecret&" となり "&" は必須。
* 署名した値はBase64エンコード後、URLエンコードする。
* @params パラメータ
* @consumerSecret ConsumerSecret
* @oAuthToken OAuthToken
*/
private def sign(params:Map[String, String], consumerSecret:String, oAuthToken:String):String = {
// 認証コード準備
val secrets = "%s&%s".format(consumerSecret, oAuthToken)
val key = new SecretKeySpec(secrets.getBytes("UTF-8"), "HmacSHA1")
val mac = Mac.getInstance(key.getAlgorithm)
mac.init(key)
// 署名
val unsigned = mkUnsignedURL(params)
val digest = mac.doFinal(unsigned.getBytes)
encode(new BASE64Encoder().encode(digest))
}
/** 署名を行うための文字列を作成する。
* この文字列は "GET" と "エンコードしたURL" と "エンコードしたパラメータ" を "&" で接続した値。
* エンコードしたパラメータは、パラメータ名でソートする必要がある。
* @params パラメータ
*/
private def mkUnsignedURL(params:Map[String, String]):String = {
val oAuthParams = params.toList.sort { (a, b) => a._1 < b._1 }.map { case(k, v) => "%s=%s".format(k, v) }.mkString("&")
"GET&%s&%s".format(encode(TwitterTokenURL), encode(oAuthParams))
}
private def encode(value:String):String = URLEncoder.encode(value, "UTF-8")
private def timestamp:String = (new java.util.Date().getTime / 1000).toString
private def nonce:String = Math.abs(new Random().nextLong).toString
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment