new Key() ๋ฅผ ํธ์ถํ๋ฉด, ๋ด๋ถ์ ์ผ๋ก๋ ๊ฐ์ธ ํค๋ฅผ ์์ฑํ๊ธฐ ์ํด์ ์์ฌ ๋์ ์์ฑ๊ธฐ(Pseudo-Random-Number-Generator)๋ฅผ ์ฌ์ฉํฉ๋๋ค. Windows ํ๊ฒฝ์์๋ Windows Crypto API์ .NET ๋ํผ์ธ RNGCryptoServiceProvider๋ฅผ ์ฌ์ฉํฉ๋๋ค.
Android ํ๊ฒฝ์์๋ SecureRandom ํด๋์ค๋ฅผ ์ฌ์ฉํ์ง๋ง, ์ํ๋ค๋ฉด RandomUtils.Random์ ์ด์ฉํ ์์ ๋ง์ ๊ตฌํ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
iOS ํ๊ฒฝ์์๋ ์์ง ๊ตฌํ๋์ง ์์๊ธฐ์ ์์ ๋ง์ IRandom ๊ตฌํ์ฒด๊ฐ ํ์ํฉ๋๋ค.
์ปดํจํฐ์๊ฒ ์์ด์, ๋๋คํ๋ค๋ ๊ฒ์ ์ด๋ ต์ต๋๋ค. ๊ฐ์ฅ ํฐ ๋ฌธ์ ๋ ์ฃผ์ด์ง ์ซ์๋ค์ด ์ ๋ง ๋๋ค์ธ์ง ํ์ธํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๋ค๋ ์ ์ ๋๋ค.
๋ง์ฝ ์ ์ฑ์ฝ๋๊ฐ ๋์ ์์ฑ๊ธฐ๋ฅผ ์กฐ์ํ๋ค๋ฉด(๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ซ์๋ฅผ ์์ธกํ ์ ์๋ค๋ฉด), ์ํฉ์ด ๋ฐ์ํ๊ธฐ ์ ๊น์ง ์์์ฐจ๋ฆด ์ ์์ต๋๋ค.
์ด๋ ํฌ๋ก์ค ํ๋ซํผ๊ณผ ํ์ ํ ๋์ ์์ฑ๊ธฐ(์๋ฅผ ๋ค๋ฉด CPU ์๋์ ์ฐ๊ด๋ ์ปดํจํฐ์ ์๊ฐ ์ฌ์ฉ)๋ ์ํํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ผ์ด ๋ฒ์ด์ง๊ธฐ ์ ๊น์ง ์์์ฐจ๋ฆด ์ ์์ต๋๋ค.
์ฑ๋ฅ์ ์ด์ ๋ก ๋๋ถ๋ถ์ ๋์ ์์ฑ๊ธฐ๋ ๋๊ฐ์ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค: ์๋๋ผ๊ณ ๋ถ๋ฅด๋ ๋์๋ฅผ ๊ณ ๋ฅด๊ณ ์์ธก ๊ฐ๋ฅํ ์์์ด ์์ฒญํ ๋๋ง๋ค ๋ค์ ์ซ์๋ฅผ ์์ฑํฉ๋๋ค.
์๋์ ๋ํดํจ ์ ๋๋ ์ํธ๋กํผ๋ผ๊ณ ๋ถ๋ฆฌ๋ ์ธก์ ์ผ๋ก ์ ์๋์ง๋ง, ์ํธ๋กํผ์ ์ ๋ ์ญ์ ๊ด์ธก์์ ์์กดํฉ๋๋ค.
์๊ณ์ ์๊ฐ์ผ๋ก๋ถํฐ ์๋๋ฅผ ์์ฑํ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ๋จํ๊ฒ, ์๊ณ๋ 1ms์ ๋ถํด๋ฅ์ ๊ฐ์ง๊ณ ์๋ค๊ณ ํด๋ด ์๋ค. (์ฌ์ค, 15ms ์ ๋ ๋ ํฝ๋๋ค.)
๋ง์ฝ ๊ณต๊ฒฉ์๊ฐ ์ ๋ฒ์ฃผ์ ์์ฑํ ํค๋ฅผ ์๊ณ ์๋ค๋ฉด, ๋น์ ์ ์๋๋
1000 * 60 * 60 * 24 * 7 = 604800000๊ฐ์ง์ ๊ฐ๋ฅ์ฑ
์ ๊ฐ์ง๋๋ค.
๊ณต๊ฒฉ์์๊ฒ ์ํธ๋กํผ๋ log2(604800000) = 29.17๋นํธ ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ๋ฌํ ์๋ฅผ ๋์ ํ๋ ๊ฑด ์ต๊ทผ ์ปดํจํฐ๋ก 2์ด๊ฐ ์ฑ ์๊ฑธ๋ฆฝ๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ "๋ธ๋ฃจํธ ํฌ์ค"๋ผ๊ณ ํฉ๋๋ค.
๊ทธ๋ฌ๋ ๋ง์ฝ ์๋๋ก ํ๋ก์ธ์ค ID์ ์๊ฐ์ ์ฌ์ฉํ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ํ๋ก์ธ์ค ID๋ 1024๊น์ง ๊ฐ๋ฅํ๋ค๊ณ ์๊ฐํด ๋ด ์๋ค.
๊ทธ๋ ๋ค๋ฉด, ๊ณต๊ฒฉ์๋ 604800000 * 1024๊ฐ์ง๋ฅผ ๋์
ํด์ผ ํฉ๋๋ค. ์ด๋ ๋๋ต 2000์ด๊ฐ ์์๋ฉ๋๋ค.
๋์์์, ์๋์ ์ปดํจํฐ๋ฅผ ์ผ ์๊ฐ์ ์ถ๊ฐํ๊ณ ๊ณต๊ฒฉ์๋ ์ค๋ ์ผฐ๋ค๋ ๊ฒ์ ์๊ณ ์๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด, 86400000๊ฐ์ง์ ๊ฐ๋ฅ์ฑ์ด ์ถ๊ฐ๋ฉ๋๋ค.
์ฆ, ๊ณต๊ฒฉ์๋ 604800000 * 1024 * 86400000 = 5,35088E+19๊ฐ์ง์ ๊ฐ๋ฅ์ฑ์ ๋์
ํด์ผ ํฉ๋๋ค.
ํ์ง๋ง ๊ณต๊ฒฉ์๊ฐ ์ปดํจํฐ๋ฅผ ์ฅ์
ํด์ ๋ง์ง๋ง ์ ๋ณด(์ปดํจํฐ๋ฅผ ์ผ ์๊ฐ)์ ์ป์ด, ๊ฐ๋ฅ์ฑ์ ์๋ฅผ ์ค์ฌ ์ํธ๋กํผ๋ฅผ ์ค์ผ ์ ์๋ค๋ ๊ฒ์ ๋ช
์ฌํ์ธ์.
์ํธ๋กํผ๋ log2(๊ฐ๋ฅ์ฑ์ ์) ๋ก ์ธก์ ๋ฉ๋๋ค. ์ฆ log2(5,35088E+19) = 65๋นํธ ์ ๋๋ค.
์ด๊ฑธ๋ก ์ถฉ๋ถํ ๊น์? ๋ญ, ๊ณต๊ฒฉ์๊ฐ ์๋๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ๋ ์์ญ์ ๋ํ ์ ๋ณด๋ฅผ ๋ชจ๋ฅธ๋ค๊ณ ๊ฐ์ ํ๋ค๋ฉด ๋ง์ด์ฃ .
๊ทธ๋ฌ๋ ๊ณต๊ฐ ํค์ ํด์๋ 20๋ฐ์ดํธ (160๋นํธ)์ด๋ฏ๋ก, ์ฃผ์๋ค์ ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ณด๋ค ์์ต๋๋ค. ์์ง ๋ฉ์์ต๋๋ค.
Note: ์ํธ๋กํผ๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ ์ ํ์ ์ผ๋ก ์ด๋ ต์ง๋ง, ์ํธ๋กํผ๋ฅผ ๊นจ๋ ๊ฒ์ ๊ธฐํ๊ธ์์ ์ผ๋ก ์ด๋ ต์ต๋๋ค.
๋น ๋ฅด๊ฒ ์ํธ๋กํผ๋ฅผ ์์ฑํ๋ ์ฌ๋ฏธ์๋ ๋ฐฉ๋ฒ์ ๋ง์ฐ์ค ์์ง์๊ณผ ๊ฐ์ ์ธ๊ฐ์ ๊ฐ์ ์ ์ด์ฉํ๋ ๊ฒ์ ๋๋ค.
๋ง์ฝ ํ๋ซํผ์ ๋์ ์์ฑ๊ธฐ๋ฅผ ์์ ํ ์ ๋ขฐํ ์ ์๋ค๋ฉด(๊ฝค๋ ํฉ๋ฆฌ์ ์ธ ์์ฌ์ ๋๋ค.), NBitcoin์ ์ฌ์ฉํ ๋์ ์์ฑ๊ธฐ์ ์ํธ๋กํผ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค.
RandomUtils.AddEntropy("hello");
RandomUtils.AddEntropy(new byte[] { 1, 2, 3 });
var nsaProofKey = new Key();**AddEntropy(data)**๋ฅผ ํธ์ถํ๋ฉด NBitcoin์ ๋ค์๊ณผ ๊ฐ์ด ์๋ํฉ๋๋ค: additionalEntropy = SHA(SHA(data) ^ additionalEntropy)
์๋ก์ด ์๋ฅผ ์์ฑํ ๋: result = SHA(PRNG() ^ additionalEntropy)
However, what is most important is not the number of possibilities. It is the time that an attacker would need to successfully break your key. Thatโs where KDF enters the game.
KDF, ํน์ Key Derivation ํจ์๋ ์ํธ๋กํผ๊ฐ ๋ฎ๋๋ผ๋ ๊ฐํ ํค๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋๋ค.
๋น์ ์ด ์๋๋ฅผ ๋ง๋๋ ค๊ณ ํ๊ณ , ๊ณต๊ฒฉ์๋ 10,000,000๊ฐ์ง์ ๊ฐ๋ฅ์ฑ์ด ์๋ค๋ ๊ฒ์ ์๊ณ ์๋ค๊ณ ๊ฐ์ ํฉ์๋ค. ๊ทธ๋ฌํ ์๋๋ ์ผ๋ฐ์ ์ผ๋ก ๊ฝค๋ ์ฝ๊ฒ ๋ซ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
ํ์ง๋ง ๋์ ์ ๋๋ฆฌ๊ฒ ๋ง๋ค ์ ์๋ค๋ฉด ์ด๋จ๊น์? KDF๋ ์๋์ ์ผ๋ก ์ปดํจํ ์์์ ๋ญ๋นํ๋ ํด์ ํจ์์ ๋๋ค.
์์:
var derived = SCrypt.BitcoinComputeDerivedKey("hello", new byte[] { 1, 2, 3 });
RandomUtils.AddEntropy(derived);๊ณต๊ฒฉ์๋ ์ํธ๋กํผ๊ฐ 5๊ธ์์์ ์๋ฉด์๋ ๊ฐ ๊ฐ๋ฅ์ฑ์ ํ์ธํ๊ธฐ ์ํด์ , Scrypt๋ฅผ ์ํํด์ผ ํฉ๋๋ค. ์ด๋ ์ ์ปดํจํฐ์์(์ญ์์ฃผ: ์ ์์ ์ปดํจํฐ) 5์ด์ ๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ๋๋ค.
๊ฒฐ๋ก : ๋์ ์์ฑ๊ธฐ๋ฅผ ๋ถ์ ํ๋ ๊ฒ์ ์ ํ ํธ์ง์ฆ์ด ์๋๋ฉฐ, ์ํธ๋กํผ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ KDF๋ฅผ ์ฌ์ฉํจ์ ํตํด ๊ณต๊ฒฉ์ ์ํํ ์ ์์ต๋๋ค. ๊ณต๊ฒฉ์๋ ์ฌ์ฉ์๋ ์์คํ ์ผ๋ก๋ถํฐ ์ ๋ณด๋ฅผ ์ป์ด ์ํธ๋กํผ๋ฅผ ์ค์ผ ์ ์์์ ํญ์ ์ผ๋ํ์ธ์. ๋ง์ฝ ์๊ฐ์ ์ํธ๋กํผ๋ก ์ฌ์ฉํ๋ค๋ฉด, ๊ณต๊ฒฉ์๋ ํค๋ฅผ ์ ๋ฒ์ฃผ์ ๋ง๋ค์๊ณ , ์ค์ 9์๋ถํฐ ์คํ 6์์๋ง ์ปดํจํฐ๋ฅผ ์ฌ์ฉํ๋ค๋ ์ ๋ณด๋ฅผ ์ฌ์ฉ์๋ก๋ถํฐ ์์๋ด์ ์ํธ๋กํผ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค.
์ด์ ํํธ์์ Scrypt๋ผ ๋ถ๋ฆฌ๋ KDF์ ๋ํด ๊ฐ๋ตํ ์๊ฐํ์ต๋๋ค. ์์์ ๋งํ๋ฏ, KDF๋ ๋ธ๋ฃจํธ ํฌ์ค๋ฅผ ์ด๋ ต๊ฒ ๋ง๋๋ ๊ฒ์ด ๋ชฉํ์ ๋๋ค.
๊ทธ๋ ๊ธฐ์ KDF๋ฅผ ์ฌ์ฉํ ๋น๋ฐ๋ฒํธ๋ก ๊ฐ์ธ ํค๋ฅผ ์ํธํํ๋ ํ์ค์ด ์กด์ฌํฉ๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก BIP38์ ๋๋ค.
var privateKey = new Key();
var bitcoinPrivateKey = privateKey.GetWif(Network.Main);
Console.WriteLine(bitcoinPrivateKey); // L1tZPQt7HHj5V49YtYAMSbAmwN9zRjajgXQt9gGtXhNZbcwbZk2r
BitcoinEncryptedSecret encryptedBitcoinPrivateKey = bitcoinPrivateKey.Encrypt("password");
Console.WriteLine(encryptedBitcoinPrivateKey); // 6PYKYQQgx947Be41aHGypBhK6TA5Xhi9TdPBkatV3fHbbKrdDoBoXFCyLK
var decryptedBitcoinPrivateKey = encryptedBitcoinPrivateKey.GetSecret("password");
Console.WriteLine(decryptedBitcoinPrivateKey); // L1tZPQt7HHj5V49YtYAMSbAmwN9zRjajgXQt9gGtXhNZbcwbZk2r
Console.ReadLine();์ด๋ฌํ ์ํธํ๋ ๋๊ฐ์ง ๊ฒฝ์ฐ์ ์ฐ์ ๋๋ค.
- ์คํ ๋ฆฌ์ง ํ๋ก๋ฐ์ด๋๋ฅผ ์ ๋ขฐํ ์ ์์ ๋ (ํดํน์ ์ํ์ ๊ฐ์ง๊ณ ์์ ๋)
- ๋๊ตฐ๊ฐ๋ฅผ ๋์ ํ์ฌ ํค๋ฅผ ๋ณด๊ดํ ๋ (๊ทธ๋ฆฌ๊ณ ๊ทธ๋ค์ ํค๋ฅผ ์๊ณ ์ถ์ง ์์ ๋)
๋ง์ฝ ์์ ๋ง์ ์คํ ๋ฆฌ์ง๊ฐ ์๋ค๋ฉด, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ค์ ์ํธํ๋ ์ถฉ๋ถํฉ๋๋ค.
๋ง์ฝ ์๋ฒ๊ฐ ๋ณตํธํ๋ ํค๋ฅผ ์์ ํ๊ณ ์๋ค๋ฉด ์กฐ์ฌํ์ธ์. ๊ณต๊ฒฉ์๊ฐ ํค๋ฅผ ๋ณตํธํํ๊ธฐ ์ํด DDoS๋ฅผ ์๋ํ ์ ์์ต๋๋ค.
๋๋๋ก์ด๋ฉด ์ต์ข ์ฌ์ฉ์์๊ฒ ๋ณตํธํ๋ฅผ ์์ํ์ธ์.
