GDPR 준수 안드로이드 앱 개발 가이드 - 암호화와 E2EE
GDPR 준수 채팅 앱 만들기
소개
안녕하세요 Back4app 커뮤니티!
이것은 Virgil Security, Inc.: 우리는 Twilio의 종단 간 암호화 메시징. 우리의 친구 @ Back4app이 종단 간 암호화 채팅 앱을 Back4app 위에 구축하는 방법을 보여달라고 요청했습니다.
이 게시물에서는 간단한 Back4App Android 메신저 앱을 종단 간 암호화하는 단계를 안내해 드리겠습니다! 준비되셨나요? PS: 세부 사항이 중요하지 않다면, 게시물 끝으로 건너뛰고 최종 제품을 다운로드하세요.
종단 간 암호화란 무엇인가?
먼저, E2EE(종단 간 암호화)가 무엇인지와 어떻게 작동하는지 간단히 복습해 보겠습니다. E2EE는 간단합니다: 채팅 메시지를 입력하면 모바일 장치(또는 브라우저)에서 암호화되고, 채팅 파트너가 수신하여 채팅 창에 표시하고자 할 때만 복호화됩니다.

메시지는 Wi-Fi와 인터넷을 통해 클라우드/웹 서버를 거쳐 데이터베이스로 이동하고 다시 채팅 파트너에게 돌아가는 동안 암호화된 상태로 유지됩니다. 다시 말해, 두 사람이 무엇에 대해 채팅하고 있는지 네트워크나 서버는 전혀 알지 못합니다.

종단 간 암호화에서 어려운 점은 채팅에 참여하는 사용자만 접근할 수 있도록 암호화 키를 관리하는 작업입니다. 내가 “다른 누구도”라고 쓸 때, 정말로 그렇게 말하는 것입니다: 클라우드 제공업체의 내부자나 심지어 당신, 개발자조차도 접근할 수 없습니다; 우연한 실수는 없다 또는 법적으로 강제된 엿보기가 가능합니다. 암호화 작업, 특히 여러 플랫폼을 위한 암호화 작업은 어렵습니다: 진정한 난수를 생성하고, 올바른 알고리즘을 선택하고, 올바른 암호화 모드를 선택하는 것은 대부분의 개발자들이 손을 흔들고 결국 그냥 하지 않게 만드는 몇 가지 예일 뿐입니다.
이 블로그 게시물에서는 이러한 성가신 세부 사항을 무시하고 Virgil의 SDK를 사용하여 빠르고 간단하게 종단 간 암호화를 수행하는 방법을 보여줍니다.
소개로, 우리는 Back4app의 메신저 앱을 종단 간 암호화로 업그레이드하는 방법은 다음과 같습니다:
- 가입 시: 새로운 사용자에 대한 개별 개인 키 및 공개 키를 생성합니다 (기억하세요: 수신자의 공개 키가 메시지를 암호화하고 일치하는 수신자의 개인 키가 이를 복호화합니다).
- 메시지를 보내기 전에, 수신자의 공개 키로 채팅 메시지를 암호화합니다.
- 메시지를 받은 후, 수신자의 개인 키로 채팅 메시지를 복호화합니다.

우리는 사용자의 공개 키를 Virgil의 카드 서비스에 게시하여 채팅 사용자가 서로를 조회하고 서로에게 메시지를 암호화할 수 있도록 합니다. 개인 키는 사용자 장치에 남아 있습니다.
간단하게 유지하세요
이것은 E2EE 채팅의 가장 간단한 구현이며, 2명의 사용자 간의 간단한 채팅 앱에 완벽하게 작동합니다. 대화가 짧고 개인 키가 있는 장치를 잃어버리면 메시지 기록을 잃어버려도 괜찮습니다.
좋아요, 충분히 이야기했어요! 이제 코딩을 시작해봅시다.
- 안드로이드 앱의 설정을 안내하겠습니다.
- 그 다음, 앱을 종단 간 암호화하도록 코드를 추가하겠습니다.
전제 조건
이 튜토리얼을 완료하려면 다음이 필요합니다:
- 안드로이드 스튜디오.
- Back4App에서 생성된 앱.
“클린” Back4app 메신저 앱 설정하기
1: 앱 서버 설정하기
클라우드 기능 배포부터 시작하겠습니다. 이를 위해서는 다음이 필요합니다:
- 찾기 main.js 및 package.json 에서 scripts 디렉토리;
- 열기 main.js 좋아하는 편집기로.
1.1) Back4App 자격 증명 받기
- 열기 대시보드 앱의 > 앱 설정 > 보안 및 키:

- 메인에서 main.js, PARSE_APP_ID를 당신의 애플리케이션 ID로 교체하고 PARSE_REST_API_KEY를 당신의 REST API 키:
1.2) Virgil 자격 증명 가져오기

- 새로운 Virgil 애플리케이션을 열고 E3Kit 섹션으로 이동하여 .env 파일을 왼쪽 사이드바의 E3Kit 섹션 아래에 생성합니다.

- 다음의 값을 복사합니다: APP_ID, APP_KEY, 그리고 APP_KEY_ID를 .env 파일에서 복사합니다.

- 복사한 값을 main.js 파일의 해당 필드(main.js의 scripts 디렉토리에 교체하세요:
1.3) 클라우드 코드 함수를 배포하세요
- Back4App “대시보드”를 열고 -> “코어” -> 클라우드 코드 함수;

- 클릭하여 +ADD를 선택하고 main.js 및 package.json(스크립트 디렉토리에서)을 선택한 후, 두 파일을 클라우드 폴더로 이동합니다;
- DEPLOY를 클릭합니다.
2: 클린 Back4app Kotlin 데모 앱 시작하기
먼저 Back4App 클라우드 코드 기능을 설정하는 것을 잊지 마세요. 이것은 이 데모의 필수 부분입니다. 그 후, 다음 단계를 진행하세요:
2.1) Android Studio에서 프로젝트 가져오기
- Android Studio 열기 -> 파일 > 새로 만들기 > 버전 관리에서 프로젝트 > Git
- Git 저장소 URL: https://github.com/VirgilSecurity/chat-back4app-android
- 다음 clean-chat-kt 브랜치를 체크아웃합니다.

중요!
“프로젝트” 유형의 파일 트리를 선택하세요. 이 튜토리얼 전반에 걸쳐 사용됩니다:

2.2) 프로젝트에 Back4App 자격 증명 설정하기
- Back4App “대시보드”에서 앱 -> “앱 설정” -> “보안 및 키”를 엽니다;

“ /app/src/main/res/values/strings.xml 파일로 이동하여 your_back4app_app_id을(를) Application ID로 교체하고 your_back4app_client_key을(를) Client Key로 교체하십시오.
2.3) DB 설정
- Back4App “대시보드” -> “코어” -> “데이터베이스 브라우저” -> “클래스 생성”을 열고 Custom 유형의 클래스를 생성하십시오. Message 및 ChatThread;

2.4) 라이브 쿼리 설정
- 애플리케이션에서 서버 설정 버튼을 누르세요.
- “웹 호스팅 및 라이브 쿼리” 블록을 찾으세요.
- 라이브 쿼리 설정을 열고 호스팅 활성화 옵션을 확인하세요.
- 당신이 생성한 2개의 클래스에 대해 라이브 쿼리를 활성화할 서브도메인 이름을 선택하세요: 메시지 및 채팅 스레드.
- 새 서브도메인 이름을 복사하고 저장 버튼을 클릭하세요:

다시 /app/src/main/res/values/strings.xml로 돌아가서 위에 입력한 “서브도메인 이름”을 back4app_live_query_url 대신 “yourSubdomainName”에 붙여넣으세요:
이 단계가 끝나면 Android Studio에서 실행 버튼을 눌러 샘플을 작동시킬 수 있습니다. 에뮬레이터나 실제 장치를 사용하여 테스트해 보세요.
3: 클린 데모 실행
클린 버전의 데모를 실행한 결과를 보려면 다음을 수행해야 합니다:
- 2명의 사용자를 등록하세요;
- 그들 사이에 대화를 시작하고 몇 개의 메시지를 보내세요;

3. Back4App “대시보드” -> “코어” -> “데이터베이스 브라우저” -> “메시지”를 엽니다.
모든 것이 잘 작동했다면, 채팅 메신저 앱이 나타나는 것을 볼 수 있어야 합니다. 두 사용자를 등록하고 서로 몇 개의 메시지를 보내세요: 메시지 클래스에 새로운 데이터가 나타나는 것을 볼 수 있어야 합니다.
서버에서 사용자가 어떤 대화를 나누고 있는지 볼 수 있다는 점에 유의하세요:

다음: 채팅 인터페이스를 닫고 다음 단계로 넘어가세요 – E2EE 암호화 추가.
이제 메시지를 종단 간 암호화해 보겠습니다!
이 부분이 끝날 무렵, 서버에서 채팅 메시지가 이렇게 보일 것입니다: 차이점을 찾을 수 있나요?

어떻게 거기에 도달할 수 있을까요? 분명히, 우리는 종단 간 암호화를 구현해야 하며, 이는 우리의 앱이 다음을 필요로 한다는 것을 의미합니다:
- 회원가입의 일환으로 개인 키와 공개 키 쌍을 생성합니다.
- 사용자의 장치의 키 저장소에 개인 키를 저장합니다.
- 다른 사용자가 다운로드하고 메시지를 암호화할 수 있도록 Virgil의 카드 서비스에 공개 키를 'Virgil 카드'로 게시합니다.
- 공개 키로 메시지를 암호화하고 개인 키로 서명합니다; 개인 키로 메시지를 복호화하고 공개 키로 검증합니다.
이를 위해, 우리는 우리의 깔끔한 데모 애플리케이션에 E3Kit을 추가하고 위에서 설명한 모든 것을 구현하기 위해 추가 코드를 작성해야 합니다.
하지만 시작하기 전에, 두 가지 중요한 용어를 명확히 해보겠습니다: Virgil 카드와 개인 키란 무엇인가요?
- Virgil 카드 - Virgil 카드에는 사용자의 개인 키가 포함되어 있습니다. Virgil 카드는 Virgil의 카드 서비스에 게시됩니다 (이 서비스를 전화번호부와 같다고 상상해 보세요) 다른 사용자가 이를 검색할 수 있도록: 앨리스는 밥을 위해 메시지를 암호화하기 위해 밥의 공개 키를 검색해야 합니다.
- 개인 키 - 암호화 키의 개인 부분입니다. 개인 키는 일치하는 공개 키를 사용하여 암호화된 데이터를 복호화할 수 있습니다.
1: E3Kit을 깔끔한 E3Kit Back4App Kotlin 데모에 추가하기
- 앱 수준에서 (모듈: app) gradle에서 /app/build.gradle 추가하세요 (하지만 gradle 스크립트는 아직 동기화하지 마세요):
- 다음 내용을 프로젝트 수준의 /build.gradle (프로젝트: chat-back4app-android)에 추가하세요:
- 이제 gradle 스크립트를 동기화할 수 있습니다;
- 다음 필드를 추가하여 AppVirgil 클래스를 업데이트하세요:
- 클래스에 필요한 라이브러리를 가져오려면 Alt+ Enter를 누르세요.
2: Back4App Cloud Code로 사용자 인증하기
- 다음 경로에 있는 ../virgilsecurity/virgilback4app/model/ 디렉토리에서 AuthenticateResponse 및 VirgilJwtResponse를 생성하여 Cloud Code 함수의 응답을 나타내세요:
- 다음 경로에 있는 ../virgilsecurity/virgilback4app/util/에서 AuthRx 객체를 생성하여 Cloud Code 함수에 대한 호출을 구현하세요 (필요한 모든 라이브러리를 가져오는 것을 잊지 마세요):
1 object AuthRx {
2
3 /**
4 * You can call it only after successful [authenticate]
5 */
6 fun virgilJwt(sessionToken: String) = Single.create<String> { emitter ->
7 val requestParams = mutableMapOf<String, String>().apply {
8 put("sessionToken", sessionToken)
9 }
10
11 ParseCloud.callFunctionInBackground<Map<String, Any>>(
12 KEY_VIRGIL_JWT,
13 requestParams
14 ) { virgilJwt, exception ->
15 if (exception == null)
16 emitter.onSuccess(virgilJwt[KEY_TOKEN].toString())
17 else
18 emitter.onError(exception)
19
20 }
21 }
22
23 private const val KEY_VIRGIL_JWT = "virgil-jwt"
24 private const val KEY_TOKEN = "token"
25 }3: Virgil JWT를 로컬에 저장하기
Cloud Code 함수에서 받은 Virgil 토큰은 로컬에 저장해야 합니다. Preferences 클래스를 ../virgilsecurity/virgilback4app/util/:에서 업데이트합시다.
- 상수를 정의합니다:
- 함수를 추가합니다 setVirgilToken, virgilToken 및 clearVirgilToken:
~~~kotlin
fun setVirgilToken(virgilToken: String) { with(sharedPreferences.edit()) { putString(KEY_VIRGIL_TOKEN, virgilToken) apply() } }
fun virgilToken(): String? { with(sharedPreferences) { return getString(KEY_VIRGIL_TOKEN, null) } }
fun clearVirgilToken() { with(sharedPreferences.edit()) { remove(KEY_VIRGIL_TOKEN) apply() } }
1 Virgil token should be reset on logout. Let's add `Preferences.instance(this).clearVirgilToken()` line into `initDrawer` function of `ThreadsListActivity` class (in `../virgilsecurity/virgilback4app/chat/contactsList/`):
2 ~~~kotlin
3 private fun initDrawer() {
4 ...
5 nvNavigation.setNavigationItemSelectedListener { item ->
6 R.id.itemLogOut -> {
7 dlDrawer.closeDrawer(GravityCompat.START)
8 presenter.disposeAll()
9 showBaseLoading(true)
10 // New code >>
11 Preferences.instance(this).clearVirgilToken()
12 // << New code
13 ...
14 }
15 }
16 }4: 사용자 등록 수정
E3Kit은 귀하의 개인 키와 공개 키를 관리합니다. 등록 과정에서 이를 생성하기 위해 다음과 같은 작업을 수행해야 합니다:
- 다음 위치에서 ../virgilsecurity/virgilback4app/util/에 RxEthree 클래스를 생성합니다:
- 이제 initEthree 함수를 추가하여 RxEthree 클래스에서 E3Kit 인스턴스를 초기화합니다:
1 import com.virgilsecurity.android.common.model.EThreeParams
2 import com.virgilsecurity.android.ethree.interaction.EThree
3
4
5 fun initEthree(identity: String, verifyPrivateKey: Boolean = false): 6Single<EThree> = Single.create { e ->
6 val params = EThreeParams(identity, {preferences.virgilToken()!!}, context)
7 val ethree = EThree(params)
8 if (verifyPrivateKey) {
9 if (ethree.hasLocalPrivateKey()) {
10 e.onSuccess(ethree)
11 } else {
12 e.onError(KeyEntryNotFoundException())
13 }
14 } else {
15 e.onSuccess(ethree)
16 }
17 }- 새로운 사용자를 registerEthree 클래스에 등록하는 함수를 추가합니다. E3Kit은 가입하는 동안 키 쌍을 생성합니다. 생성된 개인 키는 로컬 저장소에 저장되고, 공개 키는 Virgil Services에 Virgil 카드로 게시됩니다.
1 import com.android.virgilsecurity.virgilback4app.AppVirgil
2 import com.virgilsecurity.common.callback.OnCompleteListener
3 import io.reactivex.Completable
4
5
6 fun registerEthree(): Completable = Completable.create { e ->
7 AppVirgil.eThree.register().addCallback(object : OnCompleteListener {
8 override fun onError(throwable: Throwable) {
9 e.onError(throwable)
10 }
11
12 override fun onSuccess() {
13 e.onComplete()
14 }
15
16 })
17 }- 업데이트를 진행합시다 LogInPresenter 클래스 (in ../virgilsecurity/virgilback4app/auth/).
- 필드를 추가하세요 rxEthree :
1 private val rxEthree = RxEthree(context)다음의 requestSignUp 함수를 업데이트하여 E3Kit으로 등록을 실행하세요.
이제 requestSignIn 메서드에 변경을 가해 보겠습니다 LogInPresenter 클래스 (위치: ../virgilsecurity/virgilback4app/auth/):
1 fun requestSignIn(identity: String,
2 onSuccess: () -> Unit,
3 onError: (Throwable) -> Unit) {
4
5 val password = generatePassword(identity.toByteArray())
6
7 val disposable = RxParse.logIn(identity, password)
8 .subscribeOn(Schedulers.io())
9 .observeOn(Schedulers.io())
10 // New code >>
11 .flatMap { AuthRx.virgilJwt(it.sessionToken) }
12 .map { preferences.setVirgilToken(it) }
13 .flatMap { rxEthree.initEthree(identity, true) }
14 .map { AppVirgil.eThree = it }
15 // << New code
16 .observeOn(AndroidSchedulers.mainThread())
17 // Updated code >>
18 .subscribeBy(
19 onSuccess = {
20 onSuccess()
21 },
22 onError = {
23 onError(it)
24 }
25 )
26 // << Updated code
27
28 compositeDisposable += disposable
29 }6: 기존 채팅 목록 가져오기
다음으로, E3Kit 초기화를 처리하는 함수를 ThreadsListFragment 클래스에 추가합니다 (위치: ../virgilsecurity/virgilback4app/chat/contactsList/):
1 private fun onInitEthreeSuccess() {
2 presenter.requestThreads(ParseUser.getCurrentUser(),
3 20,
4 page,
5 Const.TableNames.CREATED_AT_CRITERIA,
6 ::onGetThreadsSuccess,
7 ::onGetThreadsError)
8 }
9
10 private fun onInitEthreeError(throwable: Throwable) {
11 showProgress(false)
12 if (adapter.itemCount == 0)
13 tvError.visibility = View.VISIBLE
14
15 Utils.toast(activity, Utils.resolveError(throwable))
16 }업데이트 postCreateInit 함수로 E3Kit 초기화:
1 override fun postCreateInit() {
2 ...
3 presenter = ThreadsListFragmentPresenter(activity)
4
5 showProgress(true)
6 // Updated code >>
7 if (AppVirgil.isEthreeInitialized()) {
8 presenter.requestThreads(ParseUser.getCurrentUser(),
9 20,
10 page,
11 Const.TableNames.CREATED_AT_CRITERIA,
12 ::onGetThreadsSuccess,
13 ::onGetThreadsError)
14 } else {
15 presenter.requestEthreeInit(ParseUser.getCurrentUser(), ::onInitEthreeSuccess, ::onInitEthreeError)
16 }
17 // << Updated code
18 }다음 코드를 ThreadsListFragmentPresenter 클래스에 추가하세요 virgilsecurity.virgilback4app.chat.contactsList/:
- 필드 추가:
1 private val rxEthree = RxEthree(context)- 및 함수
1 fun requestEthreeInit(currentUser: ParseUser, onSuccess: () -> Unit, onError: (Throwable) -> Unit) {
2 val disposable = rxEthree.initEthree(currentUser.username)
3 .subscribeOn(Schedulers.io())
4 .observeOn(AndroidSchedulers.mainThread())
5 .subscribeBy(
6 onSuccess = {
7 AppVirgil.eThree = it
8 onSuccess()
9 },
10 onError = {
11 onError(it)
12 }
13 )
14
15 compositeDisposable += disposable
16 }이 시점에서 우리는 사용자를 가입/로그인하고 다른 사용자와 새로운 채팅을 생성할 수 있습니다.
이제 우리의 메시지에 대한 암호화를 추가해 보겠습니다.
7: 메시지 암호화 및 복호화
다음으로 findCard 함수를 RxEthree 클래스에 추가하겠습니다 (위치: ../virgilsecurity/virgilback4app/util/) 이 함수는 사용자 이름으로 최신 Virgil 카드를 가져오는 데 도움이 될 것입니다:
1 fun findCard(identity: String): Single<Card> = Single.create { e ->
2 AppVirgil.eThree.findUser(identity).addCallback(object : OnResultListener<Card> {
3 override fun onError(throwable: Throwable) {
4 e.onError(throwable)
5 }
6
7 override fun onSuccess(result: Card) {
8 e.onSuccess(result)
9 }
10
11 })
12 }채팅이 열리면 수신자의 Virgil 카드 정보를 얻어야 합니다. postCreateInit의 ChatThreadFragment 클래스 ({ ../virgilsecurity/virgilback4app/chat/thread/})를 교체하여
1 presenter.requestMessages(thread,
2 50,
3 page,
4 Const.TableNames.CREATED_AT_CRITERIA,
5 ::onGetMessagesSuccess,
6 ::onGetMessagesError)코드를 새 코드로 교체합니다.
1 presenter.requestCard(recipientId,
2 ::onGetCardSuccess,
3 ::onGetCardError)두 개의 함수를 추가하세요:
1 private fun onGetCardSuccess(card: Card) {
2 showProgress(false)
3 adapter.interlocutorCard = card
4 presenter.requestMessages(thread,
5 50,
6 page,
7 Const.TableNames.CREATED_AT_CRITERIA,
8 ::onGetMessagesSuccess,
9 ::onGetMessagesError)
10 }
11
12 private fun onGetCardError(t: Throwable) {
13 if (t is VirgilCardIsNotFoundException || t is VirgilCardServiceException) {
14 Utils.toast(this,
15 "Virgil Card is not found.\nYou can not chat with user without Virgil Card")
16 activity.onBackPressed()
17 }
18 showProgress(false)
19 srlRefresh.isRefreshing = false
20 lockSendUi(lock = false, lockInput = false)
21
22 Utils.toast(this, Utils.resolveError(t))
23 }이제 ChatThreadPresenter:
- 필드를 추가하세요:
1 private val eThree = AppVirgil.eThree
2 private lateinit var userCard: Card
3 private val rxEthree = RxEthree(context)- 수신자의 Virgil 카드를 얻는 함수를 추가하세요:
1 fun requestCard(identity: String,
2 onSuccess: (Card) -> Unit,
3 onError: (Throwable) -> Unit) {
4
5 val disposable = rxEthree.findCard(identity)
6 .subscribeOn(Schedulers.io())
7 .observeOn(AndroidSchedulers.mainThread())
8 .subscribeBy(
9 onSuccess = {
10 userCard = it
11 onSuccess(it)
12 },
13 onError = {
14 onError(it)
15 }
16 )
17
18 compositeDisposable += disposable
19 }- 전송되는 메시지의 암호화를 추가하세요 requestSendMessage 함수에:
1 fun requestSendMessage(text: String,
2 thread: ChatThread,
3 onSuccess: () -> Unit,
4 onError: (Throwable) -> Unit) {
5
6 val encryptedText = eThree.authEncrypt(text, userCard)
7 val disposable = RxParse.sendMessage(encryptedText, thread)
8 ...
9 }모든 수신 메시지의 복호화를 추가하세요 ChatThreadRVAdapter 클래스에 (위치: ../virgilsecurity/virgilback4app/chat/thread/):
- 필드를 추가하세요:
1 private var eThree: EThree = AppVirgil.eThree
2 lateinit var interlocutorCard: Card- 메시지 복호화 구현 onBindViewHolder 함수에서
1 override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
2 when (viewHolder) {
3 is HolderMessageMe -> {
4 val decryptedText = eThree.authDecrypt(items[position].body)
5 viewHolder.bind(decryptedText)
6 }
7 is HolderMessageYou -> {
8 val decryptedText = eThree.authDecrypt(items[position].body, interlocutorCard)
9 viewHolder.bind(decryptedText)
10 }
11 }
12 }8: 전체 종단 간 암호화 데모 실행
이제 완전한 종단 간 암호화 데모의 결과를 보려면, 다시 이 단계를 진행하세요:
- 이전 사용자 로그아웃
- 2명의 새로운 사용자 등록;
- 그들 간의 대화를 시작하고 몇 개의 메시지를 보내세요;
- Back4App “대시보드” -> “코어” -> “데이터베이스 브라우저” -> “메시지”를 엽니다.
중요! 현재 사용자를 로그아웃 하고 두 명의 새로운 사용자를 등록해야 합니다. 그 후에 이 두 명의 새로운 사용자와 E2EE 채팅을 시작할 수 있습니다. 이유는 첫 번째 두 사용자가 Virgil 카드가 없기 때문에 그들에 대해 암호화\복호화를 사용할 수 없습니다.{: .blockquote-tip}
완료! 이제 사용자의 메시지가 암호화되어 있으며, 앱 내에서 사용자 자신만 접근할 수 있음을 알 수 있습니다.
HIPAA 및 GDPR 준수:
종단 간 암호화는 HIPAA(1996년 미국 건강 보험 이동성 및 책임법) 및 GDPR(유럽 연합 일반 데이터 보호 규정)의 기술적 요구 사항을 충족하는 방법입니다. 더 자세한 정보가 필요하면 무료로 Virgil 계정, 우리의 Slack 커뮤니티에 가입하고 그곳에서 문의하세요: 우리는 귀하의 개인 정보 상황에 대해 논의하고 HIPAA 및 GDPR 기술적 요구 사항을 충족하는 데 필요한 사항을 이해하는 데 도움을 드릴 수 있습니다.
이제 어디로 가야 할까요?
최종 프로젝트. 퍼즐의 일부를 놓쳤다면 E2EE 프로젝트 브랜치를 열어보세요. 이 코드에 귀하의 애플리케이션 자격 증명을 삽입할 수 있으며(기사에서 했던 것처럼) 프로젝트를 빌드할 수 있습니다.
Virgil Security로 구축할 수 있는 것에 대한 더 많은 정보를 여기에서 찾을 수 있습니다.