Wi-Fi ๋ฐ ๊ธฐํƒ€ ์—ฌ๋Ÿฌ ์•ฝ์–ด. ๋ถ€ํ’€์–ด ์˜ค๋ฅด์ง€ ์•Š๊ณ  Android ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Wi-Fi ๋…ธ๋“œ์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๋Š” ๋ฐฉ๋ฒ•

์–ด๋Š ๋‚  ์ €๋Š” Android ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Wi-Fi ๋„คํŠธ์›Œํฌ๋ฅผ ์Šค์บ”ํ•˜๊ณ  ์•ก์„ธ์Šค ํฌ์ธํŠธ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์–ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ๋ช‡ ๊ฐ€์ง€ ์–ด๋ ค์›€์— ์ง๋ฉดํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. off.Android ๋ฌธ์„œ ์„ค๋ช…๋œ ํด๋ž˜์Šค ์ค‘ ๋‹ค์ˆ˜๋Š” ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ(API ๋ ˆ๋ฒจ > 26) ์ด์— ๋ฐ˜์˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ์˜ ์ผ๋ถ€ ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์„ค๋ช…์€ ์ตœ์†Œํ•œ์ž…๋‹ˆ๋‹ค(์˜ˆ: ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ ํ•„๋“œ). ์Šค์บ” ๊ฒฐ๊ณผ ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์—๋Š” ์ค‘์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์ด ํฌํ•จ๋˜์–ด ์žˆ์ง€๋งŒ ์„ค๋ช…๋œ ๋‚ด์šฉ์ด ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค. ์„ธ ๋ฒˆ์งธ ์–ด๋ ค์›€์€ ์ฒ˜์Œ Wi-Fi์— ๊ฐ€๊นŒ์›Œ์ง€๋ฉด ์ด๋ก ์„ ์ฝ๊ณ  ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๋ผ์šฐํ„ฐ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ ์™ธ์— ๊ฐœ๋ณ„์ ์œผ๋กœ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์€ ์—ฌ๋Ÿฌ ์•ฝ์–ด๋ฅผ ๋‹ค๋ฃจ์–ด์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ๋“ค์„ ์–ด๋–ป๊ฒŒ ์—ฐ๊ด€์‹œํ‚ค๊ณ  ๊ตฌ์กฐํ™”ํ•  ๊ฒƒ์ธ์ง€๋Š” ๋ถ„๋ช…ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํŒ๋‹จ์€ ์ฃผ๊ด€์ ์ด๋ฉฐ ์ด์ „ ๊ฒฝํ—˜์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค).

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” NDK, ํ•ดํ‚น ์—†์ด Android API๋งŒ ์‚ฌ์šฉํ•˜์—ฌ Android ์ฝ”๋“œ์—์„œ Wi-Fi ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ํฌ๊ด„์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๊ณ  ์ด๋ฅผ ํ•ด์„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค.

์ง€์ฒดํ•˜์ง€ ๋ง๊ณ  ์ฝ”๋“œ ์ž‘์„ฑ์„ ์‹œ์ž‘ํ•ด ๋ณด์„ธ์š”.

1. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

์ด ๋…ธํŠธ๋Š” Android ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์ƒ์„ฑํ•œ ๋ถ„๋“ค์„ ์œ„ํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ์ด ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์ฝ”๋“œ๋Š” Kotlin, minSdkVersion=23์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

2. ์ ‘๊ทผ๊ถŒํ•œ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ Wi-Fi๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž๋กœ๋ถ€ํ„ฐ ๋ช‡ ๊ฐ€์ง€ ๊ถŒํ•œ์„ ์–ป์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์— ๋”ฐ๋ผ ์„ ์  ์„œ๋ฅ˜ ๋น„์น˜, OS ๋ฒ„์ „ 8.0 ์ดํ›„์˜ ์žฅ์น˜์—์„œ ๋„คํŠธ์›Œํฌ๋ฅผ ์Šค์บ”ํ•˜๋ ค๋ฉด ๋„คํŠธ์›Œํฌ ํ™˜๊ฒฝ ์ƒํƒœ ๋ณด๊ธฐ์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ์žฅ์น˜์˜ Wi-Fi ๋ชจ๋“ˆ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ์•ก์„ธ์Šค ๋˜๋Š” ์ขŒํ‘œ(๋Œ€๋žต)์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์ •ํ™•ํ•จ). ๋ฒ„์ „ 9.0๋ถ€ํ„ฐ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‘ ๊ฐ€์ง€ ๋ชจ๋‘๋ฅผ ๋ฌป๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์‚ฌ์šฉ์ž์—๊ฒŒ ์œ„์น˜ ์„œ๋น„์Šค๋ฅผ ์ผœ๋„๋ก ๋ช…์‹œ์ ์œผ๋กœ ์š”์ฒญํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” Google์˜ ๋ณ€๋•์ด์ง€ ์‚ฌ์šฉ์ž๋ฅผ ์—ผํƒํ•˜๋ ค๋Š” ์šฐ๋ฆฌ์˜ ์š•๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ์‚ฌ์šฉ์ž์—๊ฒŒ ์šฉ๊ฐํ•˜๊ฒŒ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”. :)

๋”ฐ๋ผ์„œ AndroidManifest.xml์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    <uses-permission android_name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android_name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android_name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android_name="android.permission.ACCESS_FINE_LOCATION"/>

๊ทธ๋ฆฌ๊ณ  ํ˜„์žฌ ํ™œ๋™์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ํฌํ•จ๋œ ์ฝ”๋“œ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

import android.app.Activity
import android.content.Context
import android.location.LocationManager
import androidx.core.app.ActivityCompat

....

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
            makeEnableLocationServices(activity.applicationContext)
        } else {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.CHANGE_WIFI_STATE),
                1
            )
        }

    /* ะฒะบะปัŽั‡ะฐะตั‚ ัะบั€ะฐะฝ ะฒะบะปัŽั‡ะตะฝะธั ัะปัƒะถะฑั‹ ะฟะพ ะพะฟั€ะตะดะตะปะตะฝะธัŽ ะผะตัั‚ะพะฟะพะปะพะถะตะฝะธั */
    fun makeEnableLocationServices(context: Context) {
        // TODO: ะฟะตั€ะตะด ะฒั‹ะทะพะฒะพะผ ัั‚ะพะน ั„ัƒะฝะบั†ะธะธ ะฝะฐะดะพ ั€ะฐััะบะฐะทะฐั‚ัŒ ะฟะพะปัŒะทะพะฒะฐั‚ะตะปัŽ, ะทะฐั‡ะตะผ ะ’ะฐะผ ะดะพัั‚ัƒะฟ ะบ ะผะตัั‚ะพะฟะพะปะพะถะตะฝะธัŽ
        val lm: LocationManager =
            context.applicationContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager

        val gpsEnabled: Boolean = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        val networkEnabled: Boolean = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!gpsEnabled && !networkEnabled) {
            context.startActivity(Intent(ACTION_LOCATION_SOURCE_SETTINGS));
        }
    }

3. BroadcastReceiver๋ฅผ ์ƒ์„ฑํ•˜๊ณ  Wi-Fi ๋„คํŠธ์›Œํฌ ํ™˜๊ฒฝ ๊ฒ€์ƒ‰์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ ์—…๋ฐ์ดํŠธ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•ฉ๋‹ˆ๋‹ค.

val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager

val wifiScanReceiver = object : BroadcastReceiver() {

  override fun onReceive(context: Context, intent: Intent) {
    val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false)
    if (success) {
      scanSuccess()
    } 
  }
}

val intentFilter = IntentFilter()
/* ะฟะพะดะฟะธัั‹ะฒะฐะตะผัั ะฝะฐ ัะพะพะฑั‰ะตะฝะธั ะพ ะฟะพะปัƒั‡ะตะฝะธะธ ะฝะพะฒั‹ั… ั€ะตะทัƒะปัŒั‚ะฐั‚ะพะฒ ัะบะฐะฝะธั€ะพะฒะฐะฝะธั */
intentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)
context.registerReceiver(wifiScanReceiver, intentFilter)

val success = wifiManager.startScan()
if (!success) {
  /* ั‡ั‚ะพ-ั‚ะพ ะฝะต ะฟะพะปัƒั‡ะธะปะพััŒ ะฟั€ะธ ะทะฐะฟัƒัะบะต ัะบะฐะฝะธั€ะพะฒะฐะฝะธั, ะฟั€ะพะฒะตั€ัŒั‚ะต ะฒั‹ะดะฐะฝั‹ะต ั€ะฐะทั€ะตัˆะตะฝะธั */
}

....

private fun scanSuccess() {
 /* ะฒะพั‚ ะพะฝะธ, ั€ะตะทัƒะปัŒั‚ะฐั‚ั‹ ัะบะฐะฝะธั€ะพะฒะฐะฝะธั */
  val results: List<ScanResult> = wifiManager.scanResults
}

๋ฌธ์„œ์˜ WiFiManager.startScan ๋ฉ”์†Œ๋“œ๋Š” API ๋ฒ„์ „ 28๋ถ€ํ„ฐ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์–ด ์žˆ์ง€๋งŒ ๊บผ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ˆ๋‚ด ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ „์ฒด์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๊ฐ์ฒด ๋ชฉ๋ก์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ์Šค์บ” ๊ฒฐ๊ณผ.

4. ScanResult๋ฅผ ๋ณด๊ณ  ์šฉ์–ด๋ฅผ ์ดํ•ดํ•˜์„ธ์š”.

์ด ํด๋ž˜์Šค์˜ ์ผ๋ถ€ ํ•„๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ํ•ด๋‹น ํ•„๋“œ์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

SSID โ€” ์„œ๋น„์Šค ์„ธํŠธ ์‹๋ณ„์ž๋Š” ๋„คํŠธ์›Œํฌ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

BSSID โ€“ ๊ธฐ๋ณธ ์„œ๋น„์Šค ์„ธํŠธ ์‹๋ณ„์ž โ€“ ๋„คํŠธ์›Œํฌ ์–ด๋Œ‘ํ„ฐ(Wi-Fi ํฌ์ธํŠธ)์˜ MAC ์ฃผ์†Œ

์ˆ˜ํ‰ โ€” ์ˆ˜์‹  ์‹ ํ˜ธ ๊ฐ•๋„ ํ‘œ์‹œ๊ธฐ [dBm(๋Ÿฌ์‹œ์•„์–ด dBm) โ€” ๋ฐ์‹œ๋ฒจ, ๊ธฐ์ค€ ์ „๋ ฅ 1mW.] โ€” ์ˆ˜์‹  ์‹ ํ˜ธ ๊ฐ•๋„ ํ‘œ์‹œ๊ธฐ. 0์—์„œ -100 ์‚ฌ์ด์˜ ๊ฐ’์„ ์ทจํ•˜๋ฉฐ, 0์—์„œ ๋ฉ€์–ด์งˆ์ˆ˜๋ก Wi-Fi ํฌ์ธํŠธ์—์„œ ์žฅ์น˜๊นŒ์ง€์˜ ๊ฒฝ๋กœ์—์„œ ๋” ๋งŽ์€ ์‹ ํ˜ธ ์ „๋ ฅ์ด ์†์‹ค๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„ํ‚คํ”ผ๋””์•„. ์—ฌ๊ธฐ์„œ๋Š” Android ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™€์ดํŒŒ์ด๋งค๋‹ˆ์ € ์„ ํƒํ•œ ๋‹จ๊ณ„์—์„œ ์‹ ํ˜ธ ๋ ˆ๋ฒจ์„ ๋งค์šฐ ์ข‹์Œ๋ถ€ํ„ฐ ๋‚˜์จ๊นŒ์ง€ ์ฒ™๋„๋กœ ๊ต์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
        val numberOfLevels = 5
        val level = WifiManager.calculateSignalLevel(level, numberOfLevels)

์ฃผํŒŒ์ˆ˜ โ€” Wi-Fi ํฌ์ธํŠธ์˜ ์ž‘๋™ ์ฃผํŒŒ์ˆ˜[Hz]. ์ฃผํŒŒ์ˆ˜ ์ž์ฒด ์™ธ์—๋„ ์†Œ์œ„ ์ฑ„๋„์— ๊ด€์‹ฌ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์ง€์ ์—๋Š” ๊ณ ์œ ํ•œ ์ž‘๋™ ์ˆœ๋„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์—์„œ ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” Wi-Fi ํฌ์ธํŠธ ๋ฒ”์œ„๋Š” 2.4GHz์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋” ์ •ํ™•ํ•˜๊ฒŒ ๋งํ•˜๋ฉด ํฌ์ธํŠธ๋Š” ์ด๋ฆ„์ด ์ง€์ •๋œ ์ฃผํŒŒ์ˆ˜์— ๊ฐ€๊นŒ์šด ๋ฒˆํ˜ธ๊ฐ€ ๋งค๊ฒจ์ง„ ์ฃผํŒŒ์ˆ˜๋กœ ์ •๋ณด๋ฅผ ํœด๋Œ€ํฐ์œผ๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. ์ฑ„๋„ ์ˆ˜ ๋ฐ ํ•ด๋‹น ์ฃผํŒŒ์ˆ˜ ํ‘œ์ค€ํ™”๋œ. ์ด๋Š” ์ธ๊ทผ ์ง€์ ์ด ์„œ๋กœ ๋‹ค๋ฅธ ์ฃผํŒŒ์ˆ˜์—์„œ ์ž‘๋™ํ•˜์—ฌ ์„œ๋กœ ๊ฐ„์„ญํ•˜์ง€ ์•Š๊ณ  ์ „์†ก ์†๋„์™€ ํ’ˆ์งˆ์„ ์ƒํ˜ธ ์ €ํ•˜์‹œํ‚ค์ง€ ์•Š๋„๋ก ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํฌ์ธํŠธ๋Š” ํ•˜๋‚˜์˜ ์ฃผํŒŒ์ˆ˜์—์„œ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‹ค์–‘ํ•œ ์ฃผํŒŒ์ˆ˜(๋งค๊ฐœ๋ณ€์ˆ˜)์— ๊ฑธ์ณ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฑ„๋„ ํญ)๋ฅผ ์ฑ„๋„ ํญ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ธ์ ‘ํ•œ(์ธ์ ‘ํ•œ ์ฑ„๋„๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ž์ฒด์ ์œผ๋กœ 3๊ฐœ์ธ) ์ฑ„๋„์—์„œ ์ž‘๋™ํ•˜๋Š” ์ง€์ ์ด ์„œ๋กœ ๊ฐ„์„ญํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฃผํŒŒ์ˆ˜๊ฐ€ 2.4 ๋ฐ 5Ghz์ธ ์ง€์ ์˜ ์ฃผํŒŒ์ˆ˜ ๊ฐ’์—์„œ ์ฑ„๋„ ๋ฒˆํ˜ธ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


    /* ะฟะพ ั‡ะฐัั‚ะพั‚ะต ะพะฟั€ะตะดะตะปัะตะผ ะฝะพะผะตั€ ะบะฐะฝะฐะปะฐ */
    val channel: Int
        get() {
            return if (frequency in 2412..2484) {
                (frequency - 2412) / 5 + 1
            } else if (frequency in 5170..5825) {
                (frequency - 5170) / 5 + 34
            } else {
                -1
            }
        }

๊ธฐ๋Šฅ - ๊ฐ€์žฅ ํฅ๋ฏธ๋กœ์šด ๋ถ„์„ ๋ถ„์•ผ๋กœ ์ž‘์—…ํ•˜๋Š”๋ฐ ๋งŽ์€ ์‹œ๊ฐ„์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ํฌ์ธํŠธ์˜ "๋Šฅ๋ ฅ"์ด ์ค„์— ์ ํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ฌธ์„œ์—์„œ ๋ฌธ์ž์—ด ํ•ด์„์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ์ฐพ์„ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์ด ์ค„์— ํฌํ•จ๋  ์ˆ˜ ์žˆ๋Š” ๋‚ด์šฉ์˜ ๋ช‡ ๊ฐ€์ง€ ์˜ˆ์ž…๋‹ˆ๋‹ค.

[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][WPS][ESS]
[WPA2-PSK-CCMP][ESS]
[WPA2-PSK-CCMP+TKIP][ESS]
[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS]
[ESS][WPS]

5. ์•ฝ์–ด ์ดํ•ด ๋ฐ ๊ตฌ๋ฌธ ๋ถ„์„ ๊ธฐ๋Šฅ

android.net.wifi.* ํŒจํ‚ค์ง€์˜ ํด๋ž˜์Šค๊ฐ€ Linux ์œ ํ‹ธ๋ฆฌํ‹ฐ์— ์˜ํ•ด ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค๋Š” ์ ์€ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. wpa_supplicant๋ฅผ ๊ธฐ๋Šฅ ํ•„๋“œ์˜ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” ์Šค์บ” ์‹œ ํ”Œ๋ž˜๊ทธ ํ•„๋“œ์˜ ๋ณต์‚ฌ๋ณธ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ง€์†์ ์œผ๋กœ ํ–‰๋™ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋จผ์ € ๊ด„ํ˜ธ ์•ˆ์˜ ์š”์†Œ๊ฐ€ "-" ๊ธฐํ˜ธ๋กœ ๊ตฌ๋ถ„๋˜๋Š” ํ˜•์‹์˜ ์ถœ๋ ฅ์„ ๊ณ ๋ คํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

[WPA-PSK-TKIP+CCMP]
[WPA2-PSK-CCMP]

์ฒซ ๋ฒˆ์งธ ์˜๋ฏธ๋Š” ์†Œ์œ„๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ ๋ฐฉ๋ฒ•. ์ฆ‰, ์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ ์ž์ฒด์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋„๋ก ํ—ˆ์šฉํ•˜๋ ค๋ฉด ์žฅ์น˜์™€ ์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ผ๋ จ์˜ ์ž‘์—…๊ณผ ํŽ˜์ด๋กœ๋“œ๋ฅผ ์•”ํ˜ธํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ๊ฒŒ์‹œ๋ฌผ์„ ์ž‘์„ฑํ•  ๋‹น์‹œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์˜ต์…˜์€ WPA ๋ฐ WPA2๋กœ, ๊ฐ ์žฅ์น˜๋Š” ์ง์ ‘ ๋˜๋Š” ์†Œ์œ„๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. RADIUS ์„œ๋ฒ„(WPA-Enterprice)๋Š” ์•”ํ˜ธํ™”๋œ ์ฑ„๋„์„ ํ†ตํ•ด ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์ง‘์— ์žˆ๋Š” ์•ก์„ธ์Šค ํฌ์ธํŠธ๋Š” ์ด ๊ตฌ์„ฑํ‘œ์— ๋”ฐ๋ผ ์—ฐ๊ฒฐ์„ ์ œ๊ณตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋ฒ„์ „๊ณผ ์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „์˜ ์ฐจ์ด์ ์€ AES์™€ ์•ˆ์ „ํ•˜์ง€ ์•Š์€ TKIP๋ผ๋Š” ๋” ๊ฐ•๋ ฅํ•œ ์•”ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”์šฑ ๋ณต์žกํ•˜๊ณ  ๋ฐœ์ „๋œ WPA3๋„ ์ ์ฐจ ๋„์ž…๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ก ์ ์œผ๋กœ๋Š” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์†”๋ฃจ์…˜ CCKM(Cisco Centralized Key Management)์— ์˜ต์…˜์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์ €๋Š” ๊ทธ๋Ÿฐ ์˜ต์…˜์„ ๋ณธ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค.

์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ MAC ์ฃผ์†Œ๋กœ ์ธ์ฆ๋˜๋„๋ก ๊ตฌ์„ฑ๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ ์˜ค๋ž˜๋œ WEP ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ์šฐ ์‹ค์ œ๋กœ๋Š” ์ธ์ฆ์ด ์—†์Šต๋‹ˆ๋‹ค(์—ฌ๊ธฐ์„œ ๋น„๋ฐ€ ํ‚ค๋Š” ์•”ํ˜ธํ™” ํ‚ค์ž…๋‹ˆ๋‹ค). ์šฐ๋ฆฌ๋Š” ๊ทธ๋Ÿฌํ•œ ์˜ต์…˜์„ OTHER๋กœ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค.
๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•œ ์ธ์ฆ ์š”์ฒญ์ธ ์ˆจ๊ฒจ์ง„ ์ข…์† ํฌํ„ธ ๊ฐ์ง€ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ๊ณต์šฉ Wi-Fi์—์„œ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์•ก์„ธ์Šค ํฌ์ธํŠธ๋Š” ์Šค์บ๋„ˆ์— ์—ด๋ ค ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค(๋ฌผ๋ฆฌ์  ์—ฐ๊ฒฐ์˜ ๊ด€์ ์—์„œ ๋ณผ ๋•Œ). ๋”ฐ๋ผ์„œ OPEN์œผ๋กœ ๋ถ„๋ฅ˜ํ•ฉ๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ๊ฐ’์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ‚ค ๊ด€๋ฆฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜. ์œ„์—์„œ ์„ค๋ช…ํ•œ ์ธ์ฆ ๋ฐฉ๋ฒ•์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค. ์•”ํ˜ธํ™” ํ‚ค๊ฐ€ ๊ตํ™˜๋˜๋Š” ์ •ํ™•ํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ์˜ต์…˜์„ ๊ณ ๋ คํ•ด ๋ด…์‹œ๋‹ค. EAP - ์–ธ๊ธ‰๋œ WPA-Enterprice์—์„œ ์‚ฌ์šฉ๋˜๋ฉฐ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž…๋ ฅ๋œ ์ธ์ฆ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. SAE - ๊ณ ๊ธ‰ WPA3์— ์‚ฌ์šฉ๋˜๋ฉฐ ๋ฌด์ฐจ๋ณ„ ๋Œ€์ž…์— ๋” ๊ฐ•ํ•ฉ๋‹ˆ๋‹ค. PSK - ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์˜ต์…˜์€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ด๋ฅผ ์•”ํ˜ธํ™”๋œ ํ˜•์‹์œผ๋กœ ์ „์†กํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. IEEE8021X - ๊ตญ์ œ ํ‘œ์ค€์— ๋”ฐ๋ฆ„(WPA ์ œํ’ˆ๊ตฐ์—์„œ ์ง€์›ํ•˜๋Š” ๊ฒƒ๊ณผ ๋‹ค๋ฆ„) OWE(Opportunistic Wireless Encryption)๋Š” OPEN์œผ๋กœ ๋ถ„๋ฅ˜๋œ ํฌ์ธํŠธ์— ๋Œ€ํ•œ IEEE 802.11 ํ‘œ์ค€์˜ ํ™•์žฅ์ž…๋‹ˆ๋‹ค. OWE๋Š” ๋ณด์•ˆ๋˜์ง€ ์•Š์€ ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์ „์†ก๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์•”ํ˜ธํ™”ํ•˜์—ฌ ๋ณด์•ˆ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์•ก์„ธ์Šค ํ‚ค๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋„ ์˜ต์…˜์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์„ NONE์ด๋ผ๊ณ  ๋ถ€๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

์„ธ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ์†Œ์œ„์ž…๋‹ˆ๋‹ค. ์•”ํ˜ธํ™” ๋ฐฉ์‹ โ€” ์ „์†ก๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณดํ˜ธํ•˜๊ธฐ ์œ„ํ•ด ์•”ํ˜ธ๊ฐ€ ์–ผ๋งˆ๋‚˜ ์ •ํ™•ํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€. ์˜ต์…˜์„ ๋‚˜์—ดํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. WEP - RC4 ์ŠคํŠธ๋ฆผ ์•”ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋น„๋ฐ€ ํ‚ค๋Š” ์•”ํ˜ธํ™” ํ‚ค๋กœ, ํ˜„๋Œ€ ์•”ํ˜ธํ™” ์„ธ๊ณ„์—์„œ๋Š” ํ—ˆ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. TKIP - WPA, CKIP - WPA2์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. TKIP+CKIP - ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด WPA ๋ฐ WPA2๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ง€์ ์—์„œ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ธ ๊ฐ€์ง€ ์š”์†Œ ๋Œ€์‹  ์™ธ๋กœ์šด WEP ํ‘œ์‹œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

[WEP]

์œ„์—์„œ ๋…ผ์˜ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ‚ค ์‚ฌ์šฉ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ผํ•œ ์•”ํ˜ธํ™” ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋‹ค์Œ ๋ธŒ๋ž˜ํ‚ท์„ ๊ณ ๋ คํ•˜์‹ญ์‹œ์˜ค.

[ESS]

๊ทธ๊ฒƒ Wi-Fi ์ž‘๋™ ๋ชจ๋“œ ๋˜๋Š” Wi-Fi ๋„คํŠธ์›Œํฌ ํ† ํด๋กœ์ง€. ์—ฐ๊ฒฐ๋œ ์žฅ์น˜๊ฐ€ ํ†ต์‹ ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ ํ•˜๋‚˜์ธ ๊ฒฝ์šฐ BSS(๊ธฐ๋ณธ ์„œ๋น„์Šค ์„ธํŠธ) ๋ชจ๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋กœ์ปฌ ๋„คํŠธ์›Œํฌ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ๋กœ์ปฌ ๋„คํŠธ์›Œํฌ์˜ ์žฅ์น˜๋ฅผ ์—ฐ๊ฒฐํ•˜๋ ค๋ฉด ์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ ํ™•์žฅ ์„œ๋น„์Šค ์„ธํŠธ(ESS)์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค. IBSS(๋…๋ฆฝ ๊ธฐ๋ณธ ์„œ๋น„์Šค ์„ธํŠธ) ์œ ํ˜•์€ ์žฅ์น˜๊ฐ€ ํ”ผ์–ด ํˆฌ ํ”ผ์–ด ๋„คํŠธ์›Œํฌ์˜ ์ผ๋ถ€์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

WPS ํ”Œ๋ž˜๊ทธ๋„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

[WPS]

WPS(Wi-Fi Protected Setup)๋Š” Wi-Fi ๋„คํŠธ์›Œํฌ์˜ ๋ฐ˜์ž๋™ ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™”ํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ 8์ž๋ฆฌ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•˜๊ฑฐ๋‚˜ ๋ผ์šฐํ„ฐ์˜ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด์„ธ์š”. ์•ก์„ธ์Šค ํฌ์ธํŠธ๊ฐ€ ์ฒซ ๋ฒˆ์งธ ์œ ํ˜•์ด๊ณ  ์ด ํ™•์ธ๋ž€์ด ์•ก์„ธ์Šค ํฌ์ธํŠธ ์ด๋ฆ„ ์˜†์— ๋‚˜ํƒ€๋‚˜๋ฉด ๊ด€๋ฆฌ์ž ํŒจ๋„๋กœ ์ด๋™ํ•˜์—ฌ WPS ์•ก์„ธ์Šค๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์‚ฌ์‹ค 8์ž๋ฆฌ PIN์€ MAC ์ฃผ์†Œ๋กœ ์•Œ์•„๋‚ผ ์ˆ˜ ์žˆ๊ฑฐ๋‚˜ ์˜ˆ์ธก ๊ฐ€๋Šฅํ•œ ์‹œ๊ฐ„ ๋‚ด์— ์ •๋ฆฌ๋˜์–ด ๋ถ€์ •์งํ•œ ์‚ฌ๋žŒ์ด ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

6. ๋ชจ๋ธ ๋ฐ ํŒŒ์‹ฑ ๊ธฐ๋Šฅ ์ƒ์„ฑ

์œ„์—์„œ ์•Œ์•„๋‚ธ ๋‚ด์šฉ์„ ๋ฐ”ํƒ•์œผ๋กœ ๋ฐ์ดํ„ฐ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

/* ัั…ะตะผะฐ ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ */
enum class AuthMethod {
    WPA3,
    WPA2,
    WPA, // Wi-Fi Protected Access
    OTHER, // ะฒะบะปัŽั‡ะฐะตั‚ ะฒ ัะตะฑั Shared Key Authentication ะธ ะดั€. ะธัะฟะพะปัŒะทัƒัŽั‰ะธะต mac-address-based ะธ WEP
    CCKM, // Cisco
    OPEN // Open Authentication. ะœะพะถะตั‚ ะฑั‹ั‚ัŒ ัะพ ัะบั€ั‹ั‚ั‹ะผ Captive Portal Detection - ะทะฐะฟั€ะพั ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ ั‡ะตั€ะตะท ะฑั€ะฐัƒะทะตั€
}

/* ะฐะปะณะพั€ะธั‚ะผ ะฒะฒะพะดะฐ ะบะปัŽั‡ะตะน */
enum class KeyManagementAlgorithm {
    IEEE8021X, // ะฟะพ ัั‚ะฐะฝะดะฐั€ั‚ัƒ
    EAP, // Extensible Authentication Protocol, ั€ะฐััˆะธั€ัะตะผั‹ะน ะฟั€ะพั‚ะพะบะพะป ะฐัƒั‚ะตะฝั‚ะธั„ะธะบะฐั†ะธะธ
    PSK, // Pre-Shared Key โ€” ะบะฐะถะดั‹ะน ัƒะทะตะป ะฒะฒะพะดะธั‚ ะฟะฐั€ะพะปัŒ ะดะปั ะดะพัั‚ัƒะฟะฐ ะบ ัะตั‚ะธ
    WEP, // ะฒ WEP ะฟะฐั€ะพะปัŒ ัะฒะปัะตั‚ัั ะบะปัŽั‡ะพะผ ัˆะธั„ั€ะพะฒะฐะฝะธั (No auth key)
    SAE, // Simultaneous Authentication of Equals - ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฒ WPA3
    OWE, // Opportunistic Wireless Encryption - ะฒ ั€ะพัƒั‚ะตั€ะฐั… ะฝะพะฒั‹ั… ะฟะพะบะพะปะตะฝะธะน, ะฟัƒะฑะปะธั‡ะฝั‹ั… ัะตั‚ัั… ั‚ะธะฟะฐ OPEN
    NONE // ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฑะตะท ัˆะธั„ั€ะพะฒะฐะฝะธั ะฒ OPEN, OTHER
}

/* ะผะตั‚ะพะด ัˆะธั„ั€ะพะฒะฐะฝะธั */
enum class CipherMethod {
    WEP, // Wired Equivalent Privacy, ะะฝะฐะปะพะณ ัˆะธั„ั€ะพะฒะฐะฝะธั ั‚ั€ะฐั„ะธะบะฐ ะฒ ะฟั€ะพะฒะพะดะฝั‹ั… ัะตั‚ัั…
    TKIP, // Temporal Key Integrity Protocol
    CCMP, // Counter Mode with Cipher Block Chaining Message Authentication Code Protocol,
    // ะฟั€ะพั‚ะพะบะพะป ะฑะปะพั‡ะฝะพะณะพ ัˆะธั„ั€ะพะฒะฐะฝะธั ั ะบะพะดะพะผ ะฐัƒั‚ะตะฝั‚ะธั‡ะฝะพัั‚ะธ ัะพะพะฑั‰ะตะฝะธั ะธ ั€ะตะถะธะผะพะผ ัั†ะตะฟะปะตะฝะธั ะฑะปะพะบะพะฒ ะธ ัั‡ะตั‚ั‡ะธะบะฐ
    // ะฝะฐ ะพัะฝะพะฒะต AES
    NONE // ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ะฑะตะท ัˆะธั„ั€ะพะฒะฐะฝะธั ะฒ OPEN, OTHER
}

/* ะฝะฐะฑะพั€ ะผะตั‚ะพะดะพะฒ ัˆะธั„ั€ะพะฒะฐะฝะธั ะธ ะฟั€ะพั‚ะพะบะพะปะพะฒ, ะฟะพ ะบะพั‚ะพั€ั‹ะผ ะผะพะถะตั‚ ั€ะฐะฑะพั‚ะฐั‚ัŒ ั‚ะพั‡ะบะฐ */
data class Capability(
    var authScheme: AuthMethod? = null,
    var keyManagementAlgorithm: KeyManagementAlgorithm? = null,
    var cipherMethod: CipherMethod? = null
)

/* ะ ะตะถะธะผ ั€ะฐะฑะพั‚ั‹ WiFi (ะธะปะธ ั‚ะพะฟะพะปะพะณะธั ัะตั‚ะตะน WiFi) */
enum class TopologyMode {
    IBSS, // ะญะฟะธะทะพะดะธั‡ะตัะบะฐั ัะตั‚ัŒ (Ad-Hoc ะธะปะธ IBSS โ€“ Independent Basic Service Set).
    BSS, // ะžัะฝะพะฒะฝะฐั ะทะพะฝะฐ ะพะฑัะปัƒะถะธะฒะฐะฝะธั Basic Service Set (BSS) ะธะปะธ Infrastructure Mode.
    ESS // ะ ะฐััˆะธั€ะตะฝะฝะฐั ะทะพะฝะฐ ะพะฑัะปัƒะถะธะฒะฐะฝะธั ESS โ€“ Extended Service Set.
}

์ด์ œ ๊ธฐ๋Šฅ ํ•„๋“œ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


private fun parseCapabilities(capabilitiesString: String): List < Capability > {
    val capabilities: List < Capability > = capabilitiesString
        .splitByBrackets()
        .filter {
            !it.isTopology() && !it.isWps()
        }
        .flatMap {
            parseCapability(it)
        }
    return
        if (!capabilities.isEmpty()) {
            capabilities
        } else {
            listOf(Capability(AuthMethod.OPEN, KeyManagementAlgorithm.NONE, CipherMethod.NONE))
        }
}

private fun parseCapability(part: String): List < Capability > {
    if (part.contains("WEP")) {
        return listOf(Capability(
            AuthMethod.OTHER,
            KeyManagementAlgorithm.WEP,
            CipherMethod.WEP
        ))
    }

    val authScheme = when {
        part.contains("WPA3") - > AuthMethod.WPA3
        part.contains("WPA2") - > AuthMethod.WPA2
        part.contains("WPA") - > AuthMethod.WPA
        else - > null
    }

    val keyManagementAlgorithm = when {
        part.contains("OWE") - > KeyManagementAlgorithm.OWE
        part.contains("SAE") - > KeyManagementAlgorithm.SAE
        part.contains("IEEE802.1X") - > KeyManagementAlgorithm.IEEE8021X
        part.contains("EAP") - > KeyManagementAlgorithm.EAP
        part.contains("PSK") - > KeyManagementAlgorithm.PSK
        else - > null
    }

    val capabilities = ArrayList < Capability > ()
    if (part.contains("TKIP") || part.contains("CCMP")) {
        if (part.contains("TKIP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.TKIP
            ))
        }
        if (part.contains("CCMP")) {
            capabilities.add(Capability(
                authScheme ? : AuthMethod.OPEN,
                keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
                CipherMethod.CCMP
            ))
        }
    } else if (authScheme != null || keyManagementAlgorithm != null) {
        capabilities.add(Capability(
            authScheme ? : AuthMethod.OPEN,
            keyManagementAlgorithm ? : KeyManagementAlgorithm.NONE,
            CipherMethod.NONE
        ))
    }

    return capabilities
}

private fun parseTopologyMode(capabilitiesString: String): TopologyMode ? {
    return capabilitiesString
        .splitByBrackets()
        .mapNotNull {
            when {
                it.contains("ESS") - > TopologyMode.ESS
                it.contains("BSS") - > TopologyMode.BSS
                it.contains("IBSS") - > TopologyMode.IBSS
                else - > null
            }
        }
        .firstOrNull()
}

private fun parseWPSAvailable(capabilitiesString: String): Boolean {
    return capabilitiesString
        .splitByBrackets()
        .any {
            it.isWps()
        }
}

private fun String.splitByBrackets(): List < String > {
    val m = Pattern.compile("[(.*?)]").matcher(this)
    val parts = ArrayList < String > ()
    while (m.find()) {
        parts.add(m.group().replace("[", "").replace("]", ""))
    }
    return parts
}

private fun String.isTopology(): Boolean {
    return TopologyMode.values().any {
        this == it.name
    }
}

private fun String.isWps(): Boolean {
    return this == "WPS"
}

8. ๊ฒฐ๊ณผ ๋ณด๊ธฐ

๋„คํŠธ์›Œํฌ๋ฅผ ์Šค์บ”ํ•ด์„œ ๋‚ด๊ฐ€ ์ฐพ์€ ๊ฒƒ์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. Log.d๋ฅผ ํ†ตํ•œ ๊ฐ„๋‹จํ•œ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Capability of Home-Home [WPA2-PSK-CCMP][ESS][WPS]
...
capabilities=[Capability(authScheme=WPA2, keyManagementAlgorithm=PSK, cipherMethod=CCMP)], topologyMode=ESS, availableWps=true

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ ๋„คํŠธ์›Œํฌ์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฌธ์ œ๋Š” ์•„์ง ๊ฒ€ํ† ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ์žฅ์น˜์˜ OS์—์„œ ์ €์žฅ๋œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ฝ์œผ๋ ค๋ฉด ๋ฃจํŠธ ๊ถŒํ•œ์ด ํ•„์š”ํ•˜๊ณ  ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ๋’ค์ ธ wpa_supplicant.conf๋ฅผ ์ฝ์œผ๋ ค๋Š” ์˜์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ์ ๋งŒ ๋ง์”€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์ด ์™ธ๋ถ€์—์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. android.net.wifi.WifiManager.

๊ฐ์‚ฌ ์—๊ณ ๋ฅด ํฌ๋…ธ๋งˆ๋ ˆํ”„ ๊ท€์ค‘ํ•œ ์ถ”๊ฐ€๋ฅผ ์œ„ํ•ด.

์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ๋Œ“๊ธ€๋กœ ์ ์–ด์ฃผ์„ธ์š” :)

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€