일반적으로 신뢰할 수있는 것으로 간주되는 SHA-256 자바 스크립트 구현이 있습니까?


98

포럼에 대한 로그인을 작성 중이며 서버로 보내기 전에 비밀번호 클라이언트 측을 자바 스크립트로 해시해야합니다. 실제로 신뢰할 수있는 SHA-256 구현을 파악하는 데 문제가 있습니다. 모든 사람이 사용하는 권위있는 스크립트가있을 것으로 예상했지만 모두 자체 구현을 가진 다양한 프로젝트를 찾고 있습니다.

다른 사람의 암호 화폐를 사용하는 것은 여러분이 직접 검토 할 자격이없는 한 항상 믿음의 도약이며 "신뢰할 수있는"에 대한 보편적 인 정의가 없다는 것을 알고 있습니다. 무엇을 사용해야하는지에 대한 합의. 그냥 순진한가요?

댓글에 많이 나오기 때문에 편집 : 예, 서버 측에서 다시 더 엄격한 해시를 수행합니다. 클라이언트 측 해싱은 데이터베이스에 저장하는 최종 결과가 아닙니다. 클라이언트 측 해싱은 인간 클라이언트가 요청하기 때문입니다. 그들은 특별한 이유를 제시하지 않았으며 아마도 그들은 과잉 살인을 좋아할 것입니다.


9
주제에서 벗어나지 않고 클라이언트 측에서 암호를 해싱하는 이유는 무엇입니까?
Steve

5
@ddyer 가깝지도 않습니다. "Do n't roll your own"은 자신의 알고리즘을 발명하거나, 알고리즘의 자체 구현 을 작성 하고, 암호화 알고리즘 위에 자신의 프로토콜을 개발하거나, 가능한 한 높은 수준의 추상화를 사용하여 위의 거의 모든 것에 적용됩니다. 안전한 코어를 고수하고 글루 코드 만 작성하는 것이 안전하다고 생각한다면 나쁜 시간을 보낼 것입니다.
Stephen Touset 2013-08-19

26
챌린지 / 응답 프로토콜없이 해시 된 암호를 사용하는 경우 해시 된 암호는 암호이며 실제로는 일반 텍스트로 암호를 전송하는 것과 동일합니다.
ddyer

26
@ddyer 특히 우리 사이트가 아니라면 사용자가 사용할 수있는 다른 모든 사이트에 대한 사용자의 일반 텍스트 암호를 보호하는 데는 가치가 있습니다. 그것은 우리에게 도움이되지 않을 수도 있지만 우리가 어딘가를 망칠 경우 잠재적으로 사용자를 도울 수있는 쉬운 수정입니다. 그리고 내가 말했듯이, 클라이언트 요청, 내가 원하더라도 내가 할 수있는 것은 아무것도 없습니다.
jono

5
@Anorov 나는 내 마음이 바뀌는 것에 개방적입니다 :) 그러나이 경우 귀하의 요점이 어떻게 적용되는지 이해하지 못합니다. 우리는 암호를 두 번 해시합니다. 한 번은 간단한 SHA-256으로 클라이언트 측에, 한 번은 더 까다로운 서버 측에 있습니다. 첫 번째는 MITM 또는 이와 유사한 경우 일반 텍스트를 보호하고 두 번째는 무차별 보호를위한 것입니다. 데이터베이스와 관리자 해시를 보유하고 있더라도 로그인을 확인하는 데 직접 사용할 수는 없습니다.
jono 2013-08-19

답변:


114

스탠포드 JS 암호화 라이브러리는 SHA-256의 구현을 포함한다. JS의 암호화는 다른 구현 플랫폼만큼 잘 검증되지는 않았지만, 이것은 암호화 분야에서 잘 확립되고 신뢰할 수있는 이름 인 Dan Boneh 가 적어도 부분적으로 개발하고 어느 정도 후원합니다. , 그리고 프로젝트가 자신이하고있는 일을 실제로 아는 누군가에 의해 약간의 감독이 있음을 의미합니다. 이 프로젝트는 NSF 에서도 지원합니다 .

그러나 ...
... 제출하기 전에 클라이언트 측에서 암호를 해시하면 해시는 암호가되고 원래 암호는 무의미 해집니다. 공격자는 사용자를 가장하기 위해 해시를 가로 채기 만하면됩니다. 해시가 수정되지 않은 상태로 서버에 저장되면 서버는 일반 텍스트로 실제 암호 (해시)를 저장 합니다. .

따라서 이전에 신뢰할 수 있었던 계획에 자체 개선 사항추가하기 로 결정했기 때문에 이제 보안이 더 나빠 졌습니다.


32
그러나 서버에서 다시 해시하면이 관행은 완벽하게 합법적입니다.
Nick Brunt 2013

13
@NickBrunt 서버에서 해시하면 전송 된 암호를 저장하지 않지만 암호 해시를 전송하는 것과는 반대로 원래 암호를 전송하는 것 이상의 보안을 추가하지 않았습니다. 두 경우 모두 전송하는 것이 실제 암호.
tylerl 2013

54
사실이지만 인터넷의 다른 곳에서 일반 텍스트로 사용되는 암호를 보내는 것보다 나쁘지 않습니다.
Nick Brunt 2013

15
@NickBrunt 동의합니다. 공격자가 여러 곳에서 사용될 수있는 원래 암호보다이 특정 앱에만 맞는 임의의 해시 문자열을 읽는 것이 좋습니다.
Aebsubis

13
서버가 사용자의 일반 텍스트 암호를 보지 않기를 원하기 때문에 클라이언트 측 해싱을 사용해야합니다. 내가 제공하는 서비스에 대한 추가 보안이 아니라 사용자에 대한 보안입니다. 나는 사용자의 해시를 상수 솔트 (전세계가 아닌 사용자 당 상수)로 솔트 할뿐만 아니라, 스니핑에 대해 네트워크에 약간의 추가 보안을 제공하는 로그인 할 때마다 임의의 세션 솔트로 다시 해싱합니다. 서버가 손상되면 게임이 끝났지 만 어쨌든 p2p가 아닌 것은 사실입니다.
Hatagashira

54

https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest 나는 내부의 js 모듈을 사용하여이 조각을 발견 :

async function sha256(message) {
    // encode as UTF-8
    const msgBuffer = new TextEncoder().encode(message);                    

    // hash the message
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

    // convert ArrayBuffer to Array
    const hashArray = Array.from(new Uint8Array(hashBuffer));

    // convert bytes to hex string                  
    const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
    return hashHex;
}

참고는 crypto.subtle에서만 사용할 수에서와 httpslocalhost-와 지역 개발을위한 예를 들어 python3 -m http.server당신은 당신이 라인을 추가해야합니다 /etc/hosts: 0.0.0.0 localhost

재부팅-당신은 localhost:8000작업으로 열 수 있습니다 crypto.subtle.


2
굉장합니다. 감사합니다. Node.js에서 유사한 API를 사용할 수 있습니까?
Con Antonakos

2
내장 된 'crypto'라이브러리는 잘 작동합니다. nodejs.org/dist/latest-v11.x/docs/api/crypto.html
tytho

18

단조 공장 의 SHA-256 구현은 빠르고 안정적입니다.

여러 SHA-256 JavaScript 구현에 대한 테스트를 실행하려면 다음으로 이동하십시오. http://brillout.github.io/test-javascript-hash-implementations/ .

내 컴퓨터의 결과는 forge가 가장 빠른 구현이며 수락 된 답변에 언급 된 Stanford Javascript Crypto Library (sjcl)보다 훨씬 빠르다는 것을 나타냅니다.

Forge는 크기가 256KB이지만 SHA-256 관련 코드를 추출하면 크기가 4.5KB로 줄어 듭니다. https://github.com/brillout/forge-sha256 참조


를 사용하여 설치 npm install node-forge했지만 이제 라이브러리를 사용하는 방법은 문자열에서 해시를 생성 foo합니까?
사용자

17

관심있는 사람들을 위해 다음을 사용하여 SHA-256 해시를 만드는 코드입니다 sjcl.

import sjcl from 'sjcl'

const myString = 'Hello'
const myBitArray = sjcl.hash.sha256.hash(myString)
const myHash = sjcl.codec.hex.fromBits(myBitArray)

4
여기에서 솔루션을 사용하려는 사람들을 위해 허용되는 답변에 포함되어야합니다. (지옥, 심지어 자신의 문서는이 같은 조각이없는)
MagicLegend

이것이 최고의 답변입니다. 나는 암호화 솔루션을 시도했지만 그것은 나를 위해 작동하지 않았습니다.
Augusto Gonzalez

12

아니요, 브라우저 JavaScript를 사용하여 암호 보안을 향상시킬 수있는 방법은 없습니다. 이 기사 를 읽어 보는 것이 좋습니다 . 귀하의 경우 가장 큰 문제는 닭 계란 문제입니다.

Javascript 암호화를 제공하는 데있어 "닭 달걀 문제"는 무엇입니까?

네트워크가 암호를 전달하는 것을 신뢰하지 않거나, 더 나쁜 것은 서버가 사용자 비밀을 유지하지 않는다는 것을 신뢰하지 않는 경우, 보안 코드를 제공하는 것을 신뢰할 수 없습니다. 암호를 도입하기 전에 암호를 스니핑하거나 일기를 읽던 공격자는 단순히 암호 코드를 하이재킹하는 것입니다.

[...]

TLS / SSL을 사용하여 Javascript 암호화 코드를 전달할 수없는 이유는 무엇입니까?

할 수 있습니다. 생각보다 어렵지만 SSL을 사용하여 Javascript 암호화를 브라우저에 안전하게 전송합니다. 문제는 SSL로 보안 채널을 설정 했으므로 더 이상 Javascript 암호화가 필요하지 않다는 것입니다. 당신은 "진짜"암호화를 가지고 있습니다.

이로 인해 :

Javascript에서 암호화 코드를 실행할 때의 문제는 암호화가 의존하는 거의 모든 기능이 호스팅 페이지를 구축하는 데 사용되는 콘텐츠에 의해 자동으로 무시 될 수 있다는 것입니다. 암호화 보안은 프로세스 초기에 (가짜 난수를 생성하거나 알고리즘에서 사용하는 상수 및 매개 변수를 조작하여) 또는 나중에 (키 자료를 공격자에게 다시 스 피팅하여) 취소 할 수 있습니다. 가능성이 가장 높은 시나리오에서 --- 암호 화폐를 완전히 우회함으로써.

어떤 자바 스크립트 코드도 실행 환경을 확인할 수있는 신뢰할 수있는 방법이 없습니다. 자바 스크립트 암호화 코드는 "난 정말 난수 생성기를 다루고 있습니까, 아니면 공격자가 제공 한 일부 팩시밀리를 다루고 있습니까?"라고 묻지 않습니다. 그리고 그것은 "저자 인 내가 승인하는 방식을 제외하고는 아무도이 암호 비밀로 아무것도 할 수 없다"고 주장 할 수 없습니다. 이들은 암호화를 사용하는 다른 환경에서 종종 제공되는 두 가지 속성이며 Javascript에서는 불가능합니다.

기본적으로 문제는 다음과 같습니다.

  • 클라이언트는 서버를 신뢰하지 않으므로 추가 보안 코드를 추가하려고합니다.
  • 해당 보안 코드는 서버 (신뢰하지 않는 서버)에서 제공합니다.

또는

  • 클라이언트는 SSL을 신뢰하지 않으므로 추가 보안 코드를 사용하기를 원합니다.
  • 해당 보안 코드는 SSL을 통해 전달됩니다.

참고 : 또한 SHA-256은 무염 비 반복 암호무차별 대입 하기가 쉽기 때문에 이에 적합하지 않습니다 . 어쨌든 이것을하기로 결정 했다면 , bcrypt , scrypt 또는 PBKDF2 의 구현을 찾으십시오 .


1
이것은 정확하지 않습니다. 클라이언트 측에서 해싱하여 암호 보안을 향상시킬 수 있습니다. SHA-256이 PBKDF2와 같은 것이 서버 측에서 사용되는 한 적합하지 않다는 것도 잘못되었습니다. 셋째, matasano 기사에는 유용한 통찰력이 포함되어 있지만 이제 치킨과 계란 문제를 근본적으로 변경하는 브라우저 앱이 있으므로 핵심은 잘못되었습니다.
user239558

2
클라이언트에서 PBKDF2를 사용해야하는 것이 맞습니다. 클라이언트 측 자바 스크립트 암호화에 대한 분노는 초기 페이지와 후속 요청이 동일한 보안 속성을 가지고 있다고 가정합니다. 초기 페이지가 별도로 설치되고 정적 인 브라우저 앱의 경우 이는 분명히 사실이 아닙니다. 또한 cache-forever 시맨틱이있는 페이지에도 해당되지 않습니다. 이 경우 클라이언트 측 프로그램을 설치할 때와 똑같은 TOFU입니다. 서버에서 정적 및 동적 페이지 제공이 분리 된 더 복잡한 설정에서도 마찬가지입니다.
user239558 2013-10-03

3
시스템 관리자가 사용자 암호에 액세스하는 것을 피하는 것이 합법적이므로 클라이언트 측에서 해시하면 많은 사용자가 암호를 반복하므로 DBA 또는 기타 IT 전문가가 사용자 암호를보고 다른 서비스 / 시스템에 액세스하는 데 다시 사용하지 못하도록 방지합니다. .
야마다

1
@Xenland 당신이하는 일은 "토큰 + 암호"라는 새 암호를 만드는 것입니다. 원래의 모든 문제가 여전히 적용됩니다. 예를 들어 공격자는 JavaScript를 코드로 대체하여 토큰 + 암호를 보낼 수 있습니다.
Brendan Long

2
@Xenland 닭고기와 달걀 문제는 귀하가 보내는 요청과 관련이 없습니다. 문제는 클라이언트가 보안 작업을 수행하기 위해 안전하지 않은 연결통해 다운로드 한 JavaScript 코드 사용 하고 있다는 것 입니다. JavaScript를 웹 브라우저에 안전하게 보내는 유일한 방법은 TLS를 통해 제공하는 것입니다. 일단 그렇게하면 연결이 이미 안전하기 때문에 다른 작업을 수행 할 필요가 없습니다. 공격자가 대체 할 수있는 JavaScript 코드를 사용하는 경우 프로토콜이 무엇인지는 중요하지 않습니다.
Brendan Long

10

이 구현은 사용하기 매우 쉽습니다. 또한 넉넉한 BSD 스타일 라이센스가 있습니다.

jsSHA : https://github.com/Caligatio/jsSHA

SHA-256 해시의 16 진수 문자열 표현을 가져 오는 빠른 방법이 필요했습니다. 3 줄만 필요했습니다.

var sha256 = new jsSHA('SHA-256', 'TEXT');
sha256.update(some_string_variable_to_hash);
var hash = sha256.getHash("HEX");

1

tylerl이 언급 한 Stanford lib 외에. jsrsasign이 매우 유용하다는 것을 알았 습니다 (Github repo : https://github.com/kjur/jsrsasign ). 정확히 얼마나 신뢰할 수 있는지는 모르지만 SHA256, Base64, RSA, x509 등의 API를 사용했으며 꽤 잘 작동합니다. 실제로 Stanford lib도 포함됩니다.

원하는 것이 SHA256 뿐이라면 jsrsasign 은 과잉 일 수 있습니다. 하지만 관련 분야에서 다른 요구 사항이 있으면 잘 맞는 것 같습니다.



2
동의하지만 공정하게 말하자면, 2015 년에 모질라의 웹 암호화 API 사양이 게시되는 동안이 질문에 답변했습니다. 2017 년 1 월
Faraway
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.