AMP 문서는 암호화된 키를 자체적으로 저장하며 암호화된 문서를 디코딩하는 키로 디커플링을 방지합니다.
작동 원리
AMP는 사용자 랜딩 문서에서 암호화된 콘텐츠의 키를 파싱합니다.
프리미엄 콘텐츠를 제공하는 동안 AMP는 사용자 자격 정보 가져오기의 일환으로 문서에서 암호화된 대칭 키를 권한 부여자에게 전달합니다.
권한 부여자는 사용자에게 올바른 권한이 있는지 확인합니다. 권한이 있는 경우 권한 부여자는 공개/개인 키 쌍에서 권한 부여자의 개인 키를 사용하여 문서의 대칭 키를 복호화합니다. 다음으로 권한 부여자는 amp-subscriptions 컴포넌트 로직에 문서 키를 반환합니다.
AMP는 해당 문서 키를 사용해 프리미엄 콘텐츠를 복호화하고 사용자에게 표시합니다!
구현 절차
아래 절차를 따라 내부 자격 정보 서버와 AMP 암호화 처리를 통합할 수 있습니다.
1단계: 공개/개인 키 쌍 생성
문서의 대칭 키를 암호화하려면 고유한 공개/개인 키 쌍이 필요합니다. 공개 키 암호화는 하이브리드 암호화 프로토콜, 구체적으로는 AES-GCM(128 비트) 대칭 암호화 방식을 사용하는 P-256 타원 곡선 ECIES 비대칭 암호화 방식입니다.
공개 키 처리는 비대칭 키 유형을 활용하여 Tink를 통해 수행되어야 합니다. 고유한 개인-공개 키 쌍을 생성하려면 다음 방식 중 하나를 따릅니다.
두 방식 모두 키 순환을 지원합니다. 키 순환 구현은 손상된 개인 키의 취약점을 제한합니다.
비대칭 키 생성을 시작하는 데 도움을 드리고자 이 스크립트가 제작되었습니다. 해당 스크립트는,
AEAD 키가 포함된 신규 ECIES를 생성합니다.
출력 파일에 일반 텍스트로 공개 키를 출력합니다.
출력 파일에 일반 텍스트로 개인 키를 출력합니다.
출력 파일에 작성하기 전 Google Cloud(GCP)에서 호스팅된 키를 사용하여 생성된 개인 키를 암호화합니다(일반적으로 봉투 암호화라고 부르는 방식).
공개 Tink Keyset를 JSON 형식으로 저장/게시해야 다른 AMP 제공 도구가 원활히 작동할 수 있습니다. AMP 스크립트는 이미 해당 형식으로 공개 키를 출력합니다.
2단계: 게시물 암호화
프리미엄 콘텐츠의 암호화 방식을 수동 또는 자동 중 선택해야 합니다.
수동 암호화
프리미엄 콘텐츠 암호화에는 Tink를 사용하는 AES-GCM 128 대칭 방식이 필요합니다. 프리미엄 콘텐츠 암호화 시 사용되는 대칭 문서 키는 문서별로 고유해야 합니다. Base64로 인코딩한 일반 텍스트 및 문서의 암호화된 콘텐츠 액세스에 필요한 SKU에서 키를 포함하는 JSON 객체로 문서 키를 추가합니다.
하단의 JSON 객체에는 Base64로 인코딩한 일반 텍스트 및 SKU 키 예시가 포함되어 있습니다.
'공개/개인 키 쌍 생성'에서 생성된 공개 키를 사용해 상단의 JSON 객체를 암호화합니다.
암호화 결과를 "local" 키에 값으로 추가합니다. <script type="application/json" cryptokeys=""> 태그로 감싼 JSON 객체에 키-값 쌍을 배치합니다. 문서 헤드에 태그를 배치합니다.
<head>
...
<scripttype="application/json"cryptokeys="">
{
"local": ['y0^r$t^ff'], // This is for your environment
"google.com": ['g00g|e$t^ff'], // This is for Google's environment
}
</script>
…
</head>
로컬 환경과 Google의 공개 키를 사용하여 문서 키를 암호화해야 합니다. Google의 공개 키를 포함하면 Google AMP 캐시가 문서를 제공 할 수 있습니다. URL에서 Google 공개 키를 허용하려면 Tink Keyset 인스턴스화가 필요합니다.
스크립트를 사용해 문서를 암호화합니다. 해당 스크립트는 HTML 문서를 허용하고 <section subscriptions-section="content" encrypted> 태그의 모든 콘텐츠를 암호화합니다. 스크립트는 전달된 URL에 위치한 공개 키를 사용하여 스크립트로 생성된 문서 키를 암호화합니다. 이 스크립트를 사용하면 콘텐츠를 제공할 수 있도록 모든 콘텐츠가 적절히 암호화 및 서식 지정됩니다. 스크립트 사용과 관련한 자세한 지침은 여기에서 확인하실 수 있습니다.
3단계: 권한 부여자 통합
사용자의 자격 정보가 적절한 경우 문서 키 복호화를 수행하려면 권한 부여자 업데이트가 필요합니다. amp-subscriptions 컴포넌트는 “crypt=” URL 매개변수를 통해 암호화된 문서 키를 "local" 권한 부여자에게 자동으로 전송합니다. 기능은 다음과 같습니다.
"local" JSON 키 필드의 문서 키 파싱.
문서 복호화.
권한 부여자의 문서 키를 복호화하려면 Tink를 사용해야 합니다. '공개/개인 키 쌍 생성' 섹션에서 생성된 개인 키를 사용해 HybridDecrypt 클라이언트를 인스턴스화합니다. 성능 최적화를 위해 이 절차를 서버 시작 시 수행하세요.
HybridDecrypt/Authorizer 배포는 키 순환 일정과 대략적으로 일치해야 HybridDecrypt 클라이언트에서 생성된 모든 키를 사용할 수 잇습니다.
Tink는 C++, Java, Go 및 Javascript로 작성된 방대한 문서 및 예제를 보유하여 서버 측 구현을 시작하는 데 도움이 됩니다.
요청 관리
권한 부여자에 요청이 전송된 경우,
“crypt=” 매개변수의 자격 정보 핑백 URL을 파싱합니다.
Base64로 "crypt=” 매개변수 값을 디코딩합니다. URL 매개변수에 저장된 값은 Base64로 인코딩한 암호화 JSON 객체입니다.
암호화된 키가 원시 바이트 형식일 경우 개인 키를 통해 키를 복호화하는 HybridDecrypt 복호화 기능을 사용합니다.
복호화를 성공적으로 마치면 그 결과를 JSON 객체로 파싱합니다.
AccessRequirements JSON 필드에 열거된 자격 정보에 대한 사용자 액세스를 검증합니다.
자격 정보 응답의 복호화된 JSON 객체 "키" 필드의 문서 키를 반환합니다. 자격 정보 응답에서 “decryptedDocumentKey”로 지정된 새 필드에 복호화된 문서 키를 추가하면 AMP 프레임워크 액세스 권한이 부여됩니다.
아래 예시는 의사 코드 조각으로 상단의 설명된 단계를 요약하여 보여줍니다.
stringdecryptDocumentKey(stringencryptedKey,List<string>usersEntitlements,HybridDecrypthybridDecrypter){// 1. Base64 decode the input encrypted key.bytesencryptedKeyBytes=base64.decode(encryptedKey);// 2. Try to decrypt the encrypted key.bytesdecryptedKeyBytes;try{decryptedKeyBytes=hybridDecrypter.decrypt(encryptedKeyBytes,null/* contextInfo */);}catch(errore){// Decryption error occurred. Handle it how you want.LOG("Error occurred decrypting: ",e);return"";}// 3. Parse the decrypted text into a JSON object.stringdecryptedKey=newstring(decryptedKeyBytes,UTF_8);json::objectdecryptedParsedJson=JsonParser.parse(decryptedKey);// 4. Check to see if the requesting user has the entitlements specified in// the AccessRequirements section of the JSON object.for(entitlementinusersEntitlements){if(decryptedParsedJson["AccessRequirements"].contains(entitlement)){// 5. Return the document key if the user has entitlements.returndecryptedParsedJson["Key"];}}// User doesn't have correct requirements, return empty string.return"";}JsonResponsegetEntitlements(stringrequestUri){// Do normal handling of entitlements here…List<string>usersEntitlements=getUsersEntitlementInfo();// Check if request URI has "crypt" parameter.StringdocumentCrypt=requestUri.getQueryParameters().getFirst("crypt");// If URI has "crypt" param, try to decrypt it.stringdocumentKey;if(documentCrypt!=null){documentKey=decryptDocumentKey(documentCrypt,usersEntitlements,this.hybridDecrypter_);}// Construct JSON response.JsonResponseresponse=JsonResponse{signedEntitlements:getSignedEntitlements(),isReadyToPay:getIsReadyToPay(),};if(!documentKey.empty()){response.decryptedDocumentKey=documentKey;}returnresponse;}
We use cookies to understand how you use our site and to improve your experience. By continuing to use our site, you accept our use of cookies and privacy policy.