teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

7

質問を減らした

2018/02/08 12:06

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -4,7 +4,7 @@
4
4
  Secure ASP.NET Web API using API Key Authentication – HMAC Authentication](http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/)
5
5
 
6
6
  上記の記事を見てHMACを使用したAPI認証というものを知りました。
7
- これに関して3つの質問があります。
7
+ これに関して2つの質問があります。
8
8
 
9
9
  ## 質問1
10
10
 
@@ -41,26 +41,8 @@
41
41
  3. Clientは1で共有したユーザ識別IDとBase64でエンコードされた署名をリクエストに同封して送信する
42
42
  4. APIはリクエストのユーザ識別IDから対応する秘密鍵を探し、その鍵とリクエストのURLとBodyから署名を作成、送信されてきた署名と比較を行い等しければ認証成功とする
43
43
 
44
-
45
44
  ## 質問2
46
45
 
47
- この認証方法の(セキュリティ的な)メリットについて知りたいです。
48
-
49
- メリットとしては以下のようなものがあると思います
50
-
51
- - `https://example.com/api/?token=XXXXX` このような形式のAPIと異なり、秘密鍵を通信しなくてもよい
52
- - 途中経路での改竄をHMACによる署名によって防ぐことができる
53
-
54
- ## 質問3
55
-
56
- [
57
- Secure ASP.NET Web API using API Key Authentication – HMAC Authentication](http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/)
58
-
59
- 元記事の実装では何かセキュリティ的な問題はあるのでしょうか。
60
- 私が理解できた範囲では特に問題はないのかなと思っています。
61
-
62
- ## 質問4
63
-
64
46
  自分でコードを書いてみましたので、セキュリティの観点からレビューをいただきたいです。
65
47
  Ruby on Railsで使用することを想定しています。
66
48
 

6

タグを追加

2018/02/08 12:06

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
File without changes

5

タグの追加

2018/01/30 09:56

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -62,6 +62,7 @@
62
62
  ## 質問4
63
63
 
64
64
  自分でコードを書いてみましたので、セキュリティの観点からレビューをいただきたいです。
65
+ Ruby on Railsで使用することを想定しています。
65
66
 
66
67
 
67
68
  ```ruby

4

レビュー観点の追加

2018/01/30 08:45

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -61,8 +61,9 @@
61
61
 
62
62
  ## 質問4
63
63
 
64
- 自分でコードを書いてみましたので、レビューをいただきたいです。
64
+ 自分でコードを書いてみましたので、セキュリティの観点からレビューをいただきたいです。
65
65
 
66
+
66
67
  ```ruby
67
68
  class HmacAuthentificator
68
69
  # アクセスIDヘッダ ユーザの識別を行う

3

不要コード削除

2018/01/30 08:44

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -77,10 +77,6 @@
77
77
  # 署名作成のハッシュ関数
78
78
  DIGEST_METHOD = 'sha256'
79
79
 
80
- # 秘密鍵(仮に定数としている、実際はハードコードしない)
81
- # SecureRandom.hex(32)で作成
82
- SECRET_TOKEN = 'a838b46b97a04ef5e6bf5127fd610f94ab60db8300cf149d70be8ffb9e3890a9'
83
-
84
80
  # タイムスタンプの期限切れ時間(秒)
85
81
  TIMESTAMP_EXPIRATION = 10.0
86
82
 

2

自分で実装したコードを追加

2018/01/30 08:42

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -57,4 +57,113 @@
57
57
  Secure ASP.NET Web API using API Key Authentication – HMAC Authentication](http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/)
58
58
 
59
59
  元記事の実装では何かセキュリティ的な問題はあるのでしょうか。
60
- 私が理解できた範囲では特に問題はないのかなと思っています。
60
+ 私が理解できた範囲では特に問題はないのかなと思っています。
61
+
62
+ ## 質問4
63
+
64
+ 自分でコードを書いてみましたので、レビューをいただきたいです。
65
+
66
+ ```ruby
67
+ class HmacAuthentificator
68
+ # アクセスIDヘッダ ユーザの識別を行う
69
+ X_ACCESS_ID_HEADER = 'X-Access-Id'
70
+
71
+ # 署名ヘッダ リクエストの正当性検証を担う
72
+ X_SIGNATURE_HEADER = 'X-Signature'
73
+
74
+ # タイムスタンプヘッダ replay attacks攻撃防止用
75
+ X_TIMESTAMP_HEADER = 'X-Timestamp'
76
+
77
+ # 署名作成のハッシュ関数
78
+ DIGEST_METHOD = 'sha256'
79
+
80
+ # 秘密鍵(仮に定数としている、実際はハードコードしない)
81
+ # SecureRandom.hex(32)で作成
82
+ SECRET_TOKEN = 'a838b46b97a04ef5e6bf5127fd610f94ab60db8300cf149d70be8ffb9e3890a9'
83
+
84
+ # タイムスタンプの期限切れ時間(秒)
85
+ TIMESTAMP_EXPIRATION = 10.0
86
+
87
+ # @param [ActionDispatch::Request] request
88
+ def initialize(request)
89
+ @request = request
90
+ end
91
+
92
+ # リクエストの正当性検証
93
+ # @return [Boolean]
94
+ def valid?
95
+ #
96
+ # タイムスタンプ
97
+ #
98
+ timestamp = @request.headers[X_TIMESTAMP_HEADER]
99
+ return false unless timestamp
100
+ parsed_timestamp = ::Time.zone.parse(timestamp)
101
+ return false unless parsed_timestamp
102
+ # タイムスタンプの有効期限検証,制限時間を超えているものと未来のものは拒否する
103
+ now = ::Time.zone.now
104
+ return false if now - parsed_timestamp > TIMESTAMP_EXPIRATION || parsed_timestamp > now
105
+
106
+ #
107
+ # アクセスID
108
+ #
109
+ access_id = @request.headers[X_ACCESS_ID_HEADER]
110
+ return false unless access_id
111
+
112
+ #
113
+ # 秘密鍵
114
+ #
115
+ secret_token = find_secret_token(access_id)
116
+ return false unless secret_token
117
+
118
+ #
119
+ # 署名
120
+ #
121
+ requested_signature = @request.headers[X_SIGNATURE_HEADER]
122
+ return false unless requested_signature
123
+
124
+ #
125
+ # 署名の再作成と検証
126
+ #
127
+ regenerated_signature = create_signature(secret_token, @request.original_url, @request.raw_post, timestamp)
128
+ # MITIGATE TIMING ATTACK
129
+ return false unless ::ActiveSupport::SecurityUtils.variable_size_secure_compare(regenerated_signature, requested_signature)
130
+ return false unless ::ActiveSupport::SecurityUtils.secure_compare(regenerated_signature, requested_signature)
131
+
132
+ return true
133
+ end
134
+
135
+ # @return [String|nil]
136
+ def find_secret_token(access_id)
137
+ # secret_tokenはDBに保存しておく
138
+ end
139
+
140
+ # リクエストから署名を作成
141
+ #
142
+ # @param [String] token 鍵文字列
143
+ # @param [String] url リクエストURL
144
+ # @param [String|nil] body リクエストボディ
145
+ # @param [String] timestamp - タイムスタンプ(ISO 8601)
146
+ # @return [String]
147
+ def create_signature(token, url, body, timestamp)
148
+ body = '' if body.nil?
149
+ content = [url, body, timestamp].map(&:strip).join
150
+ ::Base64.strict_encode64(::OpenSSL::HMAC.digest(DIGEST_METHOD, token, content))
151
+ end
152
+ end
153
+
154
+ # Railsコントローラ
155
+ class ExampleController < ApiBaseController
156
+ before_action :authentificate_api!
157
+
158
+ def index
159
+ render plain: 'ok'
160
+ end
161
+
162
+ def authentificate_api!
163
+ authentificator = HmacAuthentificator.new(request)
164
+ return true if @authentificator.valid?
165
+
166
+ fail(AuthentificationError, msg)
167
+ end
168
+ end
169
+ ```

1

サンプルの省略箇所を追記

2018/01/30 08:41

投稿

退会済みユーザー
title CHANGED
File without changes
body CHANGED
@@ -10,6 +10,7 @@
10
10
 
11
11
  まずはこの認証方法についてそもそもの理解ができているかの確認したく、
12
12
  記事のサンプルとは異なりますが自分の理解を兼ねて仕組みを以下に記載します。
13
+ ※元記事に記載があるナンスやタイムスタンプは省いています
13
14
 
14
15
  以下の内容に誤りなどありましたらご指摘いただけますでしょうか。
15
16