2013๋ ํ์ด์ค๋ถ ํด์ปคํค์์ ์์ด๋์ด๊ฐ ๋์๊ณ , 2015๋ ์ ๋์ค์ ์ํ ์คํ ์์ค ํ๋ซํผ์ผ๋ก ์ถ์๋ ๊ฒ์ด ์ด์ ๋ ์ฑ ๊ฐ๋ฐ์ ์์ด ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ํ๋ ์์ํฌ ์ค ํ๋๊ฐ ๋์์ต๋๋ค. React Native๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋กํ๋ฉฐ ๊ฐ๋ฐ์๊ฐ iOS์ Android ์ด์ ์ฒด์ ๋ชจ๋์ ๋ํด ๊ธฐ๋ณธ์ ์ผ๋ก ๋ ๋๋ง๋ ๋ชจ๋ฐ์ผ ์ฑ์ ๋น๋ํ ์ ์๋๋ก ํฉ๋๋ค. ์ฑ๊ณผ ์น ์ฌ์ดํธ์ฉ UI ์ธํฐํ์ด์ค์ ์ปดํฌ๋ํธ๋ฅผ ๋น๋ํ๊ธฐ ์ํ ์คํ ์์ค ํ๋ก ํธ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ React JavaScript(ReactJS)๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ณธ ๊ธ์์๋ ์คํ ์์ค ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ๋ก ๊ตฌ์ถ๋ ์ฑ์ ๋ํ React Native ๋ณด์์ ๋ํด์ ์ค๋ช ํฉ๋๋ค.ย
React Native ๋ณด์
๋ชจ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๊ธฐ๋ฐ ํ๋ ์์ํฌ์ ๋ง์ฐฌ๊ฐ์ง๋ก React Native๋ ๋ณด์ ์ํ์ ์ทจ์ฝํฉ๋๋ค. React Native ๋ณดํธ ๊ด์ ์์์ ๋ถ์์ ํ๋ ์์ํฌ์ ๋ค๋ฅธ ๋ถ๋ถ๊ณผ ์ด๋ค ๊ฐ์ ์ฐ๊ฒฐ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ค์ฝ๋๋ ํด๋ผ์ด์ธํธ๋จ์์ ์์ค ์ฝ๋๋ฅผ ์ผ๋ง๋ ์ง ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์, ๋ณธ์ง์ ์ผ๋ก ํ๋ฐํธ์๋ JS ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ๋๊ฑฐ๋ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๊ฐ ์ฝ๊ฒ ์ ์ถ๋ ์ ์์ต๋๋ค. JS ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ณด์ ๋ฌธ์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํฌ๋ก์ค์ฌ์ดํธ ์คํฌ๋ฆฝํ
(XSS; Cross-site Scripting)
XSS ๊ณต๊ฒฉ์ด๋ผ๊ณ ๋ ํ๋ฉฐ ๊ณต๊ฒฉ์๊ฐ ์น ์ฌ์ดํธ๋ฅผ ์์ฌ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ์์ ์์์ JS ์ฝ๋๋ฅผ ์คํํ๋๋ก ํ ๋ ๋ฐ์ํฉ๋๋ค. XSS ๊ณต๊ฒฉ์๋ ๋ ๊ฐ์ง ์ข ๋ฅ๊ฐ ์์ต๋๋ค. Reflected XSS๋ ์ผ๋ถ ํ ์คํธ ์ ๋ณด๊ฐ ํฌํจ๋ ๋งํฌ๊ฐ ๋ธ๋ผ์ฐ์ ์์์ ์ฝ๋๋ก ์ฒ๋ฆฌ๋ ๋ ๋ฐ์ํฉ๋๋ค. Stored XSS๋ ๊ณต๊ฒฉ์๊ฐ ์๋ฒ ์ก์ธ์ค ๊ถํ์ ์ป๊ณ ํด๋ผ์ด์ธํธ์ ์น ํ์ด์ง ์ ๋ณด๋ฅผ ์์ฑํ ์ ์๋ ์ฝ๋๊ฐ ์๋ฒ์์ ์คํ๋ ๋ ๋ฐ์ํฉ๋๋ค.ย
๋ถ์์ ํ ๋ฌด์์์ฑ๊ณผ ๋งํฌ
์ด๊ฒ์ ๋งํฌ๊ฐ ํด๋ผ์ด์ธํธ๊ฐ ์ ๋ ฅํ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๊ณ , ๊ณต๊ฒฉ์๊ฐ ์๋ JS ์ฝ๋์ ์ ์ฑ ์ฝ๋๋ฅผ ์ถ๊ฐํ ๋ ๋ฐ์ํฉ๋๋ค. ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด ๋ธ๋ผ์ฐ์ ์์ ๊ณต๊ฒฉ์์ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋ฉ๋๋ค.
์๋ฒ์ธก ๋ ๋๋ง ๊ณต๊ฒฉ์์ ์ํด์ ์ ์ด๋๋ โโ์ด๊ธฐ ์ํ
์ด๊ฒ์ ์ฑ์ด ์๋ฒ์ธก์์ ๋ ๋๋ง๋๋ ๊ฒฝ์ฐ์ ๋ฐ์ํฉ๋๋ค. ํ์ด์ง์ ๊ธฐ๋ณธ ๋ฒ์ ์ ์์ฑํ๋ฉด JSON ๋ฌธ์์ด์์ ๋ฌธ์ ๋ณ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. JSON.stringify () ํจ์์ ์ ๊ณต๋ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ํ์ด์ง์์ ๋ณผ ์ ์๋ ๋ฌธ์์ด๋ก ๋ณํ๋๊ธฐ ๋๋ฌธ์ ์ํํ ์ ์์ต๋๋ค.
์์ ์ฝ๋ ์คํ(ACE)
์ด๊ฒ์ ๊ณต๊ฒฉ์๊ฐ ์์ ์ฝ๋ ์คํ ์ต์คํ๋ก์์ด๋ผ๋ ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ์ฌ ๋์ ํ๋ก์ธ์ค์ ์์์ ๋ช ๋ น์ ์คํํ ์ ์์ ๋ ๋ฐ์ํฉ๋๋ค. ์ด๋ ์ ํ์ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ์ ์ฑ์ฝ๋์ ๋ ธ์ถ๋๋ฏ๋ก ๋งค์ฐ ํด๋ก์ธ ์ ์์ต๋๋ค.
Zip ์ฌ๋ฆฝ
์ด ์ํ์ ์ฝ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ณด์์ด ์์๋๊ณ , ๊ณต๊ฒฉ์๊ฐ ๋์ ๋๋ ํ ๋ฆฌ ์ธ๋ถ์์ ์ ์ฑ ์ฝ๋๋ ํ์ผ์ ์์ถ ํด์ ํ ๋ ๋ฐ์ํฉ๋๋ค. ์ด๋ก ์ธํด ๊ณต๊ฒฉ์๋ ์ค์ํ ์์คํ ๋๋ ๊ตฌ์ฑ ํ์ผ์ ๋ฎ์ด์ธ ์๋ ์์ต๋๋ค.
๋ฐ๋ผ์ ์ฑ์ ๋น๋ํ ๋ ์ ์์ ์ธ ์ 3์๋ก๋ถํฐ React Native ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณดํธํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํฉ๋๋ค. React Native์๋ ๋ฏผ๊ฐํ ์ ๋ณด์ ์์ ํ ์ ์ฅ์ ์ง์ํ๋ ๋ด์ฅ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๊ณ ์์ง ์์ง๋ง, Android๋ iOS ํ๋ซํผ ๋ชจ๋์์ ์ฑ ๋ณด์์ ๊ฐํํ๋๋ฐ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์๋ฃจ์ ์ด ์์ต๋๋ค. ์๋์์ ์ด๋ค ์ค ์ผ๋ถ์ ๋ํด ์์ธํ ์ค๋ช ํฉ๋๋ค.
์ฑ๊ณผ ์๋ฒ๊ฐ ์ฐ๊ฒฐ ๋ณด์
React Native์์ ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ํต์ ์ ์คํ ํ๋ซํผ์ด ๊ฐ์ง ๋ณด์ ์ทจ์ฝ์ ๋๋ฌธ์ ๋ฐ๋์ ๋ณด์์ด ํ์ํฉ๋๋ค. ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ํต์ ์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ์น ์๋น์ค๋ HTTP ๊ธฐ๋ฐ REST ์ ๋๋ค. HTTPS ์ฐ๊ฒฐ์์ ๊ฐ์ฅ ์ค์ํ ๋ ๊ฐ์ง๋ ํธ๋ ์ ฐ์ดํน ์ค์ ์๋ฒ์์ ์ ๊ณตํ๋ ์ ํจํ ์ธ์ฆ์์ ์ ์ก ์ค์ ๋ฐ์ดํฐ ์ํธํ์ ์ฌ์ฉ๋๋ ์ํธ์ ๋๋ค. ์ธ์ฆ์๋ ์๋ฒ์ ID๋ฅผ ์ฆ๋ช ํ๋ ์ญํ ์ ํฉ๋๋ค. ํด๋ผ์ด์ธํธ์ ์ ์ฅ๋ ์ ๋ขฐํ ์ ์๋ ์ธ์ฆ ๊ธฐ๊ด(CA)์์ ์๋ช ํ ์ ํจํ ์ธ์ฆ์๋ฅผ ์๋ฒ๊ฐ ์ ๊ณตํ ์ ์๋ค๋ฉด ์ฐ๊ฒฐ์ด ์ค๋จ๋ฉ๋๋ค. ์ด ๋ฉ์ปค๋์ฆ์ ๊ณต๊ฒฉ์๊ฐ ์ฌ์ฉ์ ๋๋ฐ์ด์ค์ ์ ์์ ์ธ ๋ฃจํธ CA ์ธ์ฆ์๋ฅผ ์ค์นํ์ฌ ํด๋ผ์ด์ธํธ๊ฐ ๊ณต๊ฒฉ์๊ฐ ์๋ช ํ CA ์ธ์ฆ์๋ฅผ ์ ๋ขฐํ๋๋ก ์์ด๊ฑฐ๋ ๋๋ฐ์ด์ค์ ์ ์ฅ๋ CA๋ฅผ ์์ ํ ์์์ํค๋ ๋ฐฉ๋ฒ์ผ๋ก ์ ์ฉ๋ ์ ์์ต๋๋ค. ์ฌ์ฉ์ ์๊ฒฉ ์ฆ๋ช ์ ์ธ์ฆ ๋ถ์ผ์น๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์, ๋ณ๋์ ์ฝ๋ ๋ณ์๋ฅผ ๊ฐ์ง ๋ค๋ฅธ ์ฌ์ฉ์์๊ฒ ์์ญ ์์ฑ์ ํ ๋นํด์ผ ํ๋ค๋ ์ ์ ์ ์ํด์ผ ํฉ๋๋ค. ์๋ฒ ์๋ต ๋ฉ์ปค๋์ฆ๊ณผ ์์ญ ์์ฑ ์ฌ์ด์ ์์ ๋ถ์ผ์น ์กฐ์ฐจ๋ ์ฑ์ ๋ณด์์ ์์์ํค๊ณ ๊ถํ์ด ์๋ ์ฌ์ฉ์์๊ฒ ์ก์ธ์ค๋ฅผ ํ์ฉํ ์ ์์ต๋๋ค.ย
React Native์์ SSL ํผ๋(Pinning)
SSL(Secure Sockets Layer)์ ๋คํธ์ํน ์ปดํจํฐ๊ฐ์ ์ธ์ฆ ๋ฐ ์ํธํ๋ ๋งํฌ๋ฅผ ์ค์ ํ๋ ํ๋กํ ์ฝ์ ๋๋ค. TLS(Transport Layer Security) ํ๋กํ ์ฝ์ 1999๋ SSL์ ๋ํ ์ ๋ฐ์ดํธ์์ง๋ง ์ข ์ข โSSLโ ๋๋ โSSL/TLSโ๋ก ํต์นญ๋ฉ๋๋ค. SSL ํผ๋์ SSL ํธ๋ ์ ฐ์ดํน ํ์๋ ํด๋ผ์ด์ธํธ ์ธก์์ ์๋ฒ ์ธ์ฆ์์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋๋ฐ ์ฌ์ฉ๋๋ ๊ธฐ์ ์ ์๋ฏธํฉ๋๋ค. ์ ๋ขฐํ ์ ์๋ ์ธ์ฆ์ ๋ชฉ๋ก์ ๋ฐํ์ ๋์ ์๋ฒ ์ธ์ฆ์์ ๋น๊ตํ ์ ์๋๋ก ํด๋ผ์ด์ธํธ ์ฑ์ ๋ด์ฅ๋ฉ๋๋ค. ์๋ฒ ์ธ์ฆ์๊ฐ ๋ก์ปฌ ์ธ์ฆ์ ๋ชฉ๋ก๊ณผ ์ผ์นํ์ง ์์ผ๋ฉด ์ฐ๊ฒฐ์ด ์ฆ์ ์ค๋จ๋๊ณ ๋ฐ์ดํฐ๊ฐ ์๋ฒ๋ก ์ ์ก๋์ง ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํด๋ผ์ด์ธํธ๊ฐ ์ ๋ขฐํ ์ ์๋ ์๋ฒ์๋ง ์ฐ๊ฒฐ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ณ ์ ๋ ์ธ์ฆ์๊ฐ ๋ง๋ฃ๋๋ฉด ์ดํ ์ธ์ฆ์๋ ๋ฆด๋ฆฌ์ค ์ ์ ํด๋ผ์ด์ธํธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณ ์ ์์ผ์ผ ํฉ๋๋ค. ๋ง์ฝ ์ ๋ฐ์ดํธ๋ ์ธ์ฆ์๊ฐ ๊ณ ์ ๋์ง ์์ผ๋ฉด, ํด๋น ์ธ์ฆ์๋ ํด๋ผ์ด์ธํธ์์ ์ธ์๋์ง ์์ผ๋ฉฐ ์ถ๊ฐ ํต์ ์ด ์ข ๋ฃ๋ฉ๋๋ค. ์ด๋ฅผ โ์ฑ ๋ธ๋ฆญํน(App Bricking)โ์ด๋ผ๊ณ ํฉ๋๋ค. SSL ํผ๋์ ์ผ๋ฐ์ ์ผ๋ก ์ ์ฒด ์ธ์ฆ์๋ฅผ ๊ณ ์ ํ๊ฑฐ๋ ํด์๋ ํค๋ง ๊ณ ์ ํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ํํ ์ ์์ต๋๋ค. ํ์๋ ์ ๋ฐ์ดํธ๋ ์ธ์ฆ์์ ์๋ช ํ๊ณ ๋ธ๋ฆญํน ์ธ์คํด์ค๋ฅผ ๋ฐฉ์งํ๋๋ฐ ๋์ผํ ํค๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ๋ ๋ฐ๋์งํ ์ต์ ์ ๋๋ค.
์ธ์ฆ์ ํผ๋์ Android์์ ์ธ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํ ์ ์์ต๋๋ค.
1. ๋คํธ์ํฌ ๋ณด์ ๊ตฌ์ฑ
์ด๊ฒ์ Android์์ ์ธ์ฆ์๋ฅผ ํผ๋ํ๋ ๊ธฐ๋ณธ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๊ฒ์ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด๋ฉฐ ์ฝ๋ฉ์ด ํ์ํ์ง ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ ์ผํ ๊ฑธ๋ฆผ๋์ Android N ์ด์์์๋ง ์ง์๋๋ค๋ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ์๋ ์ฑ ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ๋ ๋๋ฉ์ธ ๋ฐ ์ฑ์ ํน์ ํ ๋ณด์ ๊ตฌ์ฑ ํ์ผ์ ๋ณด์ ์ค์ ์ ์ปค์คํฐ๋ง์ด์งํ ์ ์์ต๋๋ค. ๊ตฌ์ฑ์ res\xml ๋๋ ํ ๋ฆฌ์ ์์ฑ๋ XML ํ์ผ์ ์ฌ์ฉํฉ๋๋ค. XML ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ธ๋ ์ ์์ต๋๋ค.
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest … >
ย ย <application
ย ย ย ย android:networkSecurityConfig=”@xml/network_security_config”
ย ย ย ย ย … >
ย ย ย ย ย ย ย …
ย ย ย </application>
</manifest>
์ด์ ย <base-config> ๋ฐ<domain-config>ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ๋คํธ์ํฌ ๋ณด์ ํ์ผ์ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
- <base-config>๋ ์ฐ๊ฒฐ์ ์ ์งํ๋ ๋๋ฉ์ธ์ ๊ด๊ณ์์ด ์ ์ฒด ์ฑ์ ์ ์ฉํด์ผ ํ๋ ๊ตฌ์ฑ์ ์ ์ธํฉ๋๋ค.
- <domain-config>๋ ๊ฐ๋ฐ์๊ฐ ์ ํํ ๋๋ฉ์ธ์ ํน์ ํ ๊ท์น์ ๊ตฌ์ฑํฉ๋๋ค.
2. TrustManager
TrustManager๋ ํผ์ด๊ฐ ์ ๊ณตํ ์๊ฒฉ ์ฆ๋ช ์ ์ฑ์์ ํ์ฉํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. javax.net.ssl์ ์ด ๊ธฐ์ ์ ๋ค์ ๋จ๊ณ๋ฅผ ํตํด ์ธ์ฆ์ ํผ๋์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ๊ฐ๊ธ์ ์ด๋ฉด ์ฃผ์ ์ค์ด ์๋ PEM ๋๋ DER ํ์์ ์ธ์ฆ์ ํ์ผ์ ๋๋ ํฐ๋ฆฌ์ ์ถ๊ฐํฉ๋๋ค.
- ์ธ์ฆ์๋ก KeyStore ์ด๊ธฐํํฉ๋๋ค.
val resource_stream = resources.openRawResource(R.raw.cert)
val key_store_type = KeyStore.getDefaultType()
val key_store = KeyStore.getInstance(key_store_type)
key_store.load(resource_stream, null)
- TrustManager ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค.
val trust_manager_algorithm = TrustManagerFactory.getDefaultAlgorithm()
val trust_manager_factory = TrustManagerFactory.getInstance(trust_manager_algorithm)
trust_manager_factory.init(keyStore)
- ๋ง์ง๋ง ๋จ๊ณ๋ TLS ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ SSL ์ปจํ ์คํธ๋ฅผ ๋ง๋๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฐ ๋ค์ TrustManager๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด์ SSL ์ฐ๊ฒฐ์ ์์ฑํฉ๋๋ค.ย
val ssl_context = SSLContext.getInstance(“TLS”)
ssl_context.init(null, trust_manager_factory.trustManagers, null)
val url = URL(“http://www.secureexample.com/“)
val url_connection = url.openConnection() as HttpsURLConnection
url_connection.sslSocketFactory = ssl_context.socketFactory
3. OkHttp ๋ฐ ์ธ์ฆ์ ํผ๋
์ด๊ฒ์ Square์ ์ ๋ช ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ฌ์ฉ์ด ์ฌ์ฐ๋ฉฐ, ๋คํธ์ํน์ ์ํด Retrofit์์ ์ฌ์ฉํฉ๋๋ค. ์์ํ๋ ค๋ฉด OktHtp CertificatePinner ๋น๋์์ ์ธ์ฆ์ ํผ๋ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ , ํด๋น ๋๋ฉ์ธ๊ณผ ์ง๋ฌธ์ ์ฌ๊ธฐ์ ์ถ๊ฐํฉ๋๋ค. ๋ง์ง๋ง ๋จ๊ณ๋ ๋น๋๋ฅผ OkHttp ํด๋ผ์ด์ธํธ์ ์ถ๊ฐํ๋ ๊ฒ์ ๋๋ค.
val certificatePinner = CertificatePinner.Builder()
ย ย ย ย ย ย ย .add(
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย “www.secureexample.com”,
ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย “sha256/7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y=”
ย ย ย ย ย ย ย ).build()
val okHttpClient = OkHttpClient.Builder()
ย ย ย ย ย ย ย .certificatePinner(certificatePinner)
ย ย ย ย ย ย ย .build()
ํ์ฌ ์ง๋ฌธ์ด ๋ง๋ฃ๋๋ ๊ฒฝ์ฐ ์ฌ๋ฌ ๊ฐ์ ์ง๋ฌธ์ ๋น๋์ ์ถ๊ฐํ ์๋ ์์ต๋๋ค. TrustManager ๊ฒฝ์ฐ ์ฒ๋ผ ์ธ์ฆ์ ํ์ผ์ ๋ฆฌ์์ค ํด๋๋ก ๊ฐ์ ธ์ฌ ์๋ ์์ต๋๋ค. ๋ค์ ๋จ๊ณ๋ ํ์ผ์์ ์ง๋ฌธ์ ์ถ์ถํ ํด๋์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค. ์ง๋ฌธ์ gradle ํ์ผ์์ build-config ํ๋๋ก ์ธ๊ธ๋์ด์ผ ํฉ๋๋ค.
react-native-pinch ๋๋ react-native-ssl-pinning๊ณผ ๊ฐ์ React Native ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ๋ค์ดํฐ๋ธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ React Native ์ ํ๋ฆฌ์ผ์ด์ ์์ SSL ํผ๋์ ๊ตฌํํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋ค์ดํฐ๋ธ ํ๋ซํผ์์์ ๊ตฌํ์ Android์ iOS์์ ๋ค๋ฆ ๋๋ค. ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ย openssl s_client -showcerts -servername <domain(i.e. google.com)> -connect <domain(i.e. google.com)>:443 ๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๋๋ฉ์ธ์ ๋ํ ์ธ์ฆ์๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
์ถ๋ ฅ์ ์ฒด์ธ์ ์ ์ฒด ์ธ์ฆ์(์๋จ์ ๋ฆฌํ ์ธ์ฆ์์ ํ๋จ์ ๋ฃจํธ ์ธ์ฆ์)์ ๋๋ค.
iOS ํ๋ซํผ์ ๊ฒฝ์ฐ ๋ด์ฅ ์คํฌ๋ฆฝํธ(get_pin_from_certificate.py)๊ฐ ํฌํจ๋ TrustKit์ด ์ผ๋ฐ์ ์ผ๋ก SSL ํผ๋์ ์ฌ์ฉ๋ฉ๋๋ค. ํ์ผ์ ๋ค์ด๋ก๋ํ๊ณ $python get_pin_from_certificate.py <your .pem file> ๋ช ๋ น์ ์ฌ์ฉํ์ฌ ๊ณต๊ฐํค ํด์๋ฅผ ๊ฒ์ํ์ญ์์ค.
SSL ํผ๋์ ์ํด ์์ฒด ์๋ช ๋ ๋ฆฌํ, ์ค๊ฐ ๋๋ ๋ฃจํธ ์ธ์ฆ์๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. ๋ฆฌํ ์ธ์ฆ์๋ ์ธ์ฆ์๊ฐ ํด๋ผ์ด์ธํธ์ ์ํด์๊ณ ์ฐ๊ฒฐ์ด ์์ ํ๋ค๋ ๊ฒ์ ์์ ํ ๋ณด์ฅํฉ๋๋ค. ์ธ์ฆ์์ ๋ง๋ฃ ์๊ฐ์ด ๋งค์ฐ ์งง๊ธฐ ๋๋ฌธ์ ์๋ฒ์์ ์ฐ๊ฒฐ์ด ๋์ด์ง์ง ์๋๋ก ์ฑ์ ์ ๋ฐ์ดํธ ํด์ผ ํฉ๋๋ค. ๋ฆฌํ ์ธ์ฆ์์ ๊ฒฝ์ฐ ๋ฐฑ์ ํค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ค๊ฐ ์ธ์ฆ์๋ ์ค๊ฐ ์ธ์ฆ ๊ธฐ๊ด์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ ์ฅ์ ์ ๋ฆฌํ ์ธ์ฆ์์ ๋ํ ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์ฑ์์ ์๋์ผ๋ก ์ ๋ฐ์ดํธ๋๋ค๋ ๊ฒ์ ๋๋ค. ๊ทธ๋ฌ๋ ๊ณต๊ธ์๋ฅผ ์ ๋ขฐํ ์ ์๋ ๊ฒฝ์ฐ์๋ง ์ค๊ฐ ์ธ์ฆ์๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋ฃจํธ ์ธ์ฆ์๋ ๋ฃจํธ ์ธ์ฆ ๊ธฐ๊ด์์ ์น์ธํ ๋ชจ๋ ์ค๊ฐ ์ธ์ฆ์์ ์ข ์๋ฉ๋๋ค. ์ด๋ ์ค๊ฐ ์ธ์ฆ์์ ๋ณด์ ์๋ฐ์ผ๋ก ์ธํด ์ฑ์ด ํด์ปค์ ๊ณต๊ฒฉ์ ์ทจ์ฝํด์ง ์ ์์ผ๋ฏ๋ก ์๋์ ์ผ๋ก ์์ ํ์ง ์์ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.ย
React Native ์ ์ฅ์ ๋ณด์
๊ฐ๋ฐ์๋ ์ข ์ข ์ ํ๋ฆฌ์ผ์ด์ ๋ด๋ถ์ ์๊ตฌ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค. React Native๋ Async-storage, sqlite, pouchdb ๋ฐ realm๊ณผ ๊ฐ์ ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ๊ณตํ๊ณ ์์ต๋๋ค.ย
๋ค์์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด์ ๊ณ์ธต์ ์ถ๊ฐ ํ ์ ์๋ ๋ช ๊ฐ์ง ํ๋ฌ๊ทธ์ธ์ ๋๋ค.
- SQLite : ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ ์ค ํ๋์ ๋๋ค. SQLCipher๋ SQLite ์ํธํ๋ฅผ ์ํด ๋๋ฆฌ ์ฌ์ฉ๋๋ ์คํ ์์ค ํ์ฅ ์ปดํฌ๋ํธ์ ๋๋ค. ์ํธ๋ ํค ์์ด๋ ์ก์ธ์ค ํ ์ ์๋ 256๋นํธ AES๋ก ์ํธํ๋ฉ๋๋ค. React Native์๋ SQLCipher๋ฅผ ์ ๊ณตํ๋ย react-native-sqlcipher-2 (ORM ๊ณต๊ธ์๋ก pouchdb ์ ํจ๊ป ์ฌ์ฉ ๊ฐ๋ฅ)์ react-native-sqlcipher-storage (Cordova ๊ตฌํ ๊ธฐ๋ฐ) ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์์ต๋๋ค.
- Realm : SQLite์ ๋นํด ๋ ๋น ๋ฅธ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ด๋ฉฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ํธํ๋ฅผ ์ง์ํฉ๋๋ค. ๋ํ AES256 ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ฉฐ ์ํธํ๋ SHA-2 HMAC ํด์๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์ฆํฉ๋๋ค.
์ด ์ธ์๋ React Native๋ iOS ๋ฐ Android๋ฅผ ์ํด์ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ช ๊ฐ์ง ๊ธฐ๋ณธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์๋์์ ์์ ํ ์ ์ฅ์๋ฅผ ์ ๊ณตํ๋ React Native ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด์ ์ค๋ช ํฉ๋๋ค.
iOS : KeyChain ์๋น์ค
ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ๋ณด๋ฅผ ์์ ํ๊ฒ ์ ์ฅํ๋๋ฐ ๋์์ด ๋๋๋ก Apple์ KeyChain ์๋น์ค๋ผ๋ ๋ณด์ ํ๋ ์์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ์๋น์ค๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ์ KeyChain์ด๋ผ๋ ์ํธํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ ์ฌ์ฉ์ ๋ฐ์ดํฐ ์ฒญํฌ๋ฅผ ์ ์ฅํ ์ ์์ต๋๋ค. KeyChain์ ์ฃผ๋ก ์ํธํ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค(SecKeychain ํด๋์ค)์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฝ์ ๋ ํญ๋ชฉ (SecKeychainItem ํด๋์ค)์ ๋ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๋น๋ฐ๋ฒํธ, ์ธ์ฆ์, ์ ์ฉ ์นด๋ ์ ๋ณด, ํ ํฐ ๋ฑ๊ณผ ๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ์ฌ๊ธฐ์ ์ ์ฅํ ์ ์์ต๋๋ค. react-native-keychain ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ React Native ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ํ KeyChain/KeyStore ์ก์ธ์ค๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํค ์ฒด์ธ์ ๋ค์ ๋ช
๋ น์ ์คํํ์ฌ React-Native-Keychain-Library๋ฅผ ํตํด์ ์ฝ๊ฒ ์ค์นํ ์ ์์ต๋๋ค.
yarn add react-native-keychain
๊ทธ๋ฐ ๋ค์, ๋ค์ ๋ช
๋ น์ ์ฌ์ฉํ์ฌ ์ฝ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ KeyChain์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
react-native link react-native-keychain
MainApplication.java์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ถ๊ฐ๋์๋์ง ํ์ธํ์ฌ ์ฑ๊ณต์ ์ธ ์ฐ๊ฒฐ์ ํ์ธํ ์ ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค์, ๋ค์์ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ค์ ๋น๋ํ ์ ์์ต๋๋ค.
react-native run-ios
react-native run-android
์์ ๋จ๊ณ๋ฅผ ์๋ฃํ๋ฉด react-native-keychain-library๋ฅผ ์ฑ ๋ด์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ย setGenericPassword(username, password, [{ accessControl, accessible, accessGroup, service }]) ๋ ์ฌ์ฉ์ ์ด๋ฆ/์ํธ ์กฐํฉ์ ๋ณด์ ์ ์ฅ์์ ์ ์ฅํ๊ณ ํญ๋ชฉ์ด ์๋ ๊ฒฝ์ฐ ย true ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ํ ์ด ํจ์๋ ๋ฌธ์์ด ๊ฐ๋ง ์ ์ฅํ ์ ์์ต๋๋ค. ๊ฐ์ฒด ๊ฐ์ด ์๋ ์๊ฒฉ ์ฆ๋ช ์ JSON.stringify๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ฅํด์ผ ํฉ๋๋ค.
getGenericPassword([{ authenticationPrompt, service }]) ๋ ๋ณด์ ์ ์ฅ์์์ ์ฌ์ฉ์ ์ด๋ฆ/์ํธ ์กฐํฉ์ ๊ฒ์ํฉ๋๋ค. ์ด ํจ์๋ ํญ๋ชฉ์ด ์์ผ๋ฉดย { username, password }๋ฅผ ๋ฐํํ๊ณ ๊ทธ๋ ์ง ์์ผ๋ฉด false ๋ฅผ ๋ฐํํฉ๋๋ค. ๊ถํ ๊ด๋ จ ์ค๋ฅ๊ฐ ์๋ ๊ฒฝ์ฐ ๊ธฐ๋ฅ์ด ๊ฑฐ๋ถ๋ฉ๋๋ค. setGenericPassword์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด ํจ์๋ ๋ฌธ์์ด๋ง ๊ฒ์ํ ์ ์์ผ๋ฉฐ, ๊ฐ์ฒด ํ์์ ์๊ฒฉ ์ฆ๋ช ์ย JSON.parse๋ฅผ ์ฌ์ฉํ์ฌ ์ก์ธ์ค ํ ์ ์์ต๋๋ค.
์ฌ์ฉ์ ์ด๋ฆ/์ํธ ์กฐํฉ์ resetGenericPasswordํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ณด์ ์ ์ฅ์์์ ์ ๊ฑฐํ๊ฑฐ๋ ์ฌ์ค์ ํ ์ ์์ต๋๋ค.
requestSharedWebCredentials() ํจ์๋ iOS ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ ๊ณต์ ์น ์๊ฒฉ ์ฆ๋ช ์ ์ ํํ ์ ์์ต๋๋ค. ์ฑ๊ณผ ์๋ฒ์ ์ถ๊ฐ ์ค์ ์ด ํ์ํฉ๋๋ค. ์ด ํจ์๋ ์น์ธ๋ ๊ฒฝ์ฐ { server, username, password }๋ฅผ ๋ฐํํ๊ณ ๊ฑฐ๋ถ๋ ๊ฒฝ์ฐย false ๋ฅผ ๋ฐํํฉ๋๋ค. ํ๋ซํผ์ด ๊ธฐ๋ฅ์ ์ง์ํ์ง ์๊ฑฐ๋ ๊ณต์ ์๊ฒฉ ์ฆ๋ช ์ด ์๋ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค.
setSharedWebCredentials(server, username, password) ๋ ๊ณต์ ์น ์๊ฒฉ ์ฆ๋ช ์ ์ค์ ํ๋๋ฐ ์ฌ์ฉ๋๋ฉฐ ํจ์๊ฐ ์น์ธ๋๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค.
setInternetCredentials(server, username, password, [{ accessControl, accessible, accessGroup }]) ํจ์๋ ์ฌ์ฉ์ ์ด๋ฆ ๋ฐ ๋น๋ฐ๋ฒํธ์ ํจ๊ป ์๋ฒ ์ด๋ฆ์ ๋ณด์ ์ ์ฅ์์ ์ ์ฅํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
getInternetCredentials(server, [{ authenticationPrompt }])๋ ๋ณด์ ์ ์ฅ์์์ ์๋ฒ/์ฌ์ฉ์ ์ด๋ฆ/์ํธ๋ฅผ ๊ฒ์ํฉ๋๋ค.
resetInternetCredentials(server) ํจ์๋ ๋ณด์ ์ ์ฅ์์์ ์๋ฒ/์ฌ์ฉ์ ์ด๋ฆ/๋น๋ฐ๋ฒํธ ์กฐํฉ์ ์์ ํ ์ ๊ฑฐํ๊ณ ์ฌ์ค์ ํฉ๋๋ค.
canImplyAuthentication([{ authenticationType }]) ํจ์๋ ์ฌ์ฉ์๊ฐ ์ ํํ ์ค์ ์ผ๋ก ๋๋ฐ์ด์ค์์ ์ธ์ฆ ์ ์ฑ ์ด ์ง์๋๋์ง ํ์ธํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. setter ํจ์์์ ์ฌ์ฉํ ์ ์๋ย accessControlํจ์์ ํจ๊ป ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ด ํจ์๋ ์น์ธ๋๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค.ย
getSupportedBiometryType() ์ ๋๋ฐ์ด์ค์์ ์ฌ์ฉํ ์ ์๋ ํ๋์จ์ด ์์ฒด ์ธ์ ์ง์์ ๋ํด ์๋ ค์ค๋๋ค. ์ง์๋๋ ๊ฒฝ์ฐย Keychain.BIOMETRY_TYPE ์ด๊ฑฐํ์ผ๋ก ํ์ธ๋๊ฑฐ๋ย null์ด ํ์๋ฉ๋๋ค. Android ๋ฐ iOS ๊ธฐ๊ธฐ ๋ชจ๋์์ ์๋ํฉ๋๋ค. ๋ฐํ๋๋ ์์ฒด ์ธ์ ์ ํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
TOUCH_ID (iOS only)
FACE_ID (iOS only)
FINGERPRINT (Android only)
API๋ ๋ํ KeyChain์ ์ก์ธ์ค ํ ์ ์๋ ์์ ์ ๊ฒฐ์ ํ๋ Keychain.ACCESSIBLE ์ด๊ฑฐํ์ ์ ๊ณตํฉ๋๋ค. ์ฌ์ฉ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ ๋ฐ ์ ๋ณด์ ๋ฏผ๊ฐ๋์ ๋ฐ๋ผ ์ต์ ์ ์ ํํ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋ช ๊ฐ์ง ์ต์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
WHEN_UNLOCKED: ๋๋ฐ์ด์ค๊ฐ ์ ๊ธ ํด์ ๋ ๊ฒฝ์ฐ์๋ง KeyChain์ ๋ฐ์ดํฐ๋ฅผ ์ก์ธ์ค ํ ์ ์์ต๋๋ค.ย
ALWAYS: KeyChain์ ํญ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. ํ์ง๋ง ์์ ํ์ง ์ ์ํด์ผ ํฉ๋๋ค.ย
WHEN_UNLOCKED_THIS_DEVICE_ONLY: KeyChain์ ํน์ ๋๋ฐ์ด์ค์์ ์ ๊ธ์ด ํด์ ๋ ๊ฒฝ์ฐ์๋ง ์ก์ธ์ค ํ ์ ์์ต๋๋ค. ์ด ์ด๊ฑฐํ์ ์ํ ํญ๋ชฉ์ ๋ค๋ฅธ ๋๋ฐ์ด์ค๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ ์ ์์ต๋๋ค.
ALWAYS_THIS_DEVICE_ONLY: KeyChain์ ๋๋ฐ์ด์ค์ ์ ๊ธ ํด์ ์ฌ๋ถ์ ๊ด๊ณ์์ด ํน์ ๋๋ฐ์ด์ค์ ์๋ ๊ฒฝ์ฐ์๋ง ์ก์ธ์ค ํ ์ ์์ต๋๋ค.
AFTER_FIRST_UNLOCK: ๋๋ฐ์ด์ค๋ฅผ ๋ค์ ์์ํ ํ ์ ๊ธ์ ํด์ ํ์ง ์์ผ๋ฉด KeyChain์ ๋ฐ์ดํฐ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค.
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY: ํน์ ๋๋ฐ์ด์ค์์ ์ฒ์ ์ ๊ธ์ ํด์ ํ ํ์ ๋ง โโKeyChain์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. ๋๋ฐ์ด์ค๊ฐ ์ ๊ธ ํด์ ๋์ง ์์ผ๋ฉด ๋ค์ ์์ํ ํ์๋ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. ์ด๊ฒ์ด ์๋ง๋ ๊ฐ์ฅ ์์ ํ ์ต์ ์ผ ๊ฒ์ ๋๋ค. ์ด ์์ฑ์ด ์๋ ํญ๋ชฉ๋ ๋ค๋ฅธ ๋๋ฐ์ด์ค๋ก ๋ง์ด๊ทธ๋ ์ด์ ๋์ง ์์ต๋๋ค.
WHEN_PASSCODE_SET_THIS_DEVICE_ONLY: KeyChain์ ๋ฐ์ดํฐ๋ ๋๋ฐ์ด์ค๊ฐ ์ ๊ธ ํด์ ๋ ๊ฒฝ์ฐ์๋ง ์ก์ธ์ค ํ ์ ์์ต๋๋ค. ์ด ์ต์ ์ ๋๋ฐ์ด์ค์ ์ํธ๊ฐ ์ค์ ๋ ๊ฒฝ์ฐ์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
Keychain.ACCESS_CONTROL enum์ด๊ฑฐํ์ KeyChain์ ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์๋ ์ฌ๋์ ๊ฒฐ์ ํ๋ ์ต์ ์ ์ ๊ณตํฉ๋๋ค. ๋ค์ ์ต์ ์ ์ฌ์ฉํ์ฌ KeyChain ํญ๋ชฉ์ ๋ํ ์ ๊ทผ์ ์ ์ด ํ ์ ์์ต๋๋ค.
USER_PRESENCE | Touch ID ๋๋ ๋น๋ฐ๋ฒํธ๋ก ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. |
BIOMETRY_ANY | ์ค์ง ๋ฑ๋ก๋ ๋ชจ๋ ์๊ฐ๋ฝ์ Touch ID ๋ง์ผ๋ก ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. |
BIOMETRY_CURRENT_SET | ํ์ฌ ๋ฑ๋ก๋ ์๊ฐ๋ฝ์ ๋ํด์๋ง Touch ID๋ก ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. |
DEVICE_PASSCODE | ๋น๋ฐ๋ฒํธ๋ก ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. |
APPLICATION_PASSWORD | ๋ฐ์ดํฐ ์ํธํ ํค ์์ฑ์ ์ํด ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ณต ๋น๋ฐ๋ฒํธ๋ฅผ ์ฌ์ฉํ๋ ์ ์ฝ์ด ์์ต๋๋ค. |
BIOMETRY_ANY_OR_DEVICE_PASSCODE | ๋ฑ๋ก๋ ๋ชจ๋ ์๊ฐ๋ฝ์ Touch ID ๋๋ ๋น๋ฐ๋ฒํธ๋ฅผ ์ฌ์ฉํ์ฌ ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค. |
BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE | ํ์ฌ ๋ฑ๋ก๋ ์๊ฐ๋ฝ์ Touch ID ๋๋ ๋น๋ฐ๋ฒํธ์ ๋ํด์๋ง ํญ๋ชฉ์ ์ก์ธ์ค ํ ์ ์๋ ์ ์ฝ์ด ์์ต๋๋ค. |
Android: ์์ ํ SharedPreferences
Android์์๋ ํค-๊ฐ ๋ฐ์ดํฐ ์ ์ฅ์์ ํด๋นํ๋ ๊ฒ์ย SharedPreferences๋ผ๊ณ ๋ช
๋ช
ํฉ๋๋ค. ์๊ตฌ์ ์ธย ํค-๊ฐ ๊ธฐ๋ณธ ๋ฐ์ดํฐ ์ ํ์ ์ ์ฅํ๊ณ ๊ฒ์ํ ์ ์๋ ํ๋ ์์ํฌ๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ย SharedPreferences ๋ ๋ฐ์ดํฐ๋ฅผ ์ผ๋ฐ ํ
์คํธ๋ก ์ ์ฅํ๋ฏ๋ก ์ ์ฌ์ ์ธ ์ํ์ผ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ณดํธํ๋ ค๋ฉด ์ค์ํ ๋ฐ์ดํฐ๋ฅผ ์ํธํํด์ผ ํฉ๋๋ค. Android Keystore๋ฅผ ์ฌ์ฉํ์ฌ SharedPreferences ์ ๋ํ ์์ฒด ์ํธํ ๋ํผ๋ฅผ ์์ฑํ ์ ์์ง๋ง, ๋ ์ฝ๊ณ ์์ ํ ์ต์
์ ๋ณด๋ค ๊ฐ๋จํ๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด UI๋ฅผ ์ ๊ณตํ๋ AndroidX ๋ณด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํธํ๋ ๊ณต์ ํ๊ฒฝ ์ค์ ์ ์ ์ฅํ๋ ๊ฒ์
๋๋ค. AndroidX ๋ณด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์์ํ๊ธฐ ์ํ ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ๋ชจ๋ ์์ค build.gradle ํ์ผ์ ์ข
์์ฑ implementation”androidx.security:security-crypto:1.0.0-alpha03″ ์ ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค. ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ฌ ์ํ ๋จ๊ณ์ ์์ผ๋ฏ๋ก API์ ์ผ๋ถ๊ฐ ํฅํ ๋ฒ์ ์์ ๋ณ๊ฒฝ๋๊ฑฐ๋ ์ ๊ฑฐ๋ ์ ์์์ ์ผ๋์ ๋์ด์ผ ํฉ๋๋ค. ์ข
์์ฑ์ ์ถ๊ฐํ ํ ์ํธํ ๋ง์คํฐ ํค๋ฅผ ์์ฑํ์ฌ Android Keystore์ ์ ์ฅํด์ผ ํฉ๋๋ค.
EncryptedSharedPreferences ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์์น์ ๋ค์ ์ฝ๋๋ฅผ ๋ฐฐ์นํ๋ฉด ์ฝ๊ฒ ์ํํ ์ ์์ต๋๋ค.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec).
๊ธฐ๋ณธ ์ฌ์์ธ AES256_GCM_SPEC์ด ๋ง์คํฐ ํค๋ฅผ ์์ฑํ๊ธฐ ์ํด ์ ๊ณต๋ฉ๋๋ค. ์ด ์ฌ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ง๋ง ํค ์์ฑ์ ๋ํ ์ถ๊ฐ ์ ์ด๊ฐ ํ์ํ ๊ฒฝ์ฐ KeyGenParameterSpec์ ์ ๊ณตํ๋ ์ต์ ๋ ์์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก SharedPreferencesย ๋ฅผ ๊ฐ์ธ๊ณ ์ํธํ๋ฅผ ์ฒ๋ฆฌํ๋ EncryptedSharedPreferences ์ธ์คํด์ค๊ฐ ํ์ํฉ๋๋ค. SharedPreferences์ ์ธ์คํด์ค๋ย Context#getSharedPreferencesย ๋๋ย Activity#getPreferences ์์ ์ง์ ๊ฐ์ ธ์ฌ ์ ์์ง๋งย EncryptedSharedPreferences์ ์์ฒด ์ธ์คํด์ค๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
๋ค์ ์์ ๋ฅผ ์ฐธ๊ณ ํ์ญ์์ค.
val sharedPreferences = EncryptedSharedPreferences.create(
ย ย ย “shared_preferences_filename”,
ย ย ย masterKeyAlias,
ย ย ย context,
ย ย ย EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
ย ย ย EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
SharedPreferencesํ์ผ๊ณผ ์ด์ ์ ์์ฑ๋ masterKeyAlias ๊ทธ๋ฆฌ๊ณ ย Context์ ์ด๋ฆ์ ์ ๋ฌํด์ผ ํฉ๋๋ค. ๋ง์ง๋ง ๋ ์ธ์๋ ๊ฐ๊ฐ ํค์ ๊ฐ์ ์ํธํํฉ๋๋ค. ย EncryptedSharedPreferences ์ธ์คํด์ค๋ย SharedPreferences ์ ๋๊ฐ์ด ์ฌ์ฉํ์ฌ ๊ฐ์ ์ฝ์ ์ ์์ต๋๋ค.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
val sharedPreferences = EncryptedSharedPreferences.create(
ย ย ย “shared_preferences_filename”,
ย ย ย masterKeyAlias,
ย ย ย context,
ย ย ย EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
ย ย ย EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
// storing a value
sharedPreferences
ย ย ย .edit()
ย ย .putString(“some_key”, “some_data”)
ย ย ย .apply()
// reading a value
sharedPreferences.getString(“some_key”, “some_default_value”) // -> “some_data”
Android Keystore
๊ฐ๋ฐ์๋ Android Keystore๋ฅผ ์ฌ์ฉํ์ฌ ์ํธํ ํค๋ฅผ ๋๋ฐ์ด์ค์์ ์ถ์ถ๋์ง ์๋๋ก ๋ณดํธํ ์ ์์ต๋๋ค. ๋ํ ํค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ์ฌ์ฉ์ ์ธ์ฆ์ ์์ฒญํ๊ฑฐ๋ ํน์ ์ํธํ ๋ชจ๋์์๋ง ํค ์ฌ์ฉ์ ์ ํํ๋ ๋ฑ์ ํค ์ฌ์ฉ ๋ฐฉ๋ฒ๊ณผ ์๊ธฐ๋ฅผ ์ ์ดํ๋ โโ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. Android Keystore์ ํค๋ฅผ ๋ณดํธํ๊ธฐ ์ํด ๋ค์์ ๋ณด์ ์กฐ์น๊ฐ ์ฌ์ฉ๋ฉ๋๋ค.
- ํค ์๋ฃ๋ ์ ํ๋ฆฌ์ผ์ด์ ํ๋ก์ธ์ค์ ๋ค์ด ๊ฐ์ง ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ฑ์ ํ๋ก์ธ์ค๊ฐ ์์๋ ๊ฒฝ์ฐ์๋ ํด์ปค๊ฐ ํค ์๋ฃ๋ฅผ ์ถ์ถํ ์ ์๊ฒ ๋ฉ๋๋ค.
- ํค ์๋ฃ๋ ์ฅ์น์ TEE(Trusted Execution Environment) ๋๋ SE(Secure Element)์ ๊ฐ์ ๋ณด์ ํ๋์จ์ด์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด ๋ณด์ ํ๋์จ์ด ์ธ๋ถ๋ก ํค ์๋ฃ๊ฐ ๋ ธ์ถ๋์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ๊ณต๊ฒฉ์๊ฐ Keystore์ ํค๋ฅผ ์ฌ์ฉํ ์ ์๋๋ผ๋ ๋๋ฐ์ด์ค์์ ์ถ์ถํ ์ ์์ต๋๋ค. ์ด ๊ธฐ๋ฅ์ ํ์ธํ๋ ค๋ฉด ํค์ ๋ํ KeyInfo๋ฅผ ์ป๊ณ ย KeyInfo.isInsideSecurityHardware()์ ๋ฐํ ๊ฐ์ ์ฐพ์ผ์ญ์์ค.
Android ๋๋ฐ์ด์ค์์ ํค์ ๋ฌด๋จ ์ฌ์ฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฑ์ ํค๋ฅผ ์์ฑํ๊ฑฐ๋ ๊ฐ์ ธ์ค๋ ๋์ ์น์ธ๋ ์ฌ์ฉ์ ์ง์ ํ ์ ์์ต๋๋ค. ํค๋ฅผ ์์ฑํ๊ฑฐ๋ ๊ฐ์ ธ์จ ํ์๋ ๊ถํ์ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. Android Keystore์์ ์ง์๋๋ ํค ์ฌ์ฉ ์น์ธ์ ๋ค์๊ณผ ๊ฐ์ด ๋ถ๋ฅํ ์ ์์ต๋๋ค.
- ์ํธํ : ์ธ์ฆ๋ ํค ์๊ณ ๋ฆฌ์ฆ, ๋ธ๋ก ๋ชจ๋, ํจ๋ฉ ์ฒด๊ณ, ์์ ๋๋ ๋ชฉ์ (์ํธํ, ๋ณตํธํ, ์๋ช , ํ์ธ) ๋ฐ ํค๋ฅผ ์ฌ์ฉํ ์ ์๋ ๋ค์ด์ ์คํธ
- ์์ ์ ํจ์ฑ ๊ฐ๊ฒฉ : ํค ์ฌ์ฉ ๊ถํ์ด ๋ถ์ฌ๋ ์๊ฐ ๊ฐ๊ฒฉ์ ์ง์ ํฉ๋๋ค.
- ์ฌ์ฉ์ ์ธ์ฆ : ์ฌ์ฉ์๋ ํค๋ฅผ ์ฌ์ฉํ ์ ์์ ๋งํผ ์ต๊ทผ์ ์ธ์ฆ์ ๋ฐ์์ผ ํฉ๋๋ค.
Android OS์์ ์ฑ์ ์ค์นํ๋ ค๋ฉด ์๋ช ์ด ๋์ด ์์ด์ผ ํฉ๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณด์ ์ธ์ฆ์์ฉ ์คํ ๋ฆฌ์ง ์์คํ ์ธ Keystore๋ฅผ ์์ฑํ์ฌ ์ํํ ์ ์์ต๋๋ค. ๊ตฌ๊ธ ํ๋ ์ด ์คํ ์ด์ ๊ฐ์ ๋ง์ผํ๋ ์ด์ค์ ์ฑ์ ๋ฐฐํฌํ๊ธฐ ์ ์ ๊ณต๊ฐํค ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ์ฌ APK์ ์๋ช ํด์ผ ํฉ๋๋ค. APKย ์๋ช ์ ํตํด์ ์ดํ ๋์ผํ ์ฑ์ ๋ํ ์ ๋ฐ์ดํธ๊ฐ ์ ์์ ์ธ ์ 3์๊ฐ ์๋ ๊ฐ๋ฐ์์ ์ํด ์ํ๋จ์ ๋ณด์ฅํ ์ ์์ต๋๋ค. ๋์ผํ ์ฑ์ด ํฅํ ๋ค๋ฅธ ํค๋ก ์๋ช ๋ ๊ฒฝ์ฐ์ ์ฑ์ ๋ฐฐํฌํ ์ ์๊ธฐ ๋๋ฌธ์, ๋ฐฐํฌ์ ์ ์ฑ์ ์๋ช ์ ๊ณ ๋ คํด์ผ ํฉ๋๋ค. ์ฑ์ ์๋ช ์ด ๊ฒฐ์ ๋๋ฉด keytool ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ Keystore๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.keytool์ Java JDK ์ค์น ํ์ ํ์ธํ ์ ์์ต๋๋ค. keytool ์๋ ์ฌ๋ฌ ๋ช ๋ น์ด ์์ผ๋ฉฐ Android ์ฑ์์ ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋ช ๋ น์ -genkeypair์ด๋ฉฐ ์ถ์ฝํ์ -genkey์ ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ -genkey
์ต์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
-alias | ย ย ย ย ย ย ย ํค์ ๋ณ์นญ ์ด๋ฆ |
-keyalg | ย ย ย ย ย ย ย ํค์์ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋๋ ์๊ณ ๋ฆฌ์ฆ |
-keysize | ย ย ย ย ย ย ย ํค์ ํฌ๊ธฐ(๋นํธ) |
-validity | ย ย ย ย ย ย ย ํค์ ์ ํจ ๊ธฐ๊ฐ(์ผ) |
์๋ฅผ ๋ค์ด, keytool -genkey -v -keystore release.keystore -alias example -keyalg RSA -keysize 2048 -validity 12000 ๋ช ๋ น์ ย release.keystore ์ด๋ผ๋ ๋ณ์นญ ์ด๋ฆ๊ณผ 12,000์ผ์ ์ ํจ ๊ธฐ๊ฐ์ RSA-2048 ๊ณต๊ฐ/๊ฐ์ธํค ์์ด ์๋ release.keystore๋ผ๋ Keystore ํ์ผ์ ์์ฑํฉ๋๋ค. APK์ ์๋ช ํ๋ ค๋ฉด Keystore์ ํค ๋ชจ๋์ ๋ํ ๊ฐ๋ ฅํ ๋น๋ฐ๋ฒํธ๊ฐ ํ์ํฉ๋๋ค. APK๋ ๋ค์ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์๋ช ํ ์ ์์ต๋๋ค.
- Gradle๋ก ์๋ช
gradle์์ ํ๋ก์ ํธ๋ฅผ ๋น๋ํ๊ธฐ ์ํด ๊ฐ๋ฐ์๋ android.signingConfig๋ฅผ ๋ง๋ ๋ค์ ํ๋ ์ด์์ android.buildTypes๊ณผ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. gradle ๋น๋ ์คํฌ๋ฆฝํธ์ ํค ์ ์ฅ์ ์ด๋ฆ๊ณผ ๋ณ์นญ์ ์ ๋ ฅํ๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
android {
ย ย ย ย signingConfigs {
ย ย ย ย ย ย ย ย release {
ย ย ย ย ย ย ย ย ย ย ย ย storeFile ‘config.keystore‘
ย ย ย ย ย ย ย ย ย ย ย ย storePassword ‘storePassword‘
ย ย ย ย ย ย ย ย ย ย ย ย keyAlias ‘example‘
ย ย ย ย ย ย ย ย ย ย ย ย keyPassword ‘keyPassword‘
ย ย ย ย ย ย ย ย }
ย ย ย ย }
ย ย ย ย buildTypes {
ย ย ย ย ย ย ย ย release {
ย ย ย ย ย ย ย ย ย ย ย ย signingConfig signingConfigs.release
ย ย ย ย ย ย ย ย }
ย ย ย ย }
ย ย }
- ์๋์ผ๋ก ์๋ช
APK์ ์๋์ผ๋ก ์๋ช ํ๋ ค๋ฉด build-tools ๋ฒ์ 24.0.3 ์ด์์ ๊ฒฝ์ฐ {ANDROID_SDK_DIRECTORY}/build-tools/{BUILD_TOOLS_VERSION}/apksigner ๊ฒฝ๋ก์ ์์นํย apksigner ๋ฅผ ์ฌ์ฉํ์ธ์. ์ด ๋๊ตฌ๋ ๊ณต๊ฐํค ์ธ์ฆ์๋ฅผ ์์ฑํ๊ธฐ ์ํด Keystore์ ์ ์ฅ๋ ๊ณต๊ฐ/๊ฐ์ธํค ์์ ์ฌ์ฉํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ๊ฐ์ธํค๊ฐ ์ ์ผํ ๋ฐฉ์์ผ๋ก ์ฐ๊ฒฐ๋ APK์ ํด๋น ์ธ์ฆ์๋ฅผ ์ฒจ๋ถํฉ๋๋ค. ์ดํ ์ฑ์ ์์ถ๋์ง ์์ ๋ฐ์ดํฐ๊ฐ ์์ธก ๊ฐ๋ฅํ ์คํ์ ์์ ์์๋๋๋ก APK๋ฅผย zipalignํฉ๋๋ค. ๋ฌผ๋ก ๊ตฌ๊ธ ํ๋ ์ด ์คํ ์ด์๋ย zipalign๋ APK๋ฅผ ํ์๋ก ํฉ๋๋ค.ย
zipalign -v -p 4 app-flavor-buildtype-unsigned.apk app-flavor-buildtype-unsigned-aligned.apk
- APK๊ฐ ์์ถ๋ ํ apksigner๋ฅผ ์ฌ์ฉํ์ฌ ์๋ช ํฉ๋๋ค.
apksigner sign –ks release.keystore –out app-flavor-buildtype.apk app-flavor-buildtype-unsigned-aligned.apk
- ๊ทธ๋ฐ ๋ค์ ๋ช ๋ น์ค์์ Keystore์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ๋ผ๋ ๋ฉ์์ง๊ฐ ํ์๋ฉ๋๋ค. Keystore ๋ฐ ํค์ ๋น๋ฐ๋ฒํธ๋ ๋ ๋ฆฝ์ ์ผ๋ก ์ ๋ ฅํด์ผ ํฉ๋๋ค. –ks-pass ๋ฐ –key-pass ์ต์ ์ ์ฌ์ฉํ์ฌ ๊ฐ๋ณ์ ์ผ๋ก ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ๋ผ๋ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์์ต๋๋ค. ๊ฐ ์ต์ ์ ๋ฐ๋ผ stdin์ ํตํด์ ๋ช ๋ น์ค๋ก๋ถํฐ ๋น๋ฐ๋ฒํธ๋ฅผ ์บก์ฒํฉ๋๋ค.
apksigner sign –ks example.keystore –ks-pass stdin –key-pass stdin –out app-signed.apk app.apk
React Native API ๋ณด์ ๋ฌธ์ ์กฐ์ฌ
API๋ ์ฃผ๋ก JSON ํ์์ ์ฌ์ฉํ๋ฉฐ, ํน์ ์๋ํฌ์ธํธ๊ฐ ์๋ ๋ฐ์ดํฐ ์ธํธ์ ๋๋ค. API์์ ๋ฐ์ดํฐ์ ์ก์ธ์คํ๋ค๋ ๊ฒ์ API ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ์๋ํฌ์ธํธ์ ์ก์ธ์คํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. React API๋ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ๋ค๋ฅธ ํ๋ซํผ ๋ฐ ์๋น์ค ๊ฐ์ ํต์ ์ ์ค์ ํ๋๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ํ ๋ค๋ฅธ ๋๋ฐ์ด์ค๋ ์ฑ์ด ์ค์น๋ ํน์ ๋๋ฐ์ด์ค๋ฅผ ์ ์ดํ ์ ์๋ ์ต์ ๋ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ API๋ ์ธ์ฆ์ด ์ ์ ํ์ง ์๊ฑฐ๋ ๋น์ฆ๋์ค ๋ก์ง์ ๊ฒฐํจ์ด ์๋ ๊ฒฝ์ฐ, ์ฑ์ด ๋ณด์ ์ํ ๋๋ MITM(man-in-the-middle) ๊ณต๊ฒฉ์ ์ทจ์ฝํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. XSS ๋ฐ SQL ์ธ์ ์ (SQLi) ๊ณต๊ฒฉ๋ ๊ฐ๋ฅํฉ๋๋ค. React Native์์ API๋ ๋ด๋ถ์ ์ผ๋ก ํ์ํ ๋ช ๋ น์ ์คํํ๊ธฐ ์ํด ์ ๋ณด๋ฅผ ์๋์ผ๋ก ๋ฌธ์ํ ํฉ๋๋ค.
๋ค์๊ณผ ๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก API ๋ณด์ ๊ด๋ จ ์ฅ์ ๋ฅผ ์ค์ด๊ฑฐ๋ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
- ๊ฐ๊ฐ์ API ์คํค๋ง๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ API ํธ์ถ ๋ช ๋ น์ ์ ํจ์ฑ ๊ฒ์ฌ
- ์ ์ฑ์ฝ๋ ์ธ์ ์ ์ด๋ ๋ณด์ ๊ณต๊ฒฉ์ ๋ฐฉ์งํ๊ธฐ ์ํ ์คํค๋ง์ ์ฃผ๊ธฐ์ ์ด๊ณ ์๊ธฐ ์ ์ ํ ๊ฒ์ฆ
- SSL/TLS ํผ๋์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ํจ์ ๋ณด์ฅ
DDoS ๊ณต๊ฒฉ์ ๋ํ React Native ๋ณด์
DDoS(๋ถ์ฐ ์๋น์ค ๊ฑฐ๋ถ)๋ ๊ถํ์ด ์๋ ์ฌ์ฉ์๊ฐ ํน์ ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค์ ์ค์ ์ฌ์ฉ์๊ฐ ์ก์ธ์คํ ์ ์๋๋ก ๋ง๋๋ ์ผ์ข ์ ์ ์ฑ ๊ณต๊ฒฉ์ ๋๋ค. ์ด ์ทจ์ฝ์ ์ ์ผ๋ฐ์ ์ผ๋ก ์๋น์ค์ IP๊ฐ ์ ๋๋ก ๋ง์คํน๋์ง ์์๊ฑฐ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ถฉ๋ถํ ์์ ํ์ง ์์ ๊ฒฝ์ฐ ๋ฐ์ํฉ๋๋ค. ์ด๋ฌํ ๊ณต๊ฒฉ์ ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ์ ํต์ ์ ์ค๋จ์์ผ ์ฑ์ ์จ๋ผ์ธ ์๋น์ค์ ์ฐจ์ง์ ๋น๊ฒ ํฉ๋๋ค. ๋ํ DDoS ๊ณต๊ฒฉ์ด ๊ธฐ์กด ์๋น์ค๋ฅผ ์ค๋จ์ํค๋ ๋์ ์ ์์ ์ธ ํธ๋ํฝ์ผ๋ก React ํ๋ก์ ํธ๋ฅผ ํ๋ฌ๋ฉ์ํฌ ์ ์๋ค๋ ๊ฒ๋ ํ์ธ๋์์ต๋๋ค. DDoS๋ก ์ธํด ์ผ๋ฐ์ ์ผ๋ก ๋ฐ์ํ๋ ๋ณด์ ๊ณต๊ฒฉ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- UDP ํ๋ฌ๋ฉ โ ํธ์คํธ ์๋น์ค์ ์ก์ธ์ค ํ ์ ์๊ฒ๋ฉ๋๋ค.
- ICMP ํ๋ฌ๋ฉ โ React ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋นํ ๋๋ฆฌ๊ฒ ๋ง๋ญ๋๋ค.
- SYN ํ๋ฌ๋ฉ โ ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค๋ฅผ ์ฝ๊ฒ ๊ณต๊ฒฉํ ์ ์๊ฒ ํฉ๋๋ค.ย
- Ping of Death(POD) โ ๋ฉ๋ชจ๋ฆฌ ๋ฒํผ ์ค๋ฒํ๋ก์ฐ ๋ฐ์์ํต๋๋ค.
- HTTP ํ๋ฌ๋ฉ โ ๊ฒฐ๊ตญ ์ ํ๋ฆฌ์ผ์ด์ ์๋น์ค์ ์์ ํ ์ข ๋ฃ๋ฅผ ์ผ๊ธฐํ๋ ์จ๋ผ์ธ ์๋น์ค์ ์ค๋จ์ ์ด๋ํฉ๋๋ค.
๋ค์์ DDoS ๊ณต๊ฒฉ์ ์ฒ๋ฆฌํ ์ ์๋ ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ ์ ๋๋ค.
- DDoS ์ํ์ ์๋ณํ๊ธฐ ์ํด ๊ฐ๋ฐ ๋ฐ ๊ทธ ์ดํ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํฌ๋ฌ๋น
- ์ ์์ ์ธ ์ฌ์ฉ์๊ฐ ํ๋ก๊ทธ๋จ ์ฝ๋์ ์ก์ธ์คํ์ง ๋ชปํ๋๋ก ๋ฐฉ๋ฌธ์ ์๋ณ ๋ฉ์ปค๋์ฆ ์ค์น
- ์๋ฒ์์ ํธ์ถํ๊ณ ํด๋ผ์ด์ธํธ ์ธก์์๋ ํธ์ถํ์ง ์์
- CAPTCHA ๋๋ JS ํ ์คํธ์ ๋์์ผ๋ก ์น-์ฑ ๊ณ์ธต ๋ณด์
- ๋์ผํ ์์ค์์ IP์ ๋ํ ์์ฒญ ์์ ์๋ ์ ํ
์ฝ๋ ๋๋
ํ
์ฝ๋ ๋๋ ํ ๋๋ ์ต์ํ๋ ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ์ ๋๋ค. ์ฝ์ ์ ์๋ ์ฝ๋๋ฅผ Uglify์ ๊ฐ์ ์ํํธ์จ์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋์ด ์ก์์ผ๋ก ์ฝ์ ์ ์๊ฒ ๋ง๋ญ๋๋ค. React Native์ Java ์ฝ๋๋ ๋๋ ํ๋์ง ์๋ ํ ์ฝ์ ์ ์๋ DEX ํ์ผ๋ก ์ ์ฅ๋ฉ๋๋ค.
React Native์๋ react-native-obfuscating-transformer๋ก ์๋ ค์ง ๋๋ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ด์ฅ๋์ด ์์ด ์ฌ์ฉ์๊ฐ JavaScript ์ฝ๋์ ๋ชจ๋ ๊ธฐ๋ณธ ์ฝ๋์ ๋ํด ๋๋ ํ๋ฅผ ๊ตฌํํ ์ ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ gradle ํ์ผ์์ ๋๋ ํ๋ฅผ ํ์ฑํํ๋ ๊ฒ์ ๋๋ค. buildTypes ์น์ ๋ด์์ย [app_name]/android/app/build.gradle๋ก ์ด๋ํ์ฌ ์๋ ์ฝ๋๋ฅผ ์ ์ฉํ ์ ์์ต๋๋ค.
android {
ย ย ย ย // … other config
ย ย ย ย buildTypes {
ย ย ย ย ย ย ย ย release {
ย ย ย ย ย ย ย ย ย ย ย ย debuggable false
ย ย ย ย ย ย ย ย ย ย ย ย shrinkResources true
ย ย ย ย ย ย ย ย ย ย ย ย zipAlignEnabled true
ย ย ย ย ย ย ย ย ย ย ย ย minifyEnabled true
ย ย ย ย ย ย ย ย ย ย ย ย useProguard true
ย ย ย ย ย ย ย ย ย ย ย ย setProguardFiles([getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’])
ย ย ย ย ย ย ย ย }
ย ย ย ย }
ย ย ย ย // … other config
}
minifyEnabled ๋ฐ useProguard๋ ์ฝ๋์ ์ต์ํ ๋ฐ ๋๋ ํ๋ฅผ ํ์ฑํํ๋ ๋ฐ๋ฉด setProguardFiles ์ง์๋ฌธ์ proguard ๊ตฌ์ฑ์ ์์น๋ฅผ ๋ํ๋ ๋๋ค. Proguard๋ ์ฝ๋๋ฅผ ๋ณดํธํ๋ ๋์์ ๋ถํ์ํ ๋ถ๋ถ์ ์ ๊ฑฐํ๊ณ ์ต์ข ์ฑ ํฌ๊ธฐ๋ฅผ ์ค์ด๋ ์ต์ ํ๋ฅผ ์ํํฉ๋๋ค. proguard ๊ตฌ์ฑ์ ์ฝ๋๋ฅผ ๋๋ ํํ๋๋ฐ ํ์ํ ๋ชจ๋ ์์ธ๊ฐ ์ถ๊ฐ๋๋ ย (proguard-rules.pro)ํ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค.
React Native์ ์ง๋ณดํ ๋ณด์
์ฑ์ด ์ฌ๋ฌ ๋๋ฐ์ด์ค์์ ์คํ๋๋ฏ๋ก ๋คํธ์ํฌ ์์ฒญ๊ณผ ๊ด๋ จ๋ ๋ช ๊ฐ์ง ์ํ์ด ์์ต๋๋ค. ๋ฃจํ ๋๊ณ ํ์ฅ๋ ๊ธฐ๊ธฐ์์ Intent์ ์ํด์ ์ฑ์ ์คํํ๋ ๊ฒ์ ๋ณธ์ง์ ์ผ๋ก ์์ ํ์ง ์๊ธฐ ๋๋ฌธ์ ์์ ํ ํผํด์ผ ํฉ๋๋ค. ๋ฃจํ ๋ ๋๋ฐ์ด์ค๋ ๊ณต๊ฒฉ์๊ฐ OS์ ๋ณด์ ๋ฉ์ปค๋์ฆ์ ๋ฌด๋ ฅํ์ํค๋๋ฐ ๋์์ ์ฃผ๋ฉฐ, ๋ณด์ ์คํ ๋ฆฌ์ง ๋ฐ ๋ฐ์ดํฐ์ ์ฝ๊ฒ ์ ๊ทผํ ์ ์๋๋ก ํฉ๋๋ค. JailMonkey๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋๋ฐ์ด์ค์ ๋ฃจํ ๋๋ ํ์ฅ ์ฌ๋ถ๋ฅผ ๊ฐ์งํ๋๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. Android ์ ์ฉ API์ธ SafetyNet์ ๋ฃจํ ๋ ๋๋ฐ์ด์ค ๋ฐ ๋ถํธ ๋ก๋์ ์ ๊ธ ํด์ ๋ฅผ ๊ฐ์งํ๋๋ฐ ๋์์ด ๋ฉ๋๋ค. ๋ํ ๋ณด์ ์ํ, ๋๋ฐ์ด์ค ๋ณ์กฐ, ์ ์ฑ ์ฑ ๋ฐ ๊ฐ์ง ์ฌ์ฉ์์ ๋ํ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค. SafetyNet์ API์ฉ ๋ํผ ํ๋ฌ๊ทธ์ธ์ธ react-native-google-safetynet์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์์ ๋๋ฐ์ด์ค๋ฅผ ๊ฒ์ฆํ ์ ์์ต๋๋ค. ๋ํ react-native-device-info ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ์ฌ ์ฑ์ด ์๋ฎฌ๋ ์ดํฐ์์ ์คํ ์ค์ธ์ง ํ์ธํ ์ ์์ต๋๋ค.
RASP
๋ฐํ์ ์ ํ๋ฆฌ์ผ์ด์ ์๊ฐ ๋ณดํธ(RASP) ๋๊ตฌ๋ ์ ํ๋ฆฌ์ผ์ด์ ์คํ ๋ฆฌ์ง์ ๋ํ ๊ณต๊ฒฉ์ ์ง์์ ์ผ๋ก ๊ฐ์งํ๊ณ ์ฑ์ ๋ณดํธํ ์ ์์ต๋๋ค. ์ด ๋๊ตฌ๋ ์ฑ์ ๋ฐํ์ ํ๊ฒฝ๋ด์ ๊ตฌ์ถ๋๋ฉฐ ์ฑ์ ๋ฐํ์ ์คํ์ ์ ์ดํ์ฌ ์ฑ์ ์ฑ๋ฅ๊ณผ ๋์์ ๋ถ์ํ ์ ์์ต๋๋ค. ์ถ๊ฐ ๋ณด์ ๊ณ์ธต์ ์ ๊ณตํ๊ณ ๋ค๋ฅธ ๋ณด์ ๋ฐ ์ฑ ๋ชจ๋ํฐ๋ง ๋๊ตฌ์ ํจ๊ป ์๋ํฉ๋๋ค. ์ฑ์ด RASP ๊ธฐ๋ฅ์ ๊ฐ๊ธฐ ์ํด์๋ ์ฑ ๋ฐํ์ ์คํ์ ์ ์ดํ๊ณ , ์ฑ ์ฑ๋ฅ ๋ฐ ๋์์ ๋ชจ๋ํฐ๋งํ๊ณ , ์นจ์ ๋๋ ๋น์ ์ ๋์์ ๊ฐ์งํ์ฌ์ผ ํฉ๋๋ค.
๊ฒฐ๋ก
React Native๋ ๊ฐ์ฅ ์ธ๊ธฐ ์๊ณ ํจ์จ์ ์ธ ์ฑ ๊ตฌ์ถ ํ๋ ์์ํฌ ์ค ํ๋์ ๋๋ค. ํฌ๋ก์ค ํ๋ซํผ ์ง์, ์ฌ์ฉ ์ฉ์ด์ฑ, ๋น์ฉ ๋ฐ ๋ฆฌ์์ค ์ต์ ํ, ๋ฐ์ด๋ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ ์ ์ธ๊ณ ๊ฐ๋ฐ์์๊ฒ ํ๋ฅญํ ์ ํ์ ๋๋ค. ์ฌ์ ์ ๋ง๋ค์ด์ง ์ปดํฌ๋ํธ ๋ฐ ๋ด์ฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ๋ถํ๊ฒ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ๊ฐ๋จํ ๊ธฐ๋ฅ์ ์ฝ๊ฒ ์ํํ๋๋ฐ ์ ํฉํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ๋ ์์ํฌ๊ฐ JavaScript ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด ์ก๊ธฐย ๋๋ฌธ์ ์ด๋ฅผ ์ฌ์ฉํ ์ฑ์ ๋ณด์ ์ํ๊ณผ ์ธ๋ถ์ ์ ์์ ์ธ ์นจ์ ์๋์ ๋ ์ทจ์ฝํฉ๋๋ค. ๋ํ ์ฑ ์ ์ฒด์ ๊ฑธ์ณ ์ ์ฌํ ๊ตฌ์ฑ ์์๋ฅผ ์ฌ์ฉํ๋ฉด, ์๋ฌด๋๋ ๋ณด์ ์ํ๋ ๋์์ง๋๋ค. ๋ฐ๋ผ์ ๊ฐ๋ฐ์๋ Android ๋ฐ iOS์์ ์ฌ์ฉํ ์ ์๋ ๋ชจ๋ ๋ณด์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ React Native ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณดํธํด์ผ ํฉ๋๋ค. ์ฑ์ ์ฌ์ฉ ์ฌ๋ก์ ์ฌ์์ ๋ฐํ์ผ๋ก ์ํ ๋ชจ๋ธ์ ์์ฑํ ํ ์ฑ ๋ณด์์ ๋ํ ๊ณต๊ฒฉ์ ๋ฐฉ์งํ๊ธฐ ์ํด ํ์ํ ์๋ฐฉ ์กฐ์น๋ฅผ ์ทจํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. 100% ๋ณด์์ ๋ณด์ฅํ๋ ๋ฐฉํ ๋ฉ์ปค๋์ฆ์ ์์ง๋ง ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ API๋ฅผ ํตํฉํ๋ฉด ์ํ ๋ฐ์์ ํ์คํ ์ค์ผ ์ ์์ต๋๋ค.
์ถ๊ฐ ์ฝ๋ฉ์์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณดํธํ๋ ค๋ฉด ์๋ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ์ฑ์ค๋ง์ ๋ํด ์์ธํ ์์๋ณด๊ณ ๋ฌด๋ฃ ํ๊ฐํ์ ์ฌ์ฉํด ๋ณด์ญ์์ค.