カプセル化とは、強い境界線を引くことです。Web ブラウザの場合は、自分のモバイル コードが他のモバイル コードに悪用されないようにすることを意味します。サーバー上では、検証されたデータと検証されていないデータ、あるユーザーのデータと別のユーザーのデータ、またはユーザーが見ることを許可されたデータと許可されていないデータの区別などを意味する場合があります。
script-src
、img-src
、object-src
、style_src
、font-src
、media-src
、frame-src
、connect-src
はリソース アクセスを制御します。この 8 つのディレクティブでは、そのディレクティブで処理される機能にサイトがアクセスできるドメインを指定する値として、ソース一覧を受け取ります。開発者はワイルドカード *
を使用するとソースの全部または一部を指示できます。ソース一覧キーワード、'unsafe-inline'
や 'unsafe-eval'
などを追加すると、スクリプト実行に対する制御の精度が高くなりますが、有害となる可能性があります。いずれのディレクティブも必須ではありません。ブラウザーは一覧にないディレクティブにもすべてのソースを許可するか、任意の default-src
ディレクティブからその値を導出します。また、このヘッダーの仕様は時間の経過とともに発展しています。Firefox ではバージョン 23 まで、IE ではバージョン 10 まで、X-Content-Security-Policy
として実装されていました。Chrome ではバージョン 25 まで X-Webkit-CSP
として実装されていました。こうした名前はいずれも廃止となり、現在は標準名 Content Security Policy
に取って代わられました。ディレクティブの数、廃止となった 2 つの代替名、同じヘッダーが複数回発生し 1 つのヘッダー内でディレクティブが繰り返される処理方法が指示される場合、開発者が誤ってこのヘッダーを設定する確率が高くなります。default-src
ディレクティブを設定します。
<http auto-config="true">
...
<headers>
...
<content-security-policy policy-directives="default-src '*'" />
</headers>
</http>
script-src
、img-src
、object-src
、style_src
、font-src
、media-src
、frame-src
、connect-src
はリソース アクセスを制御します。この 8 つのディレクティブでは、そのディレクティブで処理される機能にサイトがアクセスできるドメインを指定する値として、ソース一覧を受け取ります。開発者はワイルドカード *
を使用するとソースの全部または一部を指示できます。ソース一覧キーワード、'unsafe-inline'
や 'unsafe-eval'
などを追加すると、スクリプト実行に対する制御の精度が高くなりますが、有害となる可能性があります。いずれのディレクティブも必須ではありません。ブラウザーは一覧にないディレクティブにもすべてのソースを許可するか、任意の default-src
ディレクティブからその値を導出します。また、このヘッダーの仕様は時間の経過とともに発展しています。Firefox ではバージョン 23 まで、IE ではバージョン 10 まで、X-Content-Security-Policy
として実装されていました。Chrome ではバージョン 25 まで X-Webkit-CSP
として実装されていました。こうした名前はいずれも廃止となり、現在は標準名 Content Security Policy
に取って代わられました。ディレクティブの数、廃止となった 2 つの代替名、同じヘッダーが複数回発生し 1 つのヘッダー内でディレクティブが繰り返される処理方法が指示される場合、開発者が誤ってこのヘッダーを設定する確率が高くなります。*-src
ディレクティブは *
のような過度に許容的なポリシーで構成されています。django-csp
設定は過度に許容的で安全ではない default-src
ディレクティブを設定します。
...
MIDDLEWARE = (
...
'csp.middleware.CSPMiddleware',
...
)
...
CSP_DEFAULT_SRC = ("'self'", '*')
...
Access-Control-Allow-Origin
という新しい HTTP ヘッダーが定義されている場合、HTML5 では、JavaScript はドメイン間でデータにアクセスすることが可能です。生成元間の要求を使用してドメインにアクセスすることを許可する他のドメインを、Web サーバーはこのヘッダーを使用して定義します。しかし、このヘッダーを定義する場合には、注意が必要です。CORS ポリシーが過度に許容的であると、悪意のあるアプリケーションが不正に攻撃対象のサービスとやり取りし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
Response.AppendHeader("Access-Control-Allow-Origin", "*");
*
を Access-Control-Allow-Origin
ヘッダーの値として使用すると、アプリケーションのデータが、任意のドメインで実行される JavaScript にアクセスできることになります。Access-Control-Allow-Origin
という新しい HTTP ヘッダーが定義されている場合、HTML5 では、JavaScript はドメイン間でデータにアクセスすることが可能です。生成元間の要求を使用してドメインにアクセスすることを許可する他のドメインを、Web サーバーはこのヘッダーを使用して定義します。しかし、このヘッダーを定義する場合には、注意が必要です。CORS ポリシーが過度に許容的であると、悪意のあるアプリケーションが不正に攻撃対象のサービスとやり取りし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
<websocket:handlers allowed-origins="*">
<websocket:mapping path="/myHandler" handler="myHandler" />
</websocket:handlers>
*
を Access-Control-Allow-Origin
ヘッダーの値として使用すると、任意のドメインで実行されている JavaScript がアプリケーションのデータにアクセスできます。Access-Control-Allow-Origin
という新しい HTTP ヘッダーが定義されている場合、HTML5 では、JavaScript はドメイン間でデータにアクセスすることが可能です。生成元間の要求を使用してドメインにアクセスすることを許可する他のドメインを、Web サーバーはこのヘッダーを使用して定義します。しかし、このヘッダーを定義する場合には、注意が必要です。CORS ポリシーが過度に許容的であると、悪意のあるアプリケーションが不正に攻撃対象のサービスとやり取りし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
<?php
header('Access-Control-Allow-Origin: *');
?>
*
を Access-Control-Allow-Origin
ヘッダーの値として使用すると、アプリケーションのデータが、任意のドメインで実行される JavaScript にアクセスできることになります。Access-Control-Allow-Origin
という新しい HTTP ヘッダーが定義されている場合、HTML5 では、JavaScript はドメイン間でデータにアクセスすることが可能です。生成元間の要求を使用してドメインにアクセスすることを許可する他のドメインを、Web サーバーはこのヘッダーを使用して定義します。しかし、このヘッダーを定義する場合には、注意が必要です。CORS ポリシーが過度に許容的であると、悪意のあるアプリケーションが不正に攻撃対象のサービスとやり取りし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
response.addHeader("Access-Control-Allow-Origin", "*")
*
を Access-Control-Allow-Origin
ヘッダーの値として使用すると、アプリケーションのデータが、任意のドメインで実行される JavaScript にアクセスできることになります。Access-Control-Allow-Origin
という新しい HTTP ヘッダーが定義されている場合、HTML5 では、JavaScript はドメイン間でデータにアクセスすることが可能です。生成元間の要求を使用してドメインにアクセスすることを許可する他のドメインを、Web サーバーはこのヘッダーを使用して定義します。しかし、このヘッダーを定義する場合には、注意が必要です。CORS ポリシーが過度に許容的であると、悪意のあるアプリケーションが不正に攻撃対象のサービスとやり取りし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
play.filters.cors {
pathPrefixes = ["/some/path", ...]
allowedOrigins = ["*"]
allowedHttpMethods = ["GET", "POST"]
allowedHttpHeaders = ["Accept"]
preflightMaxAge = 3 days
}
*
を Access-Control-Allow-Origin
ヘッダーの値として使用すると、アプリケーションのデータが、任意のドメインで実行される JavaScript にアクセスできることになります。Access-Control-Allow-Origin
という新しい HTTP ヘッダーが定義されている場合、HTML5 では、JavaScript はドメイン間でデータにアクセスすることが可能です。生成元間の要求を使用してドメインにアクセスすることを許可する他のドメインを、Web サーバーはこのヘッダーを使用して定義します。しかし、このヘッダーを定義する場合には、注意が必要です。CORS ポリシーが過度に許容的であると、悪意のあるアプリケーションが不正に攻撃対象のサービスとやり取りし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
Response.AddHeader "Access-Control-Allow-Origin", "*"
*
を Access-Control-Allow-Origin
ヘッダーの値として使用すると、アプリケーションのデータが、任意のドメインで実行される JavaScript にアクセスできることになります。
WebMessage message = new WebMessage(WEBVIEW_MESSAGE);
webview.postWebMessage(message, Uri.parse("*"));
*
を使用するということは、このスクリプトが生成元に関係なくウィンドウにメッセージを送信していることを示します。
o.contentWindow.postMessage(message, '*');
*
を使用するということは、このスクリプトが生成元に関係なくウィンドウにメッセージを送信していることを示します。Unsafe-URL
に設定すると、アプリケーションで機密性の高いサイトやユーザー データ (セッション トークン、ユーザー名とパスワードを含む) が第三者サイトに開示されてしまう可能性があります。Referrer-Policy
ヘッダーは、リファラー ヘッダーに関連するブラウザーの動作を制御するために導入されました。Unsafe-URL
オプションはすべての制限を解除し、リクエストごとにリファラー ヘッダーを送信します。
<http auto-config="true">
...
<headers>
...
<referrer-policy policy="unsafe-url"/>
</headers>
</http>
Content-Security-Policy-Report-Only
ヘッダーにより、Web アプリケーションの作成者や管理者はセキュリティ ポリシーを強制適用するのではなく監視することができます。このヘッダーは通常、サイトのセキュリティ ポリシーを試用および/または開発する際に使用されます。ポリシーが有効であると判断された場合、代わりに Content-Security-Policy
ヘッダー フィールドを使用すると強制適用できます。Report-Only
モードに設定します。
<http auto-config="true">
...
<headers>
...
<content-security-policy report-only="true" policy-directives="default-src https://content.cdn.example.com" />
</headers>
</http>
Content-Security-Policy-Report-Only
ヘッダーにより、Web アプリケーションの作成者や管理者はセキュリティ ポリシーを強制適用するのではなく監視することができます。このヘッダーは通常、サイトのセキュリティ ポリシーを試用および/または開発する際に使用されます。ポリシーが有効であると判断された場合、代わりに Content-Security-Policy
ヘッダーを使用して強制適用できます。Report-Only
モードに設定します。
response.content_security_policy_report_only = "*"
SLComposeServiceViewController isContentValid
を実装して受け取った信頼できないデータを使用前に検証することができません。
#import <MobileCoreServices/MobileCoreServices.h>
@interface ShareViewController : SLComposeServiceViewController
...
@end
@interface ShareViewController ()
...
@end
@implementation ShareViewController
- (void)didSelectPost {
NSExtensionItem *item = self.extensionContext.inputItems.firstObject;
NSItemProvider *itemProvider = item.attachments.firstObject;
...
// Use the received items
...
[self.extensionContext completeRequestReturningItems:@[] completionHandler:nil];
}
...
@end
SLComposeServiceViewController isContentValid
を実装して受け取った信頼できないデータを使用前に検証することができません。SLComposeServiceViewController isContentValid
コールバック メソッドを実装してデータを検証することができません。
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
...
override func didSelectPost() {
let extensionItem = extensionContext?.inputItems.first as! NSExtensionItem
let itemProvider = extensionItem.attachments?.first as! NSItemProvider
...
// Use the received items
...
self.extensionContext?.completeRequestReturningItems([], completionHandler:nil)
}
...
}
webview
が URL を使用してアプリケーションと通信する際、受信側のアプリケーションは、通信すると想定されるアプリケーションの許可リストと送信者が一致することを検証する必要があります。受信側のアプリケーションは、UIApplicationDelegate application:openURL:options:
または UIApplicationDelegate application:openURL:sourceApplication:annotation:
委任メソッドを使用してコール URL の生成元を検証することもできます。UIApplicationDelegate application:openURL:options:
委任メソッドの実装では IPC コールの送信者の検証に失敗し、単にコール URL を処理します。
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
NSString *theQuery = [[url query] stringByRemovingPercentEncoding:NSUTF8StringEncoding];
NSArray *chunks = [theQuery componentsSeparatedByString:@"&"];
for (NSString* chunk in chunks) {
NSArray *keyval = [chunk componentsSeparatedByString:@"="]; NSString *key = [keyval objectAtIndex:0];
NSString *value = [keyval objectAtIndex:1];
// Do something with your key and value
}
return YES;
}
wewbview
が URL を使用してアプリケーションと通信する際、受信側のアプリケーションは、通信すると想定されるアプリケーションの許可リストと送信者が一致することを検証する必要があります。受信側のアプリケーションは、UIApplicationDelegate application:openURL:options:
または UIApplicationDelegate application:openURL:sourceApplication:annotation:
委任メソッドを使用してコール URL の生成元を検証することもできます。UIApplicationDelegate application:openURL:options:
委任メソッドの実装では IPC コールの送信者の検証に失敗し、単にコール URL を処理します。
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
return processCall(url)
}
webview
が URL を使用してアプリケーションと通信する際、受信側のアプリケーションはさらに操作を進める前に、コール URL を検証する必要があります。受信側のアプリケーションは、UIApplicationDelegate application:didFinishLaunchingWithOptions:
または UIApplicationDelegate application:willFinishLaunchingWithOptions:
委任メソッドを使用してコール URL を開くことを検証することもできます。UIApplicationDelegate application:didFinishLaunchingWithOptions:
委任メソッドの実装ではコール URL の検証に失敗し、常に信頼できない URL を処理します。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NS Dictionary *)launchOptions {
return YES;
}
webview
が URL を使用してアプリケーションと通信する際、受信側のアプリケーションはさらに操作を進める前に、コール URL を検証する必要があります。受信側のアプリケーションは、UIApplicationDelegate application:didFinishLaunchingWithOptions:
または UIApplicationDelegate application:willFinishLaunchingWithOptions:
委任メソッドを使用してコール URL を開くことを検証することもできます。UIApplicationDelegate application:didFinishLaunchingWithOptions:
委任メソッドの実装ではコール URL の検証に失敗し、常に信頼できない URL を処理します。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return true
}
allowBackup
属性を true
(デフォルト値) に設定し、<application>
タグの backupAgent
属性を定義することで行えます。Environment.getExternalStorageDirectory()
が Android デバイスの外部ストレージに参照を返しています。private void WriteToFile(String what_to_write) {
try{
File root = Environment.getExternalStorageDirectory();
if(root.canWrite()) {
File dir = new File(root + "write_to_the_SDcard");
File datafile = new File(dir, number + ".extension");
FileWriter datawriter = new FileWriter(datafile);
BufferedWriter out = new BufferedWriter(datawriter);
out.write(what_to_write);
out.close();
}
}
}
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:ThisDeviceOnly
を含まないアクセシビリティ レベルでは、暗号化されていないバックアップを使用する場合でも、iCloud および iTunes にバックアップされ、どのデバイスにもリストアできます。格納されているデータがどれだけ機密性が高く個人的かによっては、プライバシーの問題が発生する可能性があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleWhenUnlocked forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:ThisDeviceOnly
を含まないアクセシビリティ レベルでは、暗号化されていないバックアップを使用する場合でも、iCloud および iTunes にバックアップされ、どのデバイスにもリストアできます。格納されているデータがどれだけ機密性が高く個人的かによっては、プライバシーの問題が発生する可能性があります。
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlocked
SecItemAdd(query as CFDictionary, nil)
...
protected void onCreate(Bundle savedInstanceState) {
...
try {
File httpCacheDir = new File(context.getExternalCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) {
Log.i(TAG, "HTTP response cache installation failed:" + e);
}
}
protected void onStop() {
...
HttpResponseCache cache = HttpResponseCache.getInstalled();
if (cache != null) {
cache.flush();
}
}
{app ID}/Library/Caches/com.mycompany.myapp/Cache.db*
ファイルに暗号化せずに格納します。{app ID}/Library/Caches/com.mycompany.myapp/Cache.db*
ファイルに暗号化せずに格納します。{app ID}/Library/Caches/com.mycompany.myapp/Cache.db*
ファイルに暗号化せずに格納します。 URLCache
クラスの diskCapacity
または memoryCapacity
プロパティを 0 に設定することで、HTTP(S) レスポンス キャッシュ システムを効果的に無効化できると考えるかもしれません。しかし、NSURLCache
ドキュメントには、デバイスのメモリまたはディスク領域が残り少なくなった場合のみ、ディスク上のキャッシュとメモリ内のキャッシュの両方が設定されたサイズまで切り詰められると記載されています。両方の設定は、セキュリティ制御としてではなく、システム リソースを解放してパフォーマンスを向上させるために使用されます。{app ID}/Library/Caches/com.mycompany.myapp/Cache.db*
ファイルに暗号化せずに格納します。 URLCache
クラスの diskCapacity
または memoryCapacity
プロパティを 0 に設定することで、HTTP(S) レスポンス キャッシュ システムを効果的に無効化できると考えるかもしれません。しかし、NSURLCache
ドキュメントには、デバイスのメモリまたはディスク領域が残り少なくなった場合のみ、ディスク上のキャッシュとメモリ内のキャッシュの両方が設定されたサイズまで切り詰められると記載されています。両方の設定は、セキュリティ制御としてではなく、システム リソースを解放してパフォーマンスを向上させるために使用されます。NSFileManager
に定数として定義されます。つまり、NSFileManager
インスタンスと関連付けられた NSDictionary
に NSFileProtectionKey
鍵の値として割り当てられることになります。またファイルを作成するか、あるいは setAttributes:ofItemAtPath:error:
、attributesOfItemAtPath:error:
、createFileAtPath:contents:attributes:
などの NSFileManager
関数を使用して変更されるデータ保護クラスをファイルに含めることができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
として定義され、これを options
引数として NSData
関数 writeToURL:options:error:
および writeToFile:options:error:
に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingFileProtectionNone
:NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
でマーキングすると、ユーザーのパスワードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
の使用方法については慎重に検証し、今後も NSFileProtectionComplete
による保護が保証されるかどうかを見極める必要があります。例 2: 以下の例では、所定のデータはユーザーがデバイスの電源をオンにして初回のパスワードを入力するまでに限り保護されます (次の再起動まで)。
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSDictionary *protection = [NSDictionary dictionaryWithObject:NSFileProtectionCompleteUntilFirstUserAuthentication forKey:NSFileProtectionKey];
...
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:filepath error:nil];
...
BOOL ok = [testToWrite writeToFile:filepath atomically:YES encoding:NSUnicodeStringEncoding error:&err];
...
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSData *textData = [textToWrite dataUsingEncoding:NSUnicodeStingEncoding];
...
BOOL ok = [textData writeToFile:filepath options:NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication error:&err];
...
NSFileManager
に定数として定義されます。つまり、NSFileManager
インスタンスと関連付けられた Dictionary
に NSFileProtectionKey
鍵の値として割り当てられることになります。またファイルを作成するか、あるいは setAttributes(_:ofItemAtPath:)
、attributesOfItemAtPath(_:)
、createFileAtPath(_:contents:attributes:)
などの NSFileManager
関数を使用して変更されるデータ保護クラスをファイルに含めることができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
列挙型として定義されています。これは options
引数として NSData
の関数 (
writeToFile(_:options:)
など) に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingOptions.DataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingOptions.DataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingOptions.DataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingOptions.DataWritingFileProtectionNone
:NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
でマーキングすると、ユーザーのパスワードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、NSFileProtectionCompleteUnlessOpen
または NSFileProtectionCompleteUntilFirstUserAuthentication
の使用方法については慎重に検証し、今後も NSFileProtectionComplete
による保護が保証されるかどうかを見極める必要があります。例 2: 以下の例では、所定のデータはユーザーがデバイスの電源をオンにして初回のパスワードを入力するまでに限り保護されます (次の再起動まで)。
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
let protection = [NSFileProtectionKey: NSFileProtectionCompleteUntilFirstUserAuthentication]
do {
try NSFileManager.defaultManager().setAttributes(protection, ofItemAtPath: filename)
} catch let error as NSError {
NSLog("Unable to change attributes: \(error.debugDescription)")
}
...
BOOL ok = textToWrite.writeToFile(filename, atomically:true)
...
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
...
BOOL ok = textData.writeToFile(filepath, options: .DataWritingFileProtectionCompleteUntilFirstUserAuthentication);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
でマーキングすると、ユーザーのパスコードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、kSecAttrAccessibleAfterFirstUnlock
の使用方法については慎重に検証し、今後も保護が保証されるかどうかを見極める必要があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleAfterFirstUnlock forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAfterFirstUnlock
でマーキングすると、ユーザーのパスコードとデバイスの UID から導出された鍵を使用してファイルを暗号化できる一方、データは特定の状況下でアクセス可能のままになります。このように、kSecAttrAccessibleAfterFirstUnlock
の使用方法については慎重に検証し、今後も保護が保証されるかどうかを見極める必要があります。
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
SecItemAdd(query as CFDictionary, nil)
...
NSFileManager
に定数として定義されます。つまり、NSFileManager
インスタンスと関連付けられた NSDictionary
に NSFileProtectionKey
鍵の値として割り当てられることになります。またファイルを作成するか、あるいは setAttributes:ofItemAtPath:error:
、attributesOfItemAtPath:error:
、createFileAtPath:contents:attributes:
などの NSFileManager
関数を使用して変更されるデータ保護クラスをファイルに含めることができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
として定義され、これを options
引数として NSData
関数 writeToURL:options:error:
および writeToFile:options:error:
に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingFileProtectionNone
:NSFileProtectionNone
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、NSFileProtectionNone
の使用については慎重に検証し、今後もより厳格なデータ保護クラスによる保護が保証されることを見極める必要があります。例 2: 次の例では、所定のデータが保護されていません (デバイスの電源がオンのとき常にアクセス可能)。
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSDictionary *protection = [NSDictionary dictionaryWithObject:NSFileProtectionNone forKey:NSFileProtectionKey];
...
[[NSFileManager defaultManager] setAttributes:protection ofItemAtPath:filepath error:nil];
...
BOOL ok = [testToWrite writeToFile:filepath atomically:YES encoding:NSUnicodeStringEncoding error:&err];
...
...
filepath = [self.GetDocumentDirectory stringByAppendingPathComponent:self.setFilename];
...
NSData *textData = [textToWrite dataUsingEncoding:NSUnicodeStingEncoding];
...
BOOL ok = [textData writeToFile:filepath options:NSDataWritingFileProtectionNone error:&err];
...
NSFileManager
インスタンスに関連付けられた Dictionary
で NSFileProtectionKey
キーの値として割り当てるために、NSFileManager
で定数として定義されています。setAttributes(_:ofItemAtPath:)
、attributesOfItemAtPath(_:)
、createFileAtPath(_:contents:attributes:)
などの NSFileManager
の関数を使用すると、ファイルの作成やデータ保護クラスの変更を行うことができます。さらに、対応するデータ保護定数は NSData
オブジェクトに NSDataWritingOptions
列挙型として定義されています。これは options
引数として NSData
の関数 (
writeToFile(_:options:)
など) に渡すことができます。NSFileManager
および NSData
の各種データ保護クラス定数の定義を以下に示します。NSFileProtectionComplete
, NSDataWritingOptions.DataWritingFileProtectionComplete
:NSFileProtectionCompleteUnlessOpen
, NSDataWritingOptions.DataWritingFileProtectionCompleteUnlessOpen
:NSFileProtectionCompleteUntilFirstUserAuthentication
, NSDataWritingOptions.DataWritingFileProtectionCompleteUntilFirstUserAuthentication
:NSFileProtectionNone
, NSDataWritingOptions.DataWritingFileProtectionNone
:NSFileProtectionNone
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、NSFileProtectionNone
の使用については慎重に検証し、今後もより厳格なデータ保護クラスによる保護が保証されることを見極める必要があります。例 2: 次の例では、所定のデータが保護されていません (デバイスの電源がオンのとき常にアクセス可能)。
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
let protection = [NSFileProtectionKey: NSFileProtectionNone]
do {
try NSFileManager.defaultManager().setAttributes(protection, ofItemAtPath: filename)
} catch let error as NSError {
NSLog("Unable to change attributes: \(error.debugDescription)")
}
...
BOOL ok = textToWrite.writeToFile(filename, atomically:true)
...
...
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0])
let filename = "\(documentsPath)/tmp_activeTrans.txt"
...
BOOL ok = textData.writeToFile(filepath, options: .DataWritingFileProtectionNone);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、kSecAttrAccessibleAlways
の使用については慎重に検証し、今後もより厳格なキーチェーン アクセシビリティ レベルによる保護が保証されることを見極める必要があります。
...
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSData *token = [@"secret" dataUsingEncoding:NSUTF8StringEncoding];
// Configure KeyChain Item
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id) kSecClass];
[dict setObject:token forKey:(__bridge id)kSecValueData];
...
[dict setObject:(__bridge id)kSecAttrAccessibleAlways forKey:(__bridge id) kSecAttrAccessible];
OSStatus error = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
...
kSecAttrAccessible
キーの値として割り当てる必要があります。さまざまなキーチェーン アクセシビリティ定数の定義を以下に示します。kSecAttrAccessibleAfterFirstUnlock
:kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
:kSecAttrAccessibleAlways
:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
:kSecAttrAccessibleAlwaysThisDeviceOnly
:kSecAttrAccessibleWhenUnlocked
:kSecAttrAccessibleWhenUnlockedThisDeviceOnly
:kSecAttrAccessibleAlways
を指定すると、デバイスの UID のみに基づいて導出された鍵が暗号化に使用されます。これにより、デバイスの電源が入っているときはパスワードでロックされているときや起動時を含み、これらのファイルが常にアクセス可能になります。このため、kSecAttrAccessibleAlways
の使用については慎重に検証し、今後もより厳格なキーチェーン アクセシビリティ レベルによる保護が保証されることを見極める必要があります。
...
// Configure KeyChain Item
let token = "secret"
var query = [String : AnyObject]()
query[kSecClass as String] = kSecClassGenericPassword
query[kSecValueData as String] = token as AnyObject?
...
query[kSecAttrAccessible as String] = kSecAttrAccessibleAlways
SecItemAdd(query as CFDictionary, nil)
...