서명 검증
서명 검증 (Signature Verification)
출처: Caddy 공식 문서
본문
아티팩트 서명(artifact signing)을 사용하면 여러분이 가진 아티팩트가 프로젝트의 워크플로우가 만든 것과 동일하며 승인되지 않은 당사자(예: 중간자 공격)에 의해 수정되지 않았음을 검증할 수 있어요. 검증은 모든 당사자가 실행 파일이든 SBOM이든 텍스트 파일이든 동일한 아티팩트, 동일한 바이트 모음을 참조하고 있다는 공통 근거, 보증, 그리고 지식을 제공해요.
Caddy v2.6.0부터 CI/CD 릴리스 아티팩트는 프로젝트 Sigstore 기술로 서명되며, 이는 인증서가 발급된 대상에 대한 세부 정보를 담은 인증서를 발급해요. 선택한 아티팩트를 서명하는 데 사용된 인증서를 검사하는 것부터 시작할 수 있어요. 인증서는 base64로 인코딩되어 있으므로 먼저 base64로 디코딩해 PEM 파일을 얻어야 해요. 이 예제에서는 caddy_2.6.0_checksums.txt 아티팩트로 작업하고 Linux 계열 환경을 가정할게요.
선택한 아티팩트와 관련된 3개 파일을 다운로드하는 것으로 시작해요(즉, 검증할 실제 아티팩트인 <the artifact>, 아티팩트의 서명인 <the artifact>.sig, Sigstore가 Fulcio로 루트 인증서에서 파생한 인증서인 <the artifact>.pem). 그런 다음 다운로드한 .pem 파일을 base64 디코딩해 armored 버전으로 만들어요:
base64 -d < caddy_2.6.0_checksums.txt.pem > cert.pem
이제 openssl 명령으로 인증서를 검사할 수 있어요. 방금 디코딩한 인증서에 openssl x509 -in cert.pem -text를 실행하면 이런 출력이 잘려 나와요:
openssl x509 -in cert.pem -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
22:b0:45:9d:ad:d7:54:98:67:66:b7:de:31:01:ef:4a:02:ab:fb:60
Signature Algorithm: ecdsa-with-SHA384
Issuer: O=sigstore.dev, CN=sigstore-intermediate
Validity
Not Before: Sep 20 17:17:06 2022 GMT
Not After : Sep 20 17:27:06 2022 GMT
Subject:
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:22:ee:f6:b1:85:1c:de:cf:90:1d:91:75:36:c4:
82:9d:54:5e:f3:a6:5b:3f:18:89:8a:0b:de:d8:93:
7c:02:40:39:00:d4:4e:19:0b:30:93:cc:a4:d0:df:
35:f7:b1:08:24:89:cf:3a:38:06:ff:92:75:06:84:
b5:9e:25:8c:9a
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
Code Signing
X509v3 Subject Key Identifier:
3B:C0:D1:D2:C8:BA:2D:55:95:1F:68:78:DC:C6:2C:D9:B5:17:0E:EA
X509v3 Authority Key Identifier:
keyid:DF:D3:E9:CF:56:24:11:96:F9:A8:D8:E9:28:55:A2:C6:2E:18:64:3F
X509v3 Subject Alternative Name: critical
URI:https://github.com/caddyserver/caddy/.github/workflows/release.yml@refs/tags/v2.6.0
1.3.6.1.4.1.57264.1.1:
https://token.actions.githubusercontent.com
1.3.6.1.4.1.57264.1.2:
push
1.3.6.1.4.1.57264.1.3:
821a08a6e39ed0e7c43b0271ccf126c194eb6339
1.3.6.1.4.1.57264.1.4:
Release
1.3.6.1.4.1.57264.1.5:
caddyserver/caddy
1.3.6.1.4.1.57264.1.6:
refs/tags/v2.6.0
1.3.6.1.4.1.11129.2.4.2:
.z.x.v..`..(R.hE..k'..Eg...=.8.m..".6or....[.DS.....G0E.!..>MD.a..B.p..^..P*...um.....X..F. NYy.....#...TWIZ...y..qa....4P..
Signature Algorithm: ecdsa-with-SHA384
30:66:02:31:00:be:b3:3c:15:56:78:64:c6:0f:bc:48:69:a9:
0a:27:cd:4d:92:39:00:50:42:a8:2a:ad:11:4d:64:f2:61:35:
ec:08:e9:b5:6a:14:1b:f6:c1:0e:46:ee:a0:54:08:26:e1:02:
31:00:a7:6d:97:db:4c:c8:dd:47:13:3d:28:7a:a6:f3:64:50:
2c:5a:9d:9d:10:d0:cf:6f:d0:e9:37:76:fd:cc:8e:9d:c3:6b:
ba:78:07:40:6a:40:d6:db:f6:97:d5:6a:36:9d
-----BEGIN CERTIFICATE-----
MIIDlDCCAxmgAwIBAgIUIrBFna3XVJhnZrfeMQHvSgKr+2AwCgYIKoZIzj0EAwMw
NzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRl
cm1lZGlhdGUwHhcNMjIwOTIwMTcxNzA2WhcNMjIwOTIwMTcyNzA2WjAAMFkwEwYH
KoZIzj0CAQYIKoZIzj0DAQcDQgAEIu72sYUc3s+QHZF1NsSCnVRe86ZbPxiJigve
2JN8AkA5ANROGQswk8yk0N8197EIJInPOjgG/5J1BoS1niWMmqOCAjgwggI0MA4G
A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUO8DR
0si6LVWVH2h43MYs2bUXDuowHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4Y
ZD8wYQYDVR0RAQH/BFcwVYZTaHR0cHM6Ly9naXRodWIuY29tL2NhZGR5c2VydmVy
L2NhZGR5Ly5naXRodWIvd29ya2Zsb3dzL3JlbGVhc2UueW1sQHJlZnMvdGFncy92
Mi42LjAwOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1
YnVzZXJjb250ZW50LmNvbTASBgorBgEEAYO/MAECBARwdXNoMDYGCisGAQQBg78w
AQMEKDgyMWEwOGE2ZTM5ZWQwZTdjNDNiMDI3MWNjZjEyNmMxOTRlYjYzMzkwFQYK
KwYBBAGDvzABBAQHUmVsZWFzZTAfBgorBgEEAYO/MAEFBBFjYWRkeXNlcnZlci9j
YWRkeTAeBgorBgEEAYO/MAEGBBByZWZzL3RhZ3MvdjIuNi4wMIGKBgorBgEEAdZ5
AgQCBHwEegB4AHYACGCS8ChS/2hF0dFrJ4ScRWcYrBY9wzjSbea8IgY2b3IAAAGD
W+dEUwAABAMARzBFAiEAnD5NRKZhFLhCHHDIzV6bwVAqlYP6dW0CwKWDo1jzmEYC
IE5ZeeK14oi6I+7z2VRXSVq4/r15GAFxYaCMFrI0UOjjMAoGCCqGSM49BAMDA2kA
MGYCMQC+szwVVnhkxg+8SGmpCifNTZI5AFBCqCqtEU1k8mE17AjptWoUG/bBDkbu
oFQIJuECMQCnbZfbTMjdRxM9KHqm82RQLFqdnRDQz2/Q6Td2/cyOncNrungHQGpA
1tv2l9VqNp0=
-----END CERTIFICATE-----
인증서의 명시된 의도된 용도가 Code Signing임을 주목하세요. 인증서는 또한 X509v3 Subject Alternative Name 확장에 트리거된 Github Actions 워크플로우의 URI, 1.3.6.1.4.1.57264.1.4에 GHA 워크플로우 이름, 1.3.6.1.4.1.57264.1.3에 서명할 커밋, 1.3.6.1.4.1.57264.1.5에 저장소 이름, 1.3.6.1.4.1.57264.1.6에 트리거한 ref를 포함해요. 이 세부 사항들은 함께 우주에서 인증서를 사용할 단일 이벤트를 정확히 짚어줘요.
이제 인증서가 있으므로 cosign CLI를 사용해 서명을 검증할 수 있어요. 다음 명령을 실행해요(디코딩되지 않은 인증서를 사용한다는 점에 주목하세요):
COSIGN_EXPERIMENTAL=1 cosign verify-blob --certificate ./caddy_2.6.0_checksums.txt.pem --signature ./caddy_2.6.0_checksums.txt.sig ./caddy_2.6.0_checksums.txt
tlog entry verified with uuid: 04deb84e5a73ba75ea69092c6d700eaeb869c29cae3e0cf98dbfef871361ed09 index: 3618623
Verified OK
이제 CLI 도구를 바꿔서 투명성 로그를 저장하는 공개 Rekor 서버와 상호작용하는 rekor-cli를 사용해볼게요. 실행해요:
rekor-cli get --uuid 04deb84e5a73ba75ea69092c6d700eaeb869c29cae3e0cf98dbfef871361ed09 --format json | jq -r '.'
jq는 출력을 보기 좋게 하기 위한 것이에요. 이런 출력이 보일 거예요:
{
"Attestation": "",
"AttestationType": "",
"Body": {
"HashedRekordObj": {
"data": {
"hash": {
"algorithm": "sha256",
"value": "508f1044ecd9f14c43c6c8986b45b90fc79f25736e2bc85c0911433ce82533f2"
}
},
"signature": {
"content": "MEUCIHGL2HP5XzcUESTxIk72FS1aNK54LesTfyo+dVhRMeduAiEAnWZDZ5Ur44Y9056vr4to2Fb9FteG53eAFotv3fUZ4h4=",
"publicKey": {
"content": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURsRENDQXhtZ0F3SUJBZ0lVSXJCRm5hM1hWSmhuWnJmZU1RSHZTZ0tyKzJBd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpJd09USXdNVGN4TnpBMldoY05Nakl3T1RJd01UY3lOekEyV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVJdTcyc1lVYzNzK1FIWkYxTnNTQ25WUmU4NlpiUHhpSmlndmUKMkpOOEFrQTVBTlJPR1Fzd2s4eWswTjgxOTdFSUpJblBPamdHLzVKMUJvUzFuaVdNbXFPQ0FqZ3dnZ0kwTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVPOERSCjBzaTZMVldWSDJoNDNNWXMyYlVYRHVvd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d1lRWURWUjBSQVFIL0JGY3dWWVpUYUhSMGNITTZMeTluYVhSb2RXSXVZMjl0TDJOaFpHUjVjMlZ5ZG1WeQpMMk5oWkdSNUx5NW5hWFJvZFdJdmQyOXlhMlpzYjNkekwzSmxiR1ZoYzJVdWVXMXNRSEpsWm5NdmRHRm5jeTkyCk1pNDJMakF3T1FZS0t3WUJCQUdEdnpBQkFRUXJhSFIwY0hNNkx5OTBiMnRsYmk1aFkzUnBiMjV6TG1kcGRHaDEKWW5WelpYSmpiMjUwWlc1MExtTnZiVEFTQmdvckJnRUVBWU8vTUFFQ0JBUndkWE5vTURZR0Npc0dBUVFCZzc4dwpBUU1FS0RneU1XRXdPR0UyWlRNNVpXUXdaVGRqTkROaU1ESTNNV05qWmpFeU5tTXhPVFJsWWpZek16a3dGUVlLCkt3WUJCQUdEdnpBQkJBUUhVbVZzWldGelpUQWZCZ29yQmdFRUFZTy9NQUVGQkJGallXUmtlWE5sY25abGNpOWoKWVdSa2VUQWVCZ29yQmdFRUFZTy9NQUVHQkJCeVpXWnpMM1JoWjNNdmRqSXVOaTR3TUlHS0Jnb3JCZ0VFQWRaNQpBZ1FDQkh3RWVnQjRBSFlBQ0dDUzhDaFMvMmhGMGRGcko0U2NSV2NZckJZOXd6alNiZWE4SWdZMmIzSUFBQUdEClcrZEVVd0FBQkFNQVJ6QkZBaUVBbkQ1TlJLWmhGTGhDSEhESXpWNmJ3VkFxbFlQNmRXMEN3S1dEbzFqem1FWUMKSUU1WmVlSzE0b2k2SSs3ejJWUlhTVnE0L3IxNUdBRnhZYUNNRnJJMFVPampNQW9HQ0NxR1NNNDlCQU1EQTJrQQpNR1lDTVFDK3N6d1ZWbmhreGcrOFNHbXBDaWZOVFpJNUFGQkNxQ3F0RVUxazhtRTE3QWpwdFdvVUcvYkJEa2J1Cm9GUUlKdUVDTVFDbmJaZmJUTWpkUnhNOUtIcW04MlJRTEZxZG5SRFF6Mi9RNlRkMi9jeU9uY05ydW5nSFFHcEEKMXR2Mmw5VnFOcDA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
}
}
},
"LogIndex": 3618623,
"IntegratedTime": 1663694226,
"UUID": "04deb84e5a73ba75ea69092c6d700eaeb869c29cae3e0cf98dbfef871361ed09",
"LogID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
}
.Body.HashedRekordObj.signature.content의 값이 우리 CI에서 생성되어 caddy_2.6.0_checksums.txt.sig 파일에 있는 서명의 내용과 일치함을 주목하세요. 게다가 사용되고 다운로드된 인증서도 Rekor 서버에 저장되어 있고 응답의 .Body.HashedRekordObj.signature.publicKey.content에서 확인할 수 있으며 caddy_2.6.0_checksums.txt.pem 파일에 있는 문자열과 일치해요. 한 걸음 더 나아가 .Body.HashedRekordObj.data.hash.value가 sha256sum ./caddy_2.6.0_checksums.txt 명령의 출력과 일치하는지 확인할 수 있어요. 이제 일치하는 인증서, 일치하는 서명, 일치하는 체크섬(아카이브의 체크섬을 포함하는 파일이지만 그 자체는 아닌 파일의; 이 체크섬은 Sigstore 생태계를 통해 외부적으로 제공되고 기록됨)을 갖게 됐어요. 이 모든 것은 일반 대중이 검증할 수 있도록 투명성 로그에 공개적으로 기록돼요.
아티팩트의 진위 검증하기
Caddy 프로젝트의 산물이라고 주장되는 아티팩트를 받았는데 서명 파일이나 인증서가 주어지지 않았다면 어떻게 해야 할까요? rekor-cli를 사용해 Rekor 서버에서 해당 아티팩트를 조회할 수 있어요:
rekor-cli search --artifact ./caddy_2.6.0_checksums.txt --format json | jq -r '.UUIDs[0]'
Found matching entries (listed by UUID):
362f8ecba72f432604deb84e5a73ba75ea69092c6d700eaeb869c29cae3e0cf98dbfef871361ed09
UUID가 앞 섹션에서 같은 파일에 대해 만났던 것과 일치함을 주목하세요. 앞 섹션에서 했던 것처럼 Rekor에 이 UUID의 항목 세부 정보를 조회할 수 있어요:
rekor-cli get --uuid 04deb84e5a73ba75ea69092c6d700eaeb869c29cae3e0cf98dbfef871361ed09 --format json | jq -r '.'
하지만 이 한 줄로 두 개의 별도 명령을 병합해 조회를 단축할 수 있어요:
rekor-cli get --uuid $(rekor-cli search --artifact ./caddy_2.6.0_checksums.txt --format json | jq -r '.UUIDs[0]') --format json | jq -r '.'
{
"Attestation": "",
"AttestationType": "",
"Body": {
"HashedRekordObj": {
"data": {
"hash": {
"algorithm": "sha256",
"value": "508f1044ecd9f14c43c6c8986b45b90fc79f25736e2bc85c0911433ce82533f2"
}
},
"signature": {
"content": "MEUCIHGL2HP5XzcUESTxIk72FS1aNK54LesTfyo+dVhRMeduAiEAnWZDZ5Ur44Y9056vr4to2Fb9FteG53eAFotv3fUZ4h4=",
"publicKey": {
"content": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURsRENDQXhtZ0F3SUJBZ0lVSXJCRm5hM1hWSmhuWnJmZU1RSHZTZ0tyKzJBd0NnWUlLb1pJemowRUF3TXcKTnpFVk1CTUdBMVVFQ2hNTWMybG5jM1J2Y21VdVpHVjJNUjR3SEFZRFZRUURFeFZ6YVdkemRHOXlaUzFwYm5SbApjbTFsWkdsaGRHVXdIaGNOTWpJd09USXdNVGN4TnpBMldoY05Nakl3T1RJd01UY3lOekEyV2pBQU1Ga3dFd1lICktvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVJdTcyc1lVYzNzK1FIWkYxTnNTQ25WUmU4NlpiUHhpSmlndmUKMkpOOEFrQTVBTlJPR1Fzd2s4eWswTjgxOTdFSUpJblBPamdHLzVKMUJvUzFuaVdNbXFPQ0FqZ3dnZ0kwTUE0RwpBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVPOERSCjBzaTZMVldWSDJoNDNNWXMyYlVYRHVvd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFkKWkQ4d1lRWURWUjBSQVFIL0JGY3dWWVpUYUhSMGNITTZMeTluYVhSb2RXSXVZMjl0TDJOaFpHUjVjMlZ5ZG1WeQpMMk5oWkdSNUx5NW5hWFJvZFdJdmQyOXlhMlpzYjNkekwzSmxiR1ZoYzJVdWVXMXNRSEpsWm5NdmRHRm5jeTkyCk1pNDJMakF3T1FZS0t3WUJCQUdEdnpBQkFRUXJhSFIwY0hNNkx5OTBiMnRsYmk1aFkzUnBiMjV6TG1kcGRHaDEKWW5WelpYSmpiMjUwWlc1MExtTnZiVEFTQmdvckJnRUVBWU8vTUFFQ0JBUndkWE5vTURZR0Npc0dBUVFCZzc4dwpBUU1FS0RneU1XRXdPR0UyWlRNNVpXUXdaVGRqTkROaU1ESTNNV05qWmpFeU5tTXhPVFJsWWpZek16a3dGUVlLCkt3WUJCQUdEdnpBQkJBUUhVbVZzWldGelpUQWZCZ29yQmdFRUFZTy9NQUVGQkJGallXUmtlWE5sY25abGNpOWoKWVdSa2VUQWVCZ29yQmdFRUFZTy9NQUVHQkJCeVpXWnpMM1JoWjNNdmRqSXVOaTR3TUlHS0Jnb3JCZ0VFQWRaNQpBZ1FDQkh3RWVnQjRBSFlBQ0dDUzhDaFMvMmhGMGRGcko0U2NSV2NZckJZOXd6alNiZWE4SWdZMmIzSUFBQUdEClcrZEVVd0FBQkFNQVJ6QkZBaUVBbkQ1TlJLWmhGTGhDSEhESXpWNmJ3VkFxbFlQNmRXMEN3S1dEbzFqem1FWUMKSUU1WmVlSzE0b2k2SSs3ejJWUlhTVnE0L3IxNUdBRnhZYUNNRnJJMFVPampNQW9HQ0NxR1NNNDlCQU1EQTJrQQpNR1lDTVFDK3N6d1ZWbmhreGcrOFNHbXBDaWZOVFpJNUFGQkNxQ3F0RVUxazhtRTE3QWpwdFdvVUcvYkJEa2J1Cm9GUUlKdUVDTVFDbmJaZmJUTWpkUnhNOUtIcW04MlJRTEZxZG5SRFF6Mi9RNlRkMi9jeU9uY05ydW5nSFFHcEEKMXR2Mmw5VnFOcDA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
}
}
}
},
"LogIndex": 3618623,
"IntegratedTime": 1663694226,
"UUID": "04deb84e5a73ba75ea69092c6d700eaeb869c29cae3e0cf98dbfef871361ed09",
"LogID": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
}
이제 아티팩트가 서명되었고 그 서명이 Rekor 투명성 로그 서버에 기록되었음을 알 수 있어요. 다음 단계는 서명과 아티팩트가 Caddy 프로젝트의 CI/CD 워크플로우의 산물임을 검증하는 것이에요. Rekor를 조회해 받은 JSON에서 공개 키를 추출하고, base64 디코딩해 PEM 파일로 만든 다음 openssl로 인증서를 검사하면 돼요. 이전에 받은 Rekor 응답에서 인증서를 추출하고 base64 디코딩해 파일에 저장하는 다음 명령을 실행하세요.
rekor-cli get --uuid $(rekor-cli search --artifact ./caddy_2.6.0_checksums.txt --format json | jq -r '.UUIDs[0]') --format json | jq -r '.Body.HashedRekordObj.signature.publicKey.content' | base64 -d > cert.pem
이제 openssl로 인증서를 검사하고 X509v3 extensions 섹션에 주목하세요.
openssl x509 -in cert.pem -text
Certificate:
...
Issuer: O=sigstore.dev, CN=sigstore-intermediate
...
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
Code Signing
X509v3 Subject Key Identifier:
3B:C0:D1:D2:C8:BA:2D:55:95:1F:68:78:DC:C6:2C:D9:B5:17:0E:EA
X509v3 Authority Key Identifier:
keyid:DF:D3:E9:CF:56:24:11:96:F9:A8:D8:E9:28:55:A2:C6:2E:18:64:3F
X509v3 Subject Alternative Name: critical
URI:https://github.com/caddyserver/caddy/.github/workflows/release.yml@refs/tags/v2.6.0
1.3.6.1.4.1.57264.1.1:
https://token.actions.githubusercontent.com
1.3.6.1.4.1.57264.1.2:
push
1.3.6.1.4.1.57264.1.3:
821a08a6e39ed0e7c43b0271ccf126c194eb6339
1.3.6.1.4.1.57264.1.4:
Release
1.3.6.1.4.1.57264.1.5:
caddyserver/caddy
1.3.6.1.4.1.57264.1.6:
refs/tags/v2.6.0
1.3.6.1.4.1.11129.2.4.2:
.z.x.v..`..(R.hE..k'..Eg...=.8.m..".6or....[.DS.....G0E.!..>MD.a..B.p..^..P*...um.....X..F. NYy.....#...TWIZ...y..qa....4P..
...
확장 값은 아티팩트의 진위를 나타내요. 각 확장의 정의는 Sigstore OID 정보를 참조하세요.
서명이 검증되지 않는다면?
서명 검증 실패는 가진 아티팩트가 GitHub에서의 Caddy 프로젝트의 CI/CD 워크플로우에 의해 생성된 것이 아님을 나타내요. 서명, 인증서, 아티팩트가 있다면 cosign이 보고하는 성공적인 검증을 찾고 있단 뜻이에요. 혹은 rekor-cli를 사용해 Rekor 서버에서 항목을 검사하고, 인증서 확장이 올바르고 기대되는 값인지 검증하고, 체크섬과 서명을 일치시킬 수 있어요. 불일치하거나 Rekor 항목이 없다는 것은 아티팩트가 Caddy 프로젝트의 CI/CD에 의해 생성되지 않았거나, CI/CD 빌드 흐름과 GitHub 릴리스 페이지, 그리고 여러분에게 전달되는 사이 어딘가에서 아티팩트가 변조되었음을 의미해요.