Closed stariki closed 10 years ago
현재 올챙이 비번을 잃어 버렸을 경우에대비한 기능이 갖추어져있습니다. 필요한 기능이긴 한데.. 다른 이슈가 많아 조금 미뤄서 처리 해야할 듯해요.
감사해요.
"올챙이로 100대서버 관리/접속 하는데, 올챙이가 뚫리면 100대가 뚫리는 것 아니야?" 라는 걱정/우려가 있을 수 있다고 생각합니다.
올챙이의 비약적인 성장을 대비해, 다다다음~에는 꼭 넣어주셨으면 합니다. 감사합니다.
p.s 비번 분실시, 질문에 대한 답변이 개인적인 내용이 될 수 도 있다고 생각합니다. 평문보다는 해쉬(message digest)해서 저장해주시는 것이 좋지 않을까 싶습니다.
아네. 거기까지는 생각을 못했네요. 좀더 진지하게 고민해 보겠습니다. 감사합니다.
비번관련 부분은 수정되었습니다.
작업해주신다고 하셔서, qrcode 쪽 링크 자료 올립니다.
1) qrcode에 들어가는 내용 (text 포멧) https://code.google.com/p/google-authenticator/wiki/KeyUriFormat
2) 샘플처럼 아래 내용을 qrcode에 넣으면 "otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example"
3) 스마트폰에 구글OTP 앱 설치 후, 계정추가 메뉴에서...
4) 서버 검증은 아래 부분 활용..
http://tools.ietf.org/html/rfc6238 구현된 소스 조금 수정했습니다.
import java.lang.reflect.UndeclaredThrowableException;
import java.security.GeneralSecurityException;
import java.util.Date;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
public class TOTP {
private TOTP() {}
private static byte[] hmac_sha(String crypto, byte[] keyBytes,
byte[] text){
try {
Mac hmac;
hmac = Mac.getInstance(crypto);
SecretKeySpec macKey =
new SecretKeySpec(keyBytes, "RAW");
hmac.init(macKey);
return hmac.doFinal(text);
} catch (GeneralSecurityException gse) {
throw new UndeclaredThrowableException(gse);
}
}
private static byte[] hexStr2Bytes(String hex){
byte[] bArray = new BigInteger("10" + hex,16).toByteArray();
byte[] ret = new byte[bArray.length - 1];
for (int i = 0; i < ret.length; i++)
ret[i] = bArray[i+1];
return ret;
}
private static final int[] DIGITS_POWER
// 0 1 2 3 4 5 6 7 8
= {1,10,100,1000,10000,100000,1000000,10000000,100000000 };
private static byte[] longToByteArray(long n)
{
byte[] b = new byte[8];
b[7] = (byte) (n);
n >>>= 8;
b[6] = (byte) (n);
n >>>= 8;
b[5] = (byte) (n);
n >>>= 8;
b[4] = (byte) (n);
n >>>= 8;
b[3] = (byte) (n);
n >>>= 8;
b[2] = (byte) (n);
n >>>= 8;
b[1] = (byte) (n);
n >>>= 8;
b[0] = (byte) (n);
return b;
}
public static String generateTOTP(String key,
String returnDigits
){
int codeDigits = Integer.decode(returnDigits).intValue();
String result = null;
// Get the HEX in a Byte[]
// byte[] msg = hexStr2Bytes(time);
byte[] msg = longToByteArray(new Date().getTime()/(30*1000)); // 30초 주기로 생성..
byte[] k = hexStr2Bytes(key);
byte[] hash = hmac_sha("HmacSHA1", k, msg);
int offset = hash[hash.length - 1] & 0xf;
int binary =
((hash[offset] & 0x7f) << 24) |
((hash[offset + 1] & 0xff) << 16) |
((hash[offset + 2] & 0xff) << 8) |
(hash[offset + 3] & 0xff);
int otp = binary % DIGITS_POWER[codeDigits];
result = Integer.toString(otp);
while (result.length() < codeDigits) {
result = "0" + result;
}
return result;
}
public static void main(String[] args) {
String key = "48656C6C6F21DEADBEEF"; // "JBSWY3DPEHPK3PXP" secret base32 decoding
System.out.println(generateTOTP(key, "6")); // 구글 OTP 앱에서 표시되는 값과 같아야...
}
}
생성알고리즘이 시간 기반인 경우, 스마트폰 시간 오차가 있으니 이점 감안해주셔야 합니다.
이상입니다. 감사합니다.
https://github.com/wstrange/GoogleAuth 를 이용하였습니다.
예상 시나리오는 다음과 같습니다.
올챙이가 강력할 수록 보안이슈도 커질 것 같습니다.
관리자 로긴시 two factor인증을 도입하시는 것은 어떨까요? 비밀번호 이외에 one time password를 입력받아 사용자를 인증하는 거죠. 공개된 알고리즘을 사용하면 될 듯 싶습니다. (RFC 6238) 스마트폰 앱으로 많이 있으니, 사용자는 그냥 설치해서 사용하면 되고요. (ex 구글 OTP) 올챙이서버에서
어떨까요?