RFC 8949 CBOR 2020년 12월
Bormann & Hoffman 표준 트랙 [페이지]
스트림:
인터넷 엔지니어링 태스크 포스(IETF)
RFC:
8949
STD:
94
폐기 대상:
7049
분류:
표준 트랙
발행:
ISSN:
2070-1721
저자:
C. Bormann
Universität Bremen TZI
P. Hoffman
ICANN

RFC 8949

간결한 이진 객체 표현(CBOR)

초록

간결한 이진 객체 표현(CBOR)은 설계 목표에 극히 작은 코드 크기, 비교적 작은 메시지 크기 및 버전 협상 없이도 확장할 수 있는 가능성이 포함되는 데이터 형식입니다. 이러한 설계 목표는 ASN.1 및 MessagePack과 같은 이전의 이진 직렬화와 구별되게 합니다.

이 문서는 RFC 7049를 폐기하며, RFC 7049의 교환 형식과 완전한 호환성을 유지하면서 편집상 개선, 새로운 세부 사항 및 정오표 수정을 제공합니다. 이는 형식의 새 버전을 만들지 않습니다.

이 메모의 상태

이것은 인터넷 표준 트랙 문서입니다.

이 문서는 인터넷 엔지니어링 태스크 포스 (IETF)의 산출물입니다. 이는 IETF 커뮤니티의 합의를 나타냅니다. 공개 검토를 받았으며 인터넷 엔지니어링 운영 그룹(IESG)에 의해 출판이 승인되었습니다. 인터넷 표준에 관한 자세한 정보는 RFC 7841의 섹션 2에서 확인할 수 있습니다.

이 문서의 현재 상태, 모든 정오표 및 이에 대한 피드백 제공 방법에 관한 정보는 https://www.rfc-editor.org/info/rfc8949에서 확인할 수 있습니다.

목차

1. 서론

구조화된 데이터의 이진 표현 (이진 직렬화 형식이라고도 함)을 위한 표준화된 형식은 수백 가지가 있다. 그중 일부는 특정 정보 영역을 위한 것이며, 다른 일부는 임의의 데이터를 위해 일반화되어 있다. IETF에서 후자의 범주에서 가장 잘 알려진 형식은 아마도 ASN.1의 BER 및 DER [ASN.1]일 것이다.

여기에서 정의하는 형식은 현재 형식들이 잘 충족하지 못하는 몇 가지 특정 설계 목표를 따른다. 기본 데이터 모델은 JSON 데이터 모델 [RFC8259]의 확장된 버전이다. 이는 RFC 8259의 문법을 일반적으로 확장하자는 제안이 아니라는 점에 유의하는 것이 중요하다. 그렇게 하면 이미 배포된 JSON 문서와 상당한 하위 호환성 문제가 발생하기 때문이다. 대신, 이 문서는 단순히 JSON에서 출발하는 자체 데이터 모델을 정의한다.

부록 E는 일부 기존 이진 형식을 나열하고 이들이 간결한 이진 객체 표현(CBOR)의 설계 목표에 얼마나 잘 부합하거나 부합하지 않는지 논의한다.

이 문서는 [RFC7049]를 폐기하며, RFC 7049의 교환 형식과 완전한 호환성을 유지하면서 편집상 개선, 새로운 세부 사항 및 정오표 수정을 제공한다. 이는 형식의 새 버전을 만들지 않는다.

1.1. 목표

CBOR의 목표는 중요도가 대체로 높은 것부터 낮은 것까지 다음과 같다.

  1. 표현은 인터넷 표준에서 사용되는 대부분의 일반적인 데이터 형식을 모호하지 않게 인코딩할 수 있어야 한다.

    • 이진 인코딩을 사용하여 합리적인 기본 데이터 타입과 구조 집합을 표현해야 한다. 여기서 "합리적"이라는 것은 주로 JSON의 능력에 영향을 받으며, 주요 추가 사항은 이진 바이트 문자열이다. 지원되는 구조는 배열과 트리로 제한되며, 루프와 격자형 그래프는 지원되지 않는다.
    • 모든 데이터 형식이 고유하게 인코딩되어야 한다는 요구 사항은 없다. 즉, 숫자 "7"이 여러 다른 방식으로 인코딩될 수 있어도 허용된다.
  2. 인코더 또는 디코더의 코드는 매우 제한적인 메모리, 프로세서 성능, 명령어 집합을 가진 시스템을 지원하기 위해 간결할 수 있어야 한다.

    • 인코더와 디코더는 매우 적은 양의 코드로 구현 가능해야 한다 (예: [RFC7228]에 정의된 클래스 1 제약 노드에서).
    • 이 형식은 데이터의 현대적인 기계 표현을 사용해야 한다 (예: 이진-십진 변환을 요구하지 않아야 함).
  3. 데이터는 스키마 설명 없이 디코딩될 수 있어야 한다.

    • JSON과 유사하게, 인코딩된 데이터는 일반 디코더를 작성할 수 있도록 자기 설명적이어야 한다.
  4. 직렬화는 합리적으로 간결해야 하지만, 데이터 간결성은 인코더와 디코더의 코드 간결성에 비해 부차적이다.

    • 여기서 "합리적"이라는 것은 크기 면에서 JSON을 상한으로 하고, 구현 복잡성에 의해 제한된다. 이 복잡성은 그 간결성을 달성하기 위해 투입할 수 있는 노력의 양을 제한한다. 일반 압축 기법이나 과도한 비트 조작을 사용하는 것은 복잡성 목표에 위배된다.
  5. 이 형식은 제약 노드와 대용량 애플리케이션 모두에 적용 가능해야 한다.

    • 이는 인코딩과 디코딩 모두에서 CPU 사용이 합리적으로 절약되어야 함을 의미한다. 이는 제약 노드와 매우 많은 양의 데이터를 사용하는 애플리케이션에서의 잠재적 사용 모두에 관련된다.
  6. 이 형식은 JSON과의 상호 변환을 위해 모든 JSON 데이터 타입을 지원해야 한다.

    • 표현된 데이터가 JSON의 능력 범위 내에 있는 한, 합리적인 수준의 변환을 지원해야 한다. 모든 타입의 데이터에 대해 JSON으로 향하는 단방향 매핑을 정의할 수 있어야 한다.
  7. 이 형식은 확장 가능해야 하며, 확장된 데이터는 이전 디코더가 디코딩할 수 있어야 한다.

    • 이 형식은 수십 년 동안 사용되도록 설계되었다.
    • 이 형식은 확장을 이해하지 못하는 디코더도 메시지를 디코딩할 수 있도록 폴백을 허용하는 확장성 형태를 지원해야 한다.
    • 이 형식은 나중의 IETF 표준에 의해 미래에 확장될 수 있어야 한다.

1.2. 용어

이 문서에서 사용되는 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", 및 "OPTIONAL"은 여기에 표시된 것처럼 모두 대문자로 나타날 때에만 BCP 14 [RFC2119] [RFC8174]에 설명된 대로 해석되어야 한다.

"byte"라는 용어는 이제 관례적인 의미로 "octet"의 동의어로 사용된다. 모든 다중 바이트 값은 네트워크 바이트 순서 (즉, 최상위 바이트가 먼저 오는 방식, "빅 엔디언"이라고도 함)로 인코딩된다.

이 명세는 다음 용어를 사용한다.

데이터 항목:
단일 CBOR 데이터 조각. 데이터 항목의 구조는 0개, 1개 또는 그 이상의 중첩 데이터 항목을 포함할 수 있다. 이 용어는 표현 형식의 데이터 항목과 디코더가 그것으로부터 도출할 수 있는 추상적 개념 모두에 사용된다. 전자는 "인코딩된 데이터 항목"이라는 용어를 사용하여 구체적으로 지칭할 수 있다.
디코더:
올바른 형식의 인코딩된 CBOR 데이터 항목을 디코딩하여 애플리케이션에서 사용할 수 있게 하는 프로세스. 형식적으로 말하면, 디코더는 CBOR의 구문 규칙을 사용하여 입력을 분해하는 파서와, 애플리케이션에 적합한 형태로 데이터를 준비하는 의미 처리기를 포함한다.
인코더:
애플리케이션 정보로부터 CBOR 데이터 항목의 (올바른 형식의) 표현 형식을 생성하는 프로세스.
데이터 스트림:
더 큰 포함 데이터 항목으로 추가 조립되지 않은 0개 이상의 데이터 항목 시퀀스(한 가지 적용 사례는 [RFC8742] 참조). 데이터 스트림을 구성하는 독립적인 데이터 항목은 때때로 "최상위 데이터 항목"이라고도 한다.
올바른 형식:
CBOR의 구문 구조를 따르는 데이터 항목. 올바른 형식의 데이터 항목은 CBOR에 정의된 대로 그 값에 의해 암시되는 초기 바이트와 바이트 문자열 및/또는 데이터 항목을 사용하며, 뒤따르는 불필요한 데이터를 포함하지 않는다. CBOR 디코더는 정의상 올바른 형식의 데이터 항목에서만 내용을 반환한다.
유효함:
올바른 형식이며 CBOR 데이터 항목에 적용되는 의미적 제한도 따르는 데이터 항목(섹션 5.3).
예상됨:
일반 영어 의미 외에도, "expected"라는 용어는 애플리케이션이 입력 데이터에 대해 갖는 CBOR 유효성 이상의 요구 사항을 설명하는 데 사용된다. 올바른 형식(전혀 처리 가능), 유효함(유효성 검사 일반 디코더가 검사), 예상됨(애플리케이션이 검사)은 수용 가능성 계층의 위계를 이룬다.
스트림 디코더:
데이터 스트림을 디코딩하고 시퀀스의 각 데이터 항목을 수신되는 대로 애플리케이션에서 사용할 수 있게 하는 프로세스.

Infinity, NaN (숫자가 아님), 음의 0, 비정규수와 같은 부동소수점 값에 대한 용어와 개념은 [IEEE754]에 정의되어 있다.

비트 산술이나 데이터 타입이 설명되는 곳에서, 이 문서는 프로그래밍 언어 C [C]에서 익숙한 표기법을 사용한다. 다만 ".."는 주어진 양 끝을 모두 포함하는 범위를 나타내며, 위첨자 표기법은 거듭제곱을 나타낸다. 예를 들어, 2의 64제곱은 다음과 같이 표기한다: 264. 이 명세의 일반 텍스트 버전에서는 위첨자 표기법을 사용할 수 없으므로 대체 표기법으로 렌더링된다. 그 표기법은 이 RFC에 최적화되어 있지 않으며, 불행히도 C의 배타적 OR(부록에서만 사용되고, 부록은 거듭제곱을 사용하지 않음)와 모호하고 일반 텍스트 버전의 독자에게 주의를 요구한다.

예제와 의사 코드는 부호 있는 정수가 2의 보수 표현을 사용하고 부호 있는 정수의 오른쪽 시프트가 부호 확장을 수행한다고 가정한다. 이러한 가정은 현재 최종 초안으로 제공되는 2020년 버전 C++의 섹션 6.8.1 (basic.fundamental) 및 7.6.7 (expr.shift)에도 명시되어 있다 [Cplusplus20].

16진수에 대한 "0x" 표기와 유사하게, 이진 표기의 숫자는 "0b"가 앞에 붙는다. 밑줄은 오직 가독성을 위해 숫자에 추가될 수 있으므로, 0b00100001 (0x21)은 바이트의 비트에 대한 원하는 해석을 강조하기 위해 0b001_00001로 쓸 수 있다. 이 경우 세 비트와 다섯 비트로 나뉜다. 인코딩된 CBOR 데이터 항목은 때때로 "0x" 또는 "0b" 표기로 주어진다. 이 값들은 먼저 C에서와 같이 숫자로 해석된 다음, 표기에 표현된 모든 선행 0 바이트를 포함하여 네트워크 바이트 순서의 바이트 문자열로 해석된다.

단어는 강조를 위해 기울임꼴로 표시될 수 있다. 이 명세의 일반 텍스트 형식에서는 단어를 밑줄 문자로 둘러싸는 방식으로 이를 표시한다. 축어 텍스트(예: 프로그래밍 언어의 이름)는 monospace 글꼴로 표시될 수 있다. 일반 텍스트에서는 텍스트를 큰따옴표로 둘러싸는 방식으로 다소 모호하게 근사한다 (큰따옴표는 또한 일반적인 의미도 유지한다).

2. CBOR 데이터 모델

CBOR는 일반 데이터 모델에 대해 명시적이다. 이 모델은 CBOR에서 표현할 수 있는 모든 데이터 항목의 집합을 정의한다. 기본 일반 데이터 모델은 "단순 값" 및 태그의 등록을 통해 확장 가능하다. 그러면 애플리케이션은 결과적으로 확장된 일반 데이터 모델의 하위 집합을 만들어 자체 특정 데이터 모델을 구축할 수 있다.

일반 데이터 모델의 데이터 항목을 표현할 수 있는 환경 내에서는 일반 CBOR 인코더와 디코더를 구현할 수 있다 (일반적으로는 환경에 자연스러운 표현이 아직 없는 데이터 항목에 대해 추가 구현 데이터 타입을 정의하는 것을 포함한다). 일반 인코더와 디코더를 제공할 수 있는 능력은 CBOR의 명시적인 설계 목표이다. 그러나 많은 애플리케이션은 자체 애플리케이션별 인코더 및/또는 디코더를 제공할 것이다.

섹션 3에 정의된 기본(확장되지 않은) 일반 데이터 모델에서, 데이터 항목은 다음 중 하나이다.

이 모델에서 정수와 부동소수점 값은 같은 수치 값을 갖더라도 서로 구별된다는 점에 유의한다.

또한 직렬화 변형은 일반 데이터 모델 수준에서 보이지 않는다는 점에 유의한다. 이러한 의도적인 비가시성에는 인코딩된 부동소수점 값의 바이트 수가 포함된다. 또한 정수의 인코딩, 텍스트 또는 바이트 문자열 길이의 인코딩, 배열의 요소 수 또는 맵의 쌍 수에 대한 인코딩, 또는 태그 번호의 인코딩과 같은 "인수"(섹션 3 참조)의 인코딩 선택도 포함된다.

2.1. 확장된 일반 데이터 모델

이 기본 일반 데이터 모델은 이 문서에서 다음과 같은 여러 단순 값과 태그 번호의 등록을 통해 확장되었다.

  • false, true, null, 및 undefined (20..23으로 식별되는 단순 값, 섹션 3.3)
  • 위보다 더 큰 범위와 정밀도를 가진 정수 및 부동소수점 값 (태그 번호 2에서 5, 섹션 3.4)
  • 시점 또는 RFC 3339에 정의된 날짜/시간 문자열과 같은 애플리케이션 데이터 타입 (태그 번호 1 및 0, 섹션 3.4)

확장된 일반 데이터 모델의 추가 요소는 CBOR를 위해 생성된 IANA 레지스트리를 통해 정의될 수 있다(그리고 이미 정의되어 왔다). 그러한 확장을 일반 인코더나 디코더가 알지 못하더라도, 그 확장을 사용하는 데이터 항목은 기본 일반 데이터 모델 내에서, 즉 일반 단순 값 또는 일반 태그로 표현하여 애플리케이션으로 또는 애플리케이션에서 전달될 수 있다.

다시 말해, 기본 일반 데이터 모델은 이 문서에 정의된 대로 안정적이며, 확장된 일반 데이터 모델은 새 단순 값 또는 태그 번호의 등록을 통해 확장되지만 결코 축소되지 않는다.

일반 인코더와 디코더가 false, true, 및 null (undefined는 의도적으로 제외됨)을 해당 프로그래밍 환경에 적합한 형태로 표현할 수 있으리라는 강한 기대가 있지만, 태그로 생성된 데이터 모델 확장의 구현은 실제로 선택 사항이며 구현 품질의 문제이다.

2.2. 특정 데이터 모델

CBOR 기반 프로토콜의 특정 데이터 모델은 일반적으로 확장된 일반 데이터 모델의 하위 집합을 취하고, 이 하위 집합 및 그 구성 요소 내의 데이터 항목에 애플리케이션 의미를 부여한다. 그러한 특정 데이터 모델을 문서화하고 데이터 항목의 타입을 명시할 때는, CBOR 표현의 측면("주요 타입 1", "주요 타입 4")을 참조하기보다는 일반 데이터 모델 이름("음의 정수", "배열")으로 타입을 식별하는 것이 바람직하다.

특정 데이터 모델은 또한 맵 키 및 인코더 자유도를 위해 (서로 다른 타입의 값을 포함하여) 값의 동등성을 지정할 수 있다. 예를 들어, 일반 데이터 모델에서는 유효한 맵이 00.0을 모두 키로 가질 수 있으며, 인코더는 MUST NOT 0.0을 정수 (주요 타입 0, 섹션 3.1)로 인코딩해서는 안 된다. 그러나 특정 데이터 모델이 정수 값을 갖는 부동소수점 표현과 정수 표현이 동등하다고 선언한다면, 단일 맵에서 00.0을 모두 맵 키로 사용하는 것은 서로 다른 주요 타입으로 인코딩되었더라도 중복으로 간주되어 유효하지 않게 된다. 또한 인코더는 인코딩 바이트를 절약하기 위해 정수 값을 갖는 부동소수점을 정수로, 또는 그 반대로 인코딩할 수 있다.

3. CBOR 인코딩 명세

CBOR 데이터 항목(섹션 2)은 이 섹션에 설명된 대로 올바른 형식의 인코딩된 데이터 항목을 담는 바이트 문자열로 인코딩되거나 그로부터 디코딩된다. 인코딩은 부록 B표 7에 초기 바이트를 기준으로 요약되어 있다. 인코더는 MUST 올바른 형식의 인코딩된 데이터 항목만 생성해야 한다. 디코더는 올바른 형식의 인코딩된 CBOR 데이터 항목이 아닌 입력을 만났을 때 디코딩된 데이터 항목을 반환해서는 MUST NOT 안 된다 (이는 손상된 인코딩된 CBOR 데이터 항목에서 일부 정보를 사용할 수 있게 하는 진단 및 복구 도구의 유용성을 떨어뜨리지 않는다).

각 인코딩된 데이터 항목의 초기 바이트는 주요 타입(상위 3비트, 섹션 3.1에서 설명됨)에 대한 정보와 추가 정보(하위 5비트)를 모두 포함한다. 몇 가지 예외를 제외하고, 추가 정보의 값은 부호 없는 정수 "인수"를 로드하는 방법을 설명한다.

24보다 작음:
인수의 값은 추가 정보의 값이다.
24, 25, 26 또는 27:
인수의 값은 각각 이어지는 1, 2, 4 또는 8바이트에 네트워크 바이트 순서로 저장된다. 주요 타입 7과 추가 정보 값 25, 26, 27의 경우, 이 바이트들은 정수 인수가 아니라 부동소수점 값으로 사용된다 (섹션 3.3 참조).
28, 29, 30:
이 값들은 CBOR 형식의 향후 추가를 위해 예약되어 있다. 현재 버전의 CBOR에서 인코딩된 항목은 올바른 형식이 아니다.
31:
인수 값이 도출되지 않는다. 주요 타입이 0, 1 또는 6이면 인코딩된 항목은 올바른 형식이 아니다. 주요 타입 2부터 5까지는 항목의 길이가 부정이고, 주요 타입 7에서는 이 바이트가 데이터 항목을 구성하지 않고 부정 길이 항목을 종료한다. 모두 섹션 3.2에 설명되어 있다.

초기 바이트와 인수를 구성하기 위해 소비되는 모든 추가 바이트를 통틀어 데이터 항목의 헤드라고 한다.

이 인수의 의미는 주요 타입에 따라 달라진다. 예를 들어, 주요 타입 0에서 인수는 데이터 항목 자체의 값이며(주요 타입 1에서는 데이터 항목의 값이 인수로부터 계산된다), 주요 타입 2와 3에서는 이어지는 바이트의 문자열 데이터 길이를 제공하고, 주요 타입 4와 5에서는 포함된 데이터 항목 수를 결정하는 데 사용된다.

인코딩된 바이트 시퀀스가 데이터 항목의 끝에 도달하기 전에 끝나면, 그 항목은 올바른 형식이 아니다. 최외곽 인코딩된 항목이 디코딩된 후에도 인코딩된 바이트 시퀀스에 바이트가 남아 있으면, 그 인코딩은 단일 올바른 형식의 CBOR 항목이 아니다. 애플리케이션에 따라 디코더는 이 인코딩을 올바른 형식이 아닌 것으로 처리하거나 남은 바이트의 시작 위치를 애플리케이션에 알려줄 수 있다.

CBOR 디코더 구현은 초기 바이트의 256개 정의된 값 전체에 대한 점프 테이블(표 7)을 기반으로 할 수 있다. 제약 구현의 디코더는 보다 간결한 코드를 위해 초기 바이트와 이어지는 바이트의 구조를 대신 사용할 수 있다 (이것이 어떻게 보일 수 있는지에 대한 대략적인 인상은 부록 C 참조).

3.1. 주요 타입

다음은 주요 타입과 그 타입에 관련된 추가 정보 및 기타 바이트를 나열한다.

주요 타입 0:
0..264-1 범위의 부호 없는 정수(양 끝 포함). 인코딩된 항목의 값은 인수 자체이다. 예를 들어, 정수 10은 한 바이트 0b000_01010(주요 타입 0, 추가 정보 10)으로 나타낸다. 정수 500은 0b000_11001 (주요 타입 0, 추가 정보 25)에 이어 두 바이트 0x01f4가 오며, 이는 십진수 500이다.
주요 타입 1:
-264..-1 범위의 음의 정수(양 끝 포함). 항목의 값은 -1에서 인수를 뺀 값이다. 예를 들어, 정수 -500은 0b001_11001(주요 타입 1, 추가 정보 25)에 이어 두 바이트 0x01f3이 오며, 이는 십진수 499이다.
주요 타입 2:
바이트 문자열. 문자열의 바이트 수는 인수와 같다. 예를 들어 길이가 5인 바이트 문자열은 초기 바이트 0b010_00101 (주요 타입 2, 길이에 대한 추가 정보 5)을 가진 뒤, 5바이트의 이진 내용이 이어진다. 길이가 500인 바이트 문자열은 0b010_11001(주요 타입 2, 두 바이트 길이를 나타내는 추가 정보 25)의 3개 초기 바이트와 길이 500을 나타내는 두 바이트 0x01f4, 그리고 500바이트의 이진 내용이 이어진다.
주요 타입 3:
UTF-8 [RFC3629]로 인코딩된 텍스트 문자열 (섹션 2). 문자열의 바이트 수는 인수와 같다. 잘못된 UTF-8 시퀀스를 포함하는 문자열은 올바른 형식이지만 유효하지 않다(섹션 1.2). 이 타입은 사람이 읽을 수 있는 텍스트를 해석하거나 표시해야 하는 시스템을 위해 제공되며, 구조화되지 않은 바이트와 지정된 문자 집합(Unicode) 및 인코딩(UTF-8)을 가진 텍스트를 구분할 수 있게 한다. JSON과 같은 형식과 달리, 이 타입의 Unicode 문자는 결코 이스케이프되지 않는다. 따라서 줄바꿈 문자(U+000A)는 문자열에서 항상 바이트 0x0a로 표현되며, 결코 바이트 0x5c6e (문자 "\" 및 "n")나 0x5c7530303061(문자 "\", "u", "0", "0", "0", 및 "a")로 표현되지 않는다.
주요 타입 4:
데이터 항목의 배열. 다른 형식에서 배열은 리스트, 시퀀스 또는 튜플이라고도 한다("CBOR sequence"는 약간 다른 것이지만 [RFC8742] 참조). 인수는 배열 안의 데이터 항목 수이다. 배열의 항목들이 모두 같은 타입일 필요는 없다. 예를 들어, 임의 타입의 항목 10개를 포함하는 배열은 초기 바이트 0b100_01010(주요 타입 4, 길이에 대한 추가 정보 10)을 가진 뒤 10개의 나머지 항목이 이어진다.
주요 타입 5:
데이터 항목 쌍의 맵. 맵은 테이블, 딕셔너리, 해시 또는 (JSON의) 객체라고도 한다. 맵은 데이터 항목의 쌍으로 구성되며, 각 쌍은 바로 뒤에 값이 오는 키로 이루어진다. 인수는 맵의 데이터 항목 수이다. 예를 들어, 9쌍을 포함하는 맵은 초기 바이트 0b101_01001(주요 타입 5, 쌍 수에 대한 추가 정보 9)을 가진 뒤 18개의 나머지 항목이 이어진다. 첫 번째 항목은 첫 번째 키, 두 번째 항목은 첫 번째 값, 세 번째 항목은 두 번째 키이며, 이런 식으로 계속된다. 맵의 항목은 쌍으로 오기 때문에 전체 수는 항상 짝수이다. 홀수 개의 항목을 포함하는 맵(마지막 키 데이터 항목 뒤에 값 데이터가 없음)은 올바른 형식이 아니다. 중복 키를 가진 맵은 올바른 형식일 수 있지만 유효하지 않으며, 따라서 불확정 디코딩을 야기한다. 섹션 5.6도 참조한다.
주요 타입 6:
태그 번호가 인수인(0..264-1 범위의 정수) 태그가 지정된 데이터 항목("태그")이며, 헤드 뒤에 오는 단일 인코딩된 데이터 항목을 포함된 데이터 항목(태그 내용)으로 가진다. 섹션 3.4를 참조한다.
주요 타입 7:
부동소수점 수와 단순 값, 그리고 "break" 정지 코드. 섹션 3.3을 참조한다.

이 여덟 가지 주요 타입은 데이터 항목의 초기 바이트에 대해 가능한 256개 값 중 어떤 값이 사용되는지를 보여 주는 간단한 표(표 7)로 이어진다.

주요 타입 6과 7에서는 가능한 값 중 다수가 향후 명세를 위해 예약되어 있다. 이 값들에 대한 자세한 정보는 섹션 9를 참조한다.

표 1은 당분간 섹션 3.2를 무시하고 CBOR가 정의한 주요 타입을 요약한다. 이 표의 숫자 N은 인수를 나타낸다.

표 1: CBOR 주요 타입의 정길이 사용 개요(N = 인수)
주요 타입 의미 내용
0 부호 없는 정수 N -
1 음의 정수 -1-N -
2 바이트 문자열 N바이트
3 텍스트 문자열 N바이트(UTF-8 텍스트)
4 배열 N개의 데이터 항목(요소)
5 2N개의 데이터 항목(키/값 쌍)
6 번호 N의 태그 1개의 데이터 항목
7 단순/부동소수점 -

3.2. 일부 주요 타입에 대한 부정 길이

네 가지 CBOR 항목(배열, 맵, 바이트 문자열 및 텍스트 문자열)은 추가 정보 값 31을 사용하여 부정 길이로 인코딩될 수 있다. 이는 배열이나 맵 내부의 항목 수 또는 문자열의 총 길이를 알기 전에 항목의 인코딩을 시작해야 할 때 유용하다. (데이터 항목이 모두 알려지기 전에 전송을 시작할 수 있는 능력은 종종 그 데이터 항목 내의 "스트리밍"이라고 한다.)

부정 길이 배열과 맵은 부정 길이 문자열(바이트 문자열과 텍스트 문자열)과는 다르게 처리된다.

3.2.1. "break" 정지 코드

"break" 정지 코드는 주요 타입 7과 추가 정보 값 31(0b111_11111)로 인코딩된다. 이는 그 자체가 데이터 항목이 아니다. 단지 부정 길이 항목을 닫기 위한 구문적 기능이다.

"break" 정지 코드가 부정 길이 문자열, 배열 또는 맵의 바로 내부가 아닌, 데이터 항목이 예상되는 곳에 나타나면 -- 예를 들어 정길이 배열이나 맵 바로 내부 -- 포함하는 항목은 올바른 형식이 아니다.

3.2.2. 부정 길이 배열 및 맵

부정 길이 배열과 맵은 추가 정보 값 31을 가진 해당 주요 타입을 사용하고, 그 뒤에 배열의 경우 0개 이상의 항목, 맵의 경우 키/값 쌍의 임의 길이 시퀀스가 이어지며, "break" 정지 코드(섹션 3.2.1)로 끝나는 방식으로 표현된다. 다시 말해, 부정 길이 배열과 맵은 추가 정보 값 31로 시작하고 "break" 정지 코드로 끝난다는 점을 제외하면 다른 배열 및 맵과 동일하게 보인다.

"break" 정지 코드가 맵에서 키 뒤에 나타나, 그 키의 값 대신 위치하면, 맵은 올바른 형식이 아니다.

부정 길이 배열 또는 맵 항목을 중첩하는 것에 대한 제한은 없다. "break"는 단일 항목만 종료하므로, 중첩된 부정 길이 항목은 부정 길이 항목을 시작하는 타입 바이트 수만큼 정확히 많은 "break" 정지 코드를 필요로 한다.

예를 들어, 인코더가 추상 배열 [1, [2, 3], [4, 5]]를 표현하려고 한다고 가정한다. 정길이 인코딩은 0x8301820203820405가 된다.

83        -- Array of length 3
   01     -- 1
   82     -- Array of length 2
      02  -- 2
      03  -- 3
   82     -- Array of length 2
      04  -- 4
      05  -- 5

부정 길이 인코딩은 필요에 따라 이 데이터 항목에서 인코딩된 세 배열 각각에 독립적으로 적용될 수 있으며, 다음과 같은 표현으로 이어진다.

0x9f018202039f0405ffff
9F        -- Start indefinite-length array
   01     -- 1
   82     -- Array of length 2
      02  -- 2
      03  -- 3
   9F     -- Start indefinite-length array
      04  -- 4
      05  -- 5
      FF  -- "break" (inner array)
   FF     -- "break" (outer array)
0x9f01820203820405ff
9F        -- Start indefinite-length array
   01     -- 1
   82     -- Array of length 2
      02  -- 2
      03  -- 3
   82     -- Array of length 2
      04  -- 4
      05  -- 5
   FF     -- "break"
0x83018202039f0405ff
83        -- Array of length 3
   01     -- 1
   82     -- Array of length 2
      02  -- 2
      03  -- 3
   9F     -- Start indefinite-length array
      04  -- 4
      05  -- 5
      FF  -- "break"
0x83019f0203ff820405
83        -- Array of length 3
   01     -- 1
   9F     -- Start indefinite-length array
      02  -- 2
      03  -- 3
      FF  -- "break"
   82     -- Array of length 2
      04  -- 4
      05  -- 5

부정 길이 맵(우연히 두 개의 키/값 쌍을 가짐)의 예는 다음과 같을 수 있다.

0xbf6346756ef563416d7421ff
BF           -- Start indefinite-length map
   63        -- First key, UTF-8 string length 3
      46756e --   "Fun"
   F5        -- First value, true
   63        -- Second key, UTF-8 string length 3
      416d74 --   "Amt"
   21        -- Second value, -2
   FF        -- "break"

3.2.3. 부정 길이 바이트 문자열 및 텍스트 문자열

부정 길이 문자열은 바이트 문자열 또는 텍스트 문자열에 대한 주요 타입과 추가 정보 값 31을 포함하는 바이트로 표현되며, 그 뒤에 지정된 타입의 정길이 문자열("청크")이 0개 이상 이어지고, "break" 정지 코드(섹션 3.2.1)로 끝난다. 부정 길이 문자열이 나타내는 데이터 항목은 청크들의 연결이다. 청크가 없으면 데이터 항목은 지정된 타입의 빈 문자열이다. 길이가 0인 청크는 특별히 유용하지는 않지만 허용된다.

부정 길이 문자열 표시자 (0b010_11111 또는 0b011_11111)와 "break" 정지 코드 사이의 항목 중 같은 주요 타입의 정길이 문자열 항목이 아닌 것이 있다면, 그 문자열은 올바른 형식이 아니다.

이 설계는 부정 길이 문자열을 부정 길이 문자열의 청크로 중첩하는 것을 허용하지 않는다. 허용한다면 디코더 구현이 중첩 수준의 스택이나 최소한 카운트를 유지해야 한다. 인코더 쪽에서는 내부 부정 길이 문자열이 청크로 구성될 것이며, 이러한 청크를 대신 외부 부정 길이 문자열에 직접 넣을 수 있기 때문에 불필요하다.

부정 길이 텍스트 문자열 내부의 정길이 텍스트 문자열 중 유효하지 않은 것이 있다면, 부정 길이 텍스트 문자열은 유효하지 않다. 이는 단일 Unicode 코드 포인트(스칼라 값)의 UTF-8 바이트가 청크 사이에 나뉘어질 수 없음을 의미한다는 점에 유의한다. 텍스트 문자열의 새 청크는 코드 포인트 경계에서만 시작될 수 있다.

예를 들어, 다음 바이트들로 구성된 인코딩된 데이터 항목을 가정한다.

0b010_11111 0b010_00100 0xaabbccdd 0b010_00011 0xeeff99 0b111_11111
5F              -- Start indefinite-length byte string
   44           -- Byte string of length 4
      aabbccdd  -- Bytes content
   43           -- Byte string of length 3
      eeff99    -- Bytes content
   FF           -- "break"

디코딩 후, 이는 7바이트를 가진 하나의 바이트 문자열 0xaabbccddeeff99가 된다.

3.2.4. 주요 타입의 부정 길이 사용 요약

표 2는 CBOR가 정의한 주요 타입이 부정 길이 인코딩(추가 정보가 31로 설정됨)에 사용되는 방식을 요약한다.

표 2: CBOR 주요 타입의 부정 길이 사용 개요(추가 정보 = 31)
주요 타입 의미 "break" 정지 코드까지 포함되는 것
0 (올바른 형식이 아님) -
1 (올바른 형식이 아님) -
2 바이트 문자열 정길이 바이트 문자열
3 텍스트 문자열 정길이 텍스트 문자열
4 배열 데이터 항목(요소)
5 데이터 항목(키/값 쌍)
6 (올바른 형식이 아님) -
7 "break" 정지 코드 -

3.3. 부동소수점 수 및 내용이 없는 값

주요 타입 7은 두 종류의 데이터, 즉 부동소수점 수와 내용을 필요로 하지 않는 "단순 값"을 위한 것이다. 초기 바이트의 5비트 추가 정보 값 각각은 표 3에 정의된 대로 별도의 의미를 가진다. 정수에 대한 주요 타입과 마찬가지로, 이 주요 타입의 항목은 내용 데이터를 담지 않는다. 모든 정보는 초기 바이트(헤드)에 있다.

표 3: 주요 타입 7의 추가 정보 값
5비트 값 의미
0..23 단순 값(값 0..23)
24 단순 값(이어지는 바이트의 값 32..255)
25 IEEE 754 반정밀도 부동소수점(16비트가 뒤따름)
26 IEEE 754 단정밀도 부동소수점(32비트가 뒤따름)
27 IEEE 754 배정밀도 부동소수점(64비트가 뒤따름)
28-30 예약됨, 현재 문서에서는 올바른 형식이 아님
31 부정 길이 항목에 대한 "break" 정지 코드 (섹션 3.2.1)

다른 모든 주요 타입과 마찬가지로, 5비트 값 24는 단일 바이트 확장을 의미한다. 즉, 단순 값을 표현하기 위해 추가 바이트가 뒤따른다. (혼동을 최소화하기 위해 32에서 255까지의 값만 사용된다.) 이는 초기 바이트의 구조를 유지한다. 다른 주요 타입과 마찬가지로, 그 길이는 항상 첫 번째 바이트의 추가 정보에 의존한다. 표 4는 단순 값에 할당되고 사용할 수 있는 숫자 값을 나열한다.

표 4: 단순 값
의미
0..19 (할당되지 않음)
20 false
21 true
22 null
23 undefined
24..31 (예약됨)
32..255 (할당되지 않음)

인코더는 0xf8(주요 타입 7, 추가 정보 24)로 시작하고 0x20(십진수 32)보다 작은 바이트가 이어지는 2바이트 시퀀스를 내보내서는 MUST NOT 안 된다. 그러한 시퀀스는 올바른 형식이 아니다. (이는 인코더가 false, true, null, 또는 undefined를 2바이트 시퀀스로 인코딩할 수 없으며 이들의 1바이트 변형만 올바른 형식임을 의미한다. 더 일반적으로 말하면, 각 단순 값은 단 하나의 표현 변형만 가진다.)

5비트 값 25, 26, 27은 16비트, 32비트, 64비트 IEEE 754 이진 부동소수점 값 [IEEE754]을 위한 것이다. 이러한 부동소수점 값은 적절한 크기의 추가 바이트에 인코딩된다. (16비트 부동소수점 수에 대한 일부 정보는 부록 D를 참조한다.)

3.4. 항목 태그 지정

CBOR에서 데이터 항목은 태그 번호로 고유하게 식별되는 추가 의미를 부여하기 위해 태그로 둘러싸일 수 있다. 태그는 주요 타입 6이며, 그 인수(섹션 3)는 태그 번호를 나타내고, 단일 포함 데이터 항목인 태그 내용을 포함한다. (태그가 내용에 추가 구조를 요구하는 경우, 이 구조는 포함된 데이터 항목으로 제공된다.) 여기서는 태그 번호와 태그 내용 모두로 구성된 전체 데이터 항목을 태그라는 용어로 부른다. 태그 내용은 태그가 지정되는 데이터 항목이다.

예를 들어, 길이 12의 바이트 문자열이 부호 없는 큰 수(섹션 3.4.3)임을 나타내기 위해 번호 2의 태그로 표시된다고 가정한다. 인코딩된 데이터 항목은 바이트 0b110_00010(주요 타입 6, 태그 번호에 대한 추가 정보 2)으로 시작하고, 이어서 인코딩된 태그 내용, 즉 0b010_01100(주요 타입 2, 길이에 대한 추가 정보 12)과 큰 수의 12바이트가 뒤따른다.

확장된 일반 데이터 모델에서, 태그 번호의 정의는 그 태그 번호와 함께 전달되는 추가 의미를 설명한다. 이러한 의미는 일부 태그가 지정된 데이터 항목과 기본 일반 데이터 모델로 표현될 수 있는 다른 데이터 항목 사이의 동등성을 포함할 수 있다. 예를 들어, 태그 내용이 단일 바이트 0x01을 가진 바이트 문자열인 큰 수 0xc24101은 정수 1과 동등하며, 이는 0x01, 0x1801 또는 0x190001로도 인코딩될 수 있다. 태그 정의는 일반 인코더에 권장되는 선호 직렬화(섹션 4.1)를 지정할 수 있다. 이는 태그를 사용하는 표현보다 기본 일반 데이터 모델 표현을 선호할 수 있다.

태그 정의는 일반적으로 그러한 태그에 대해 어떤 중첩 데이터 항목이 유효한지를 정의한다. 태그 정의는 이 문서에 정의된 태그처럼 내용을 매우 특정한 구문 구조로 제한할 수도 있고, 더 의미적으로 내용을 정의할 수도 있다. 후자의 예는 태그 40 및 1040이 배열을 표현하는 여러 방식을 허용하는 방법이다 [RFC8746].

관례상 많은 태그는 null 또는 undefined 값을 태그 내용으로 받아들이지 않는다. 대신 기대되는 것은 null 또는 undefined 값을 전체 태그 대신 사용할 수 있다는 것이다. 섹션 3.4.2는 애플리케이션 프로토콜에서 그리고 플랫폼 타입으로 매핑할 때 이 관례를 처리하는 것에 대한 특정 태그의 추가 고려 사항을 제공한다.

디코더가 모든 태그 번호의 태그를 이해할 필요는 없으며, 특정 CBOR 데이터 항목을 생성하는 구현과 그 스트림을 디코딩하는 구현이 데이터 흐름의 각 항목의 의미를 알고 있는 애플리케이션에서는 태그의 가치가 거의 없을 수도 있다. 이 명세에서 태그의 주된 목적은 날짜와 같은 공통 데이터 타입을 정의하는 것이다. 부차적인 목적은 CBOR 데이터 항목을 다른 형식으로 변환해야 할 것으로 예상될 때 항목의 내용에 대한 힌트를 필요로 하는 경우 변환 힌트를 제공하는 것이다. 태그의 의미를 이해하는 것은 디코더에게 선택 사항이다. 디코더는 태그의 추가 의미를 해석하지 않고도 태그 번호와 태그 내용을 모두 애플리케이션에 단순히 제시할 수 있다.

태그는 자신이 둘러싸는 데이터 항목에 의미를 적용한다. 태그는 중첩될 수 있다. 태그 A가 태그 B를 둘러싸고, 태그 B가 데이터 항목 C를 둘러싸면, 태그 A는 태그 B를 데이터 항목 C에 적용한 결과에 적용된다.

IANA는 섹션 9.2에 설명된 대로 태그 번호 레지스트리를 유지한다. 표 5[RFC7049]에 정의된 태그 번호 중 이 섹션의 나머지 부분에서 정의를 제공하는 목록을 제공한다. (태그 번호 35도 [RFC7049]에 정의되어 있었다. 이 태그 번호에 대한 논의는 섹션 3.4.5.3에 나온다.) [RFC7049]가 출판된 이후 많은 다른 태그 번호도 정의되었다는 점에 유의한다. 전체 목록은 섹션 9.2에 설명된 레지스트리를 참조한다.

표 5: RFC 7049에 정의된 태그 번호
태그 데이터 항목 의미
0 텍스트 문자열 표준 날짜/시간 문자열; 섹션 3.4.1 참조
1 정수 또는 부동소수점 에포크 기반 날짜/시간; 섹션 3.4.2 참조
2 바이트 문자열 부호 없는 큰 수; 섹션 3.4.3 참조
3 바이트 문자열 음의 큰 수; 섹션 3.4.3 참조
4 배열 십진 분수; 섹션 3.4.4 참조
5 배열 큰 부동소수점 수; 섹션 3.4.4 참조
21 (임의) base64url 인코딩으로의 예상 변환; 섹션 3.4.5.2 참조
22 (임의) base64 인코딩으로의 예상 변환; 섹션 3.4.5.2 참조
23 (임의) base16 인코딩으로의 예상 변환; 섹션 3.4.5.2 참조
24 바이트 문자열 인코딩된 CBOR 데이터 항목; 섹션 3.4.5.1 참조
32 텍스트 문자열 URI; 섹션 3.4.5.3 참조
33 텍스트 문자열 base64url; 섹션 3.4.5.3 참조
34 텍스트 문자열 base64; 섹션 3.4.5.3 참조
36 텍스트 문자열 MIME 메시지; 섹션 3.4.5.3 참조
55799 (임의) 자기 설명 CBOR; 섹션 3.4.6 참조

개념적으로, 태그는 (역)직렬화 시간이 아니라 일반 데이터 모델에서 해석된다. 소수의 태그(현재로서는 태그 번호 25와 태그 번호 29 [IANA.cbor-tags])는 (역)직렬화 시간에 처리를 필요로 할 수 있는 의미로 등록되어 있다. 즉, 디코더는 데이터 항목이 CBOR 데이터 항목으로 인코딩되는 정확한 순서를 인식해야 하며, 인코더는 그 순서를 제어해야 한다. 이는 이러한 태그가 임의의 일반 CBOR 인코더/디코더 위에서 구현될 수 없음을 의미한다(그러한 인코더/디코더는 맵의 항목에 대한 직렬화 순서를 데이터 모델 수준에서 반영하지 않을 수 있으며 그 반대도 마찬가지이다). 따라서 이들의 구현은 일반적으로 일반 인코더/디코더에 통합되어야 한다. 이러한 속성을 가진 새 태그를 정의하는 것은 NOT RECOMMENDED이다.

IANA는 태그 번호 65535, 4294967295 및 18446744073709551615(16비트, 32비트, 64비트에서 이진수 모든 비트가 1)를 할당했다. 이들은 특정 태그의 존재 또는 태그 부재를 나타내기 위한 단일 정수 데이터 구조를 원하는 구현자를 위한 편의로 사용될 수 있다. 그 할당은 [CBOR-TAGS]의 섹션 10에 설명되어 있다. 이러한 태그는 실제 CBOR 데이터 항목에 나타나도록 의도되지 않았다. 구현은 그러한 발생을 오류로 표시할 MAY 수 있다.

프로토콜은 태그 번호 0 및 1을 사용하여 시점을 나타내는 데이터 항목으로, 태그 번호 2 및 3을 사용하여 임의 크기의 정수로, 그리고 태그 번호 4 및 5를 사용하여 임의 크기와 정밀도의 부동소수점 값으로 일반 데이터 모델(섹션 2)을 확장할 수 있다.

3.4.1. 표준 날짜/시간 문자열

태그 번호 0은 [RFC3339]date-time 생성 규칙에 설명되고, [RFC4287]의 섹션 3.3에서 정제된 표준 형식의 텍스트 문자열을 포함하며, 거기에 설명된 시점을 나타낸다. 다른 타입의 중첩 항목이나 [RFC4287]에 설명된 형식과 일치하지 않는 텍스트 문자열은 유효하지 않다.

3.4.2. 에포크 기반 날짜/시간

태그 번호 1은 UTC 시간으로 1970-01-01T00:00Z부터 표현된 민간 시간의 시점까지의 초 수를 세는 숫자 값을 포함한다.

태그 내용은 부호 없는 정수 또는 음의 정수(주요 타입 0 및 1) 또는 부동소수점 수(추가 정보 25, 26 또는 27을 가진 주요 타입 7)이어야 MUST 한다. 다른 포함 타입은 유효하지 않다.

음이 아닌 값(주요 타입 0 및 음이 아닌 부동소수점 수)은 1970-01-01T00:00Z UTC 이후의 시간 값을 나타내며 POSIX [TIME_T]에 따라 해석된다. (POSIX 시간은 "UNIX Epoch time"이라고도 알려져 있다.) 윤초는 POSIX 시간에서 특별히 처리되며, 이로 인해 십 년에 여러 번 1초의 불연속이 발생한다. 2106년 초 이후의 시간을 표현해야 하는 애플리케이션은 태그 내용에 대한 64비트 정수 지원을 생략할 수 없다는 점에 유의한다.

음수 값(주요 타입 1 및 음의 부동소수점 수)은 1970-01-01T00:00Z 이전의 UTC 초 수 시간에 대한 보편적 표준이 없으므로, 애플리케이션 요구 사항에 따라 결정되는 대로 해석된다(국가 달력의 불연속보다 앞선 시점의 경우 특히 그렇다). 비유한값에도 동일하게 적용된다.

초의 소수 부분을 나타내기 위해, 태그 번호 1 내에서 정수 값 대신 부동소수점 값을 사용할 수 있다. 이는 일반적으로 binary64 지원을 요구한다는 점에 유의한다. binary16 및 binary32는 1970년 초 주변의 짧은 기간 동안만 0이 아닌 초의 소수 부분을 제공하기 때문이다. 태그 번호 1 지원을 요구하는 애플리케이션은 태그 내용을 정수(또는 부동소수점 값)로만 제한할 수 있다.

날짜/시간에 대한 플랫폼 타입은 null 또는 undefined 값을 포함할 수 있으며, 이는 애플리케이션 프로토콜 수준에서도 바람직할 수 있다는 점에 유의한다. 비유한 태그 내용 값(예: 정의되지 않은 날짜/시간 값에 대한 NaN 또는 설정되지 않은 만료 날짜에 대한 Infinity)을 가진 태그 번호 1 값을 내보내는 것이 이를 처리하는 명백한 방법처럼 보일 수 있지만, 태그가 없는 null 또는 undefined를 사용하면 비유한값의 사용을 피하고 더 짧은 인코딩을 얻을 수 있다. 애플리케이션 프로토콜 설계자는 이러한 경우를 고려하고 이를 처리하기 위한 명확한 지침을 포함하는 것이 권장된다.

3.4.3. 큰 수

태그 번호 2 및 3을 사용하는 프로토콜은 임의 크기의 정수를 나타내는 "큰 수"로 일반 데이터 모델(섹션 2)을 확장한다. 기본 일반 데이터 모델에서 큰 수 값은 같은 모델의 정수와 같지 않지만, 이 태그 정의가 생성하는 확장된 일반 데이터 모델은 수치 값을 기반으로 동등성을 정의하며, 선호 직렬화(섹션 4.1)는 기본 정수로도 표현될 수 있는 큰 수를 결코 사용하지 않는다 (아래 참조).

큰 수는 바이트 문자열 데이터 항목으로 인코딩되며, 이는 네트워크 바이트 순서의 부호 없는 정수 n으로 해석된다. 다른 타입의 포함 항목은 유효하지 않다. 태그 번호 2의 경우 큰 수의 값은 n이다. 태그 번호 3의 경우, 큰 수의 값은 -1 - n이다. 바이트 문자열의 선호 직렬화는 모든 선행 0을 생략하는 것이다(n = 0에 대한 선호 직렬화가 빈 바이트 문자열이라는 점에 유의하되, 아래를 참조). 이러한 태그를 이해하는 디코더는 선행 0이 있는 큰 수도 디코딩할 수 있어야 MUST 한다. 주요 타입 0 또는 1을 사용하여 표현할 수 있는 정수의 선호 직렬화는 이를 큰 수로 인코딩하는 대신 그렇게 인코딩하는 것이다 (이는 선호 직렬화를 사용할 때 큰 수에서 빈 문자열이 결코 발생하지 않음을 의미한다). 이 점은 숫자를 인코딩할 때 기본 정수 대신 큰 수 표현을 선택하는 비선호 선택이 애플리케이션 의미를 갖도록 의도되지 않았음을 의미한다(0에 대해 0x00 대신 0x1800과 같이 필요한 것보다 긴 기본 정수 표현을 선택하는 것이 그렇지 않은 것과 같다).

예를 들어, 숫자 18446744073709551616(264)은 0b110_00010(주요 타입 6, 태그 번호 2)에 이어 0b010_01001(주요 타입 2, 길이 9), 그리고 0x010000000000000000(한 바이트 0x01 및 여덟 바이트 0x00)으로 표현된다. 16진수로는 다음과 같다.

C2                        -- Tag 2
   49                     -- Byte string of length 9
      010000000000000000  -- Bytes content

3.4.4. 십진 분수 및 큰 부동소수점 수

태그 번호 4를 사용하는 프로토콜은 m*(10e) 형태의 임의 길이 십진 분수를 나타내는 데이터 항목으로 일반 데이터 모델을 확장한다. 태그 번호 5를 사용하는 프로토콜은 m*(2e) 형태의 임의 길이 이진 분수를 나타내는 데이터 항목으로 일반 데이터 모델을 확장한다. 큰 수와 마찬가지로, 서로 다른 타입의 값은 일반 데이터 모델에서 같지 않다.

십진 분수는 정수 가수와 10진수 기반 스케일링 계수를 결합한다. 이들은 애플리케이션이 1.1과 같은 십진 분수의 정확한 표현을 필요로 할 때 가장 유용하다. 많은 십진 분수는 이진 부동소수점 표현에서 정확한 표현이 없기 때문이다.

"큰 부동소수점 수"는 정수 가수와 2진수 기반 스케일링 계수를 결합한다. 이들은 CBOR가 지원하는 세 가지 IEEE 754 형식 (섹션 3.3)의 범위나 정밀도를 초과할 수 있는 이진 부동소수점 값이다. 큰 부동소수점 수는 또한 IEEE 754를 지원할 필요 없이 기본적인 이진 부동소수점 기능이 필요한 제약 애플리케이션에서도 사용될 수 있다.

십진 분수 또는 큰 부동소수점 수는 정확히 두 개의 정수, 즉 지수 e와 가수 m을 포함하는 태그가 지정된 배열로 표현된다. 십진 분수(태그 번호 4)는 10진수 기반 지수를 사용한다. 십진 분수 데이터 항목의 값은 m*(10e)이다. 큰 부동소수점 수(태그 번호 5)는 2진수 기반 지수를 사용한다. 큰 부동소수점 수 데이터 항목의 값은 m*(2e)이다. 지수 e는 주요 타입 0 또는 1의 정수로 표현되어야 MUST 하며, 가수는 큰 수(섹션 3.4.3)일 수도 있다. 다른 구조를 가진 포함 항목은 유효하지 않다.

십진 분수의 예는 숫자 273.15를 0b110_00100(태그에 대한 주요 타입 6, 태그 번호에 대한 추가 정보 4)으로 표현하고, 이어서 0b100_00010(배열에 대한 주요 타입 4, 배열 길이에 대한 추가 정보 2), 0b001_00001(첫 번째 정수에 대한 주요 타입 1, -2 값에 대한 추가 정보 1), 0b000_11001(두 번째 정수에 대한 주요 타입 0, 두 바이트 값에 대한 추가 정보 25), 그리고 0b0110101010110011(두 바이트의 27315)이 뒤따르는 것이다. 16진수로는 다음과 같다.

C4             -- Tag 4
   82          -- Array of length 2
      21       -- -2
      19 6ab3  -- 27315

큰 부동소수점 수의 예는 숫자 1.5를 0b110_00101(태그에 대한 주요 타입 6, 태그 번호에 대한 추가 정보 5)으로 표현하고, 이어서 0b100_00010(배열에 대한 주요 타입 4, 배열 길이에 대한 추가 정보 2), 0b001_00000(첫 번째 정수에 대한 주요 타입 1, -1 값에 대한 추가 정보 0), 그리고 0b000_00011(두 번째 정수에 대한 주요 타입 0, 값 3에 대한 추가 정보 3)이 뒤따르는 것이다. 16진수로는 다음과 같다.

C5             -- Tag 5
   82          -- Array of length 2
      20       -- -1
      03       -- 3

십진 분수와 큰 부동소수점 수는 Infinity, -Infinity 또는 NaN의 표현을 제공하지 않는다. 십진 분수나 큰 부동소수점 수 대신 이러한 값이 필요하다면, 섹션 3.3의 IEEE 754 반정밀도 표현을 사용할 수 있다.

3.4.5. 콘텐츠 힌트

이 섹션의 태그는 일반 CBOR 처리기가 사용할 수 있는 콘텐츠 힌트를 위한 것이다. 이러한 콘텐츠 힌트는 일반 데이터 모델을 확장하지 않는다.

3.4.5.1. 인코딩된 CBOR 데이터 항목

때때로 포함하는 데이터 항목이 디코딩되는 시점에 즉시 디코딩되도록 의도되지 않은 내장 CBOR 데이터 항목을 운반하는 것이 유익하다. 태그 번호 24(CBOR 데이터 항목)는 내장 바이트 문자열을 CBOR 형식으로 인코딩된 단일 데이터 항목으로 태그 지정하는 데 사용할 수 있다. 바이트 문자열이 아닌 포함 항목은 유효하지 않다. 포함된 바이트 문자열은 올바른 형식의 CBOR 데이터 항목을 인코딩하면 유효하다. 디코딩된 CBOR 항목의 유효성 검사는 태그 유효성에 필요하지 않다 (하지만 일반 디코더가 특별 옵션으로 제공할 수는 있다).

3.4.5.2. CBOR-to-JSON 변환기를 위한 예상되는 이후 인코딩

태그 번호 21에서 23은 텍스트 기반 표현과 상호 운용할 때 바이트 문자열이 특정 인코딩을 필요로 할 수 있음을 나타낸다. 이러한 태그는 인코더가 자신이 작성하는 바이트 문자열 데이터가 나중에 특정 JSON 기반 용도로 변환될 가능성이 있음을 알 때 유용하다. 그 용도는 일부 문자열이 base64, base64url 등으로 인코딩된다고 지정한다. 인코더는 메시지 크기나 인코더의 코드 크기 또는 둘 모두를 줄이기 위해 직접 인코딩하는 대신 바이트 문자열을 사용한다. 인코더는 변환기가 일반적인지 여부를 알지 못하므로 이진 문자열을 JSON으로 변환하는 올바른 방식이라고 믿는 것을 말하고자 한다.

태그가 지정된 데이터 항목은 바이트 문자열일 수도 있고 다른 데이터 항목일 수도 있다. 후자의 경우, 이 태그는 예상 변환으로 태그가 지정된 중첩 데이터 항목에 포함된 바이트 문자열 데이터 항목을 제외하고, 그 데이터 항목에 포함된 모든 바이트 문자열 데이터 항목에 적용된다.

이 세 태그 번호는 [RFC4648]에 정의된 기본 데이터 인코딩 중 세 가지로의 변환을 제안한다. 태그 번호 21은 base64url 인코딩 ([RFC4648]의 섹션 5)으로의 변환을 제안하며, 여기서 패딩은 사용되지 않는다 ([RFC4648]의 섹션 3.2 참조). 즉, 인코딩된 문자열에서 모든 후행 등호("=")가 제거된다. 태그 번호 22는 RFC 4648에 정의된 패딩을 포함하는 고전적인 base64 인코딩 ([RFC4648]의 섹션 4)으로의 변환을 제안한다. base64url과 base64 모두에 대해 패딩 비트는 0으로 설정된다 ([RFC4648]의 섹션 3.5 참조). 그리고 대체 인코딩으로의 변환은 바이트 문자열의 내용에 대해 수행된다(즉, 줄바꿈, 공백 또는 기타 추가 문자를 더하지 않는다). 태그 번호 23은 대문자 알파벳을 사용하는 base16(16진수) 인코딩으로의 변환을 제안한다 ([RFC4648]의 섹션 8 참조). 세 태그 번호 모두에 대해 빈 바이트 문자열의 인코딩은 빈 텍스트 문자열이라는 점에 유의한다.

3.4.5.3. 인코딩된 텍스트

일부 텍스트 문자열은 인터넷에서 널리 사용되는 형식의 데이터를 보유하며, 때로는 디코더가 그러한 형식을 검증하고 적절한 형태로 애플리케이션에 제공할 수 있다. 이러한 형식 중 일부를 위한 태그가 있다.

  • 태그 번호 32는 [RFC3986]에 정의된 URI를 위한 것이다. 텍스트 문자열이 URI-reference 생성 규칙과 일치하지 않으면, 그 문자열은 유효하지 않다.
  • 태그 번호 33 및 34는 각각 [RFC4648]에 정의된 base64url 및 base64로 인코딩된 텍스트 문자열을 위한 것이다. 다음 중 하나라도 적용되면:

    • 인코딩된 텍스트 문자열에 비알파벳 문자가 포함되어 있거나 마지막 4문자 블록에 알파벳 문자가 1개만 있는 경우(여기서 알파벳은 태그 번호 33에 대해 [RFC4648]의 섹션 5, 태그 번호 34에 대해 [RFC4648]의 섹션 4에서 정의됨), 또는
    • 2문자 또는 3문자 블록의 패딩 비트가 0이 아닌 경우, 또는
    • base64 인코딩에 잘못된 수의 패딩 문자가 있는 경우, 또는
    • base64url 인코딩에 패딩 문자가 있는 경우,

    그 문자열은 유효하지 않다.

  • 태그 번호 36은 [RFC2045]에 정의된 MIME 메시지 (모든 헤더 포함)를 위한 것이다. 유효한 MIME 메시지가 아닌 텍스트 문자열은 유효하지 않다. (이 태그의 경우, 유효성 검사는 일반 디코더에 특히 부담이 될 수 있으므로 제공되지 않을 수도 있다. 많은 MIME 메시지는 일반 이진 데이터이므로 텍스트 문자열로 표현될 수 없다는 점에 유의한다. [IANA.cbor-tags]는 태그 번호 36과 유사하지만 태그 내용으로 바이트 문자열을 사용하는 태그 번호 257에 대한 등록을 나열한다.)

태그 번호 33 및 34는 21 및 22와 다르다는 점에 유의한다. 전자는 데이터가 base로 인코딩된 형태로 전송되고, 후자는 원시 바이트 문자열 형태로 전송된다.

[RFC7049]는 또한 Perl Compatible Regular Expressions(PCRE/PCRE2) 형식 [PCRE] 또는 JavaScript 정규 표현식 구문 [ECMA262]의 정규 표현식을 위한 태그 번호 35를 정의했다. 이러한 정규 표현식 명세의 최신 기술 수준은 그 이후 발전했으며 계속 발전하고 있으므로, 이 명세는 참조를 업데이트하려고 시도하지 않는다. 대신 이 태그는 자신들이 사용하는 특정 정규 표현식 변형을 대역 외로 지정하는 애플리케이션을 위해 계속 사용할 수 있다(아마도 PCRE와 ECMA262 모두의 정의된 공통 하위 집합으로 사용을 제한하여). 이 명세가 [RFC7049]를 넘어 태그 유효성을 명확히 하므로, 우리는 태그가 [RFC7049]에서 개방적인 방식으로 정의되었기 때문에, 포함된 모든 문자열 값은 CBOR 태그 수준에서 유효해야 한다는 점에 유의한다(하지만 그 후 애플리케이션 수준에서는 "예상됨"이 아닐 수 있다).

3.4.6. 자기 설명 CBOR

많은 애플리케이션에서는 CBOR가 데이터 항목의 인코딩에 사용되고 있음이 문맥에서 명확할 것이다. 예를 들어, 특정 프로토콜이 CBOR 사용을 지정하거나, 그 사용을 지정하는 미디어 타입이 표시될 수 있다. 그러나 그러한 문맥 정보가 없는 애플리케이션도 있을 수 있다. 예를 들어, CBOR 데이터가 구별 가능한 메타데이터가 없는 파일에 저장된 경우이다. 여기서는 데이터 자체에 몇 가지 구별 특성이 있으면 도움이 될 수 있다.

태그 번호 55799는 이 목적을 위해 정의되며, 애플리케이션이 지정한 대로 저장된 인코딩된 CBOR 데이터 항목의 시작 부분에서 사용하기 위한 것이다. 이는 자신이 둘러싸는 데이터 항목에 특별한 의미를 부여하지 않는다. 즉, 태그 번호 55799에 포함된 태그 내용의 의미는 태그 내용 자체의 의미와 정확히 동일하다.

이 태그 헤드의 직렬화는 0xd9d9f7이며, 자주 사용되는 파일 타입의 구별 표시로 사용되고 있지 않은 것으로 보인다. 특히, 0xd9d9f7은 뒤에 유효한 CBOR 데이터 항목이 이어지는 경우 어떤 Unicode 인코딩에서도 Unicode 텍스트의 유효한 시작이 아니다.

예를 들어, 디코더가 CBOR와 JSON을 모두 디코딩할 수 있다고 하자. 그러한 디코더는 두 형식을 기계적으로 구별해야 한다. 인코더가 디코더를 돕는 쉬운 방법은 전체 CBOR 항목에 태그 번호 55799를 붙이는 것이다. 이 태그의 직렬화는 JSON 텍스트의 시작에서 결코 발견되지 않을 것이다.

4. 직렬화 고려 사항

4.1. 선호 직렬화

데이터 모델 수준의 일부 값에 대해 CBOR는 여러 직렬화를 제공한다. 많은 애플리케이션에서는 인코더가 항상 선호 직렬화(선호 인코딩)를 선택하는 것이 바람직하다. 그러나 현재 명세는 이 선호를 강제하는 부담을 인코더나 디코더 어느 쪽에도 지우지 않는다.

일부 제약 디코더는 비선호 직렬화를 디코딩하는 능력이 제한될 수 있다. 예를 들어, 어떤 애플리케이션에서 1_000_000_000(십억) 미만의 정수만 예상된다면, 디코더는 정수의 64비트 인수를 디코딩하는 데 필요한 코드를 생략할 수 있다. 항상 선호 직렬화("선호 인코더")를 사용하는 인코더는 이 애플리케이션에서 발생할 수 있는 숫자에 대해 이 디코더와 상호 운용된다. 일반적으로 말해, 선호 인코더는 예컨대 항상 64비트 정수를 사용하는 인코더보다 더 보편적으로 상호 운용 가능하며 또한 낭비도 적다.

마찬가지로, 제약 인코더는 지원하는 표현 변형의 다양성이 제한되어 선호 직렬화를 내보내지 않을 수 있다("변형 인코더"). 예를 들어, 제약 인코더는 더 짧은 표현을 사용할 수 있더라도 자신이 인코딩하는 정수에 대해 항상 32비트 변형을 사용하도록 설계될 수 있다(64비트 변형으로만 표현할 수 있는 정수가 애플리케이션에 필요하지 않다고 가정). 선호 직렬화만 수신한다고 가정하지 않는 디코더 ("변형 허용 디코더")는 따라서 더 보편적으로 상호 운용 가능하다고 할 수 있다(다만 선호 직렬화를 수신하는 경우에 최적화할 수도 있다). CBOR 디코더의 완전한 구현은 정의상 변형 허용적이다. 이 구분은 CBOR 디코더의 제약 구현이 변형 인코더를 만나는 경우에만 관련된다.

선호 직렬화는 항상 인수(섹션 3)를 표현하는 가장 짧은 형식을 사용한다. 또한 인코딩되는 값을 보존하는 가장 짧은 부동소수점 인코딩을 사용한다.

부동소수점 값에 대한 선호 직렬화는 그 값을 보존하는 가장 짧은 부동소수점 인코딩이다. 예를 들어 숫자 5.5는 0xf94580, 숫자 5555.5는 0xfa45ad9c00이다. NaN 값의 경우, 더 짧은 가수를 오른쪽으로 0으로 채웠을 때 원래 NaN 값이 재구성된다면 더 짧은 인코딩이 선호된다 (많은 애플리케이션에서는 단일 NaN 인코딩 0xf97e00이면 충분하다).

항목의 직렬화가 시작되는 시점에 길이를 알고 있다면 항상 정길이 인코딩이 선호된다.

4.2. 결정적으로 인코딩된 CBOR

일부 프로토콜은 인코더가 특정한 결정적 형식의 CBOR만 내보내기를 원할 수 있다. 그러한 프로토콜은 또한 디코더가 입력이 그 결정적 형식인지 확인하게 할 수도 있다. 그러한 프로토콜은 "결정적 형식"이 무엇을 의미하는지, 그리고 인코더와 디코더가 무엇을 해야 하는지를 자유롭게 정의할 수 있다. 이 섹션은 그러한 결정적 형식의 기반이 될 수 있는 제한 집합을 정의한다.

4.2.1. 핵심 결정적 인코딩 요구 사항

CBOR 인코딩은 다음 제한을 만족하면 "핵심 결정적 인코딩 요구 사항"을 만족한다.

  • 선호 직렬화를 사용해야 MUST 한다. 특히 이는 정수, 주요 타입 2부터 5까지의 길이, 그리고 태그에 대한 인수(섹션 3 참조)가 가능한 한 짧아야 MUST 함을 의미한다. 예를 들면 다음과 같다.

    • 0부터 23까지 및 -1부터 -24까지는 주요 타입과 같은 바이트에 표현되어야 MUST 한다.
    • 24부터 255까지 및 -25부터 -256까지는 추가 uint8_t만으로 표현되어야 MUST 한다.
    • 256부터 65535까지 및 -257부터 -65536까지는 추가 uint16_t만으로 표현되어야 MUST 한다.
    • 65536부터 4294967295까지 및 -65537부터 -4294967296까지는 추가 uint32_t만으로 표현되어야 MUST 한다.

    부동소수점 값도 그 값을 보존하는 가장 짧은 형식을 사용해야 MUST 한다. 예를 들어 1.5는 0xf93e00(binary16)으로, 1000000.5는 0xfa49742408(binary32)로 인코딩된다. (이를 구현하는 한 방법은 모든 부동소수점을 64비트 부동소수점으로 시작하게 한 다음, 32비트 부동소수점으로 시험 변환을 수행하는 것이다. 결과가 같은 수치 값이면 더 짧은 형식을 사용하고, 16비트 부동소수점으로의 시험 변환으로 이 과정을 반복한다. 이는 양의 Infinity 및 음의 Infinity에 대해 16비트 부동소수점을 선택하는 데도 동작한다.)

  • 부정 길이 항목은 나타나서는 MUST NOT 안 된다. 대신 정길이 항목으로 인코딩할 수 있다.
  • 모든 맵의 키는 그 결정적 인코딩의 바이트 단위 사전식 순서로 정렬되어야 MUST 한다. 예를 들어, 다음 키들은 올바르게 정렬되어 있다.

    1. 10, 0x0a로 인코딩됨.
    2. 100, 0x1864로 인코딩됨.
    3. -1, 0x20으로 인코딩됨.
    4. "z", 0x617a로 인코딩됨.
    5. "aa", 0x626161로 인코딩됨.
    6. [100], 0x811864로 인코딩됨.
    7. [-1], 0x8120으로 인코딩됨.
    8. false, 0xf4로 인코딩됨.

4.2.2. 추가 결정적 인코딩 고려 사항

CBOR 태그는 결정적 인코딩에 대해 추가 고려 사항을 제시한다. CBOR 기반 프로토콜이 특정 태그의 존재와 부재에 대해 동일한 의미를 제공한다면(예: 날짜/시간 위치에서 태그 1 데이터 항목과 원시 숫자를 모두 허용하고 후자를 태그가 붙은 것처럼 처리), 결정적 형식은 "가장 짧은 형식" 원칙에 따라 태그의 존재를 허용하지 않을 것이다. 예를 들어, 어떤 프로토콜은 인코더에게 URL을 텍스트 문자열로 표현하거나, 섹션 3.4.5.3을 사용하여 텍스트 문자열을 포함하는 태그 번호 32로 표현하는 선택권을 줄 수 있다. 이 프로토콜의 결정적 인코딩은 태그가 존재해야 한다고 요구하거나 태그가 없어야 한다고 요구해야 하며, 둘 중 아무 것이나 허용해서는 안 된다.

특정 위치에서 특정 의미를 얻기 위해 태그를 요구하는 프로토콜에서는, 그 태그도 결정적 형식에 나타나야 한다. 결정적 인코딩 고려 사항은 태그의 내용에도 적용된다.

프로토콜에 태그 번호 2 또는 3 (섹션 3.4.3)을 사용하여 절댓값이 264 이상인 정수를 표현할 수 있는 필드가 포함되어 있다면, 그 프로토콜의 결정적 인코딩은 더 작은 정수도 이러한 태그를 사용하여 표현할지, 또는 주요 타입 0과 1을 사용하여 표현할지를 지정해야 한다. 선호 직렬화는 후자의 선택을 사용하므로, 이것이 권장된다.

기본 부동소수점 값(섹션 3.3)이나 태그(또는 둘 모두)를 사용하여 표현되는 부동소수점 값을 포함하는 프로토콜은, 다음과 같은 결정적 인코딩에 대한 추가 요구 사항을 정의해야 할 수 있다.

  • IEEE 부동소수점 값은 양의 0과 음의 0을 서로 다른 값으로 표현할 수 있지만, 애플리케이션은 이를 구별하지 않을 수 있으며, 모든 0 값을 양의 부호로 표현하고 음의 0을 허용하지 않기로 결정할 수 있다. (애플리케이션은 또한 64비트 또는 심지어 32비트 부동소수점 값을 표현할 필요가 전혀 없도록 부동소수점 값의 정밀도를 제한하고자 할 수도 있다.)
  • 프로토콜에 부동소수점 값을 표현할 수 있는 필드가 포함되어 있고, 정수와 부동소수점 값을 서로 바꿔 쓸 수 있다고 선언하는 특정 데이터 모델이 있다면, 그 프로토콜의 결정적 인코딩은 예를 들어 정수 1.0이 0x01(부호 없는 정수), 0xf93c00(binary16), 0xfa3f800000(binary32), 또는 0xfb3ff0000000000000(binary64) 중 무엇으로 인코딩되는지를 지정해야 한다. 이에 대한 예시 규칙은 다음과 같다.

    1. 64비트에 들어맞는 정수 값은 주요 타입 0과 1의 값으로 인코딩하고, 다른 값은 그 값을 정확히 표현하는 선호(16비트, 32비트 또는 64비트 중 가장 작은) 부동소수점 표현으로 인코딩한다.
    2. 정수 값이라도 모든 값을 그 값을 정확히 표현하는 선호 부동소수점 표현으로 인코딩한다. 또는
    3. 모든 값을 64비트 부동소수점 표현으로 인코딩한다.

    규칙 1은 정수와 부동소수점 값 사이의 경계를 걸치고, 규칙 3은 선호 직렬화를 사용하지 않으므로, 많은 경우 규칙 2가 좋은 선택일 수 있다.

  • NaN이 허용된 값이고, NaN 페이로드나 signaling NaN을 지원할 의도가 없다면, 프로토콜은 단일 표현, 일반적으로 0xf97e00을 선택해야 한다. 그 단순한 선택이 불가능하다면, NaN 처리에 특별한 주의가 필요하다.
  • 비정규수(주어진 IEEE 754 숫자 형식에서 가능한 가장 낮은 지수를 가진 0이 아닌 수)는 일부 부동소수점 구현에서 출력 시 0으로 플러시되거나 입력 시 0으로 처리될 수 있다. 프로토콜의 결정적 인코딩은 그러한 구현을 명시적으로 수용하는 한편, 다른 구현에는 교환에서 비정규수를 제외하고 대신 0을 교환하도록 부담을 부과하고자 할 수 있다.
  • 같은 숫자는 서로 다른 십진 분수, 서로 다른 큰 부동소수점 수, 그리고 숫자 값을 표현하도록 정의될 수 있는 다른 태그 아래의 서로 다른 형식으로 표현될 수 있다. 구현에 따라, 이러한 형식(또는 기본 일반 데이터 모델의 형식) 중 어느 것이 동등한지 판단하는 것이 항상 실용적이지 않을 수 있다. 숫자의 표현 형식에 대해 이러한 종류의 선택지를 제시하는 애플리케이션 프로토콜은 결정적 인코딩을 위한 형식을 어떻게 선택해야 하는지 명시해야 한다.

4.2.3. 길이 우선 맵 키 정렬

핵심 결정적 인코딩 요구 사항(섹션 4.2.1)은 섹션 3.9 of [RFC7049]에서 제안된 순서 (그곳에서는 "Canonical CBOR"라고 불림)와 다른 순서로 맵 키를 정렬한다. [RFC7049]에 지정된 순서와 호환되어야 하는 프로토콜은 대신 이 명세의 "길이 우선 핵심 결정적 인코딩 요구 사항"의 관점에서 지정될 수 있다.

CBOR 인코딩은 핵심 결정적 인코딩 요구 사항을 만족하되, 모든 맵의 키가 다음과 같이 정렬되어야 MUST 한다는 점만 다르면 "길이 우선 핵심 결정적 인코딩 요구 사항"을 만족한다.

  1. 두 키의 길이가 다르면, 더 짧은 것이 먼저 정렬된다.
  2. 두 키의 길이가 같으면, (바이트 단위) 사전식 순서에서 더 낮은 값을 가진 것이 먼저 정렬된다.

예를 들어, 길이 우선 핵심 결정적 인코딩 요구 사항에 따르면 다음 키들은 올바르게 정렬되어 있다.

  1. 10, 0x0a로 인코딩됨.
  2. -1, 0x20으로 인코딩됨.
  3. false, 0xf4로 인코딩됨.
  4. 100, 0x1864로 인코딩됨.
  5. "z", 0x617a로 인코딩됨.
  6. [-1], 0x8120으로 인코딩됨.
  7. "aa", 0x626161로 인코딩됨.
  8. [100], 0x811864로 인코딩됨.

5. CBOR 기반 프로토콜 만들기

CBOR와 같은 데이터 형식은 형식 협상이 없는 환경에서 자주 사용된다. CBOR의 특정 설계 목표는 포함되거나 가정된 스키마를 전혀 필요로 하지 않는 것이다. 디코더는 CBOR 항목을 가져와 다른 지식 없이 디코딩할 수 있다.

물론 실제 구현에서는 인코더와 디코더가 CBOR 데이터 항목에 무엇이 있어야 하는지에 대해 공유된 관점을 갖게 된다. 예를 들어, 합의된 형식은 "항목은 첫 번째 값이 UTF-8 문자열이고, 두 번째 값이 정수이며, 이후 값은 0개 이상의 부동소수점 수인 배열이다" 또는 "항목은 키로 바이트 문자열을 가지고, 키가 0xab01인 쌍을 포함하는 맵이다"일 수 있다.

CBOR 기반 프로토콜은 디코더가 유효하지 않거나 기타 예상치 못한 데이터를 어떻게 처리하는지 지정해야 MUST 한다. CBOR 기반 프로토콜은 임의의 유효한 데이터를 예상치 못한 것으로 취급한다고 지정할 MAY 수 있다. CBOR 기반 프로토콜의 인코더는 유효한 항목만 생성해야 MUST 한다. 즉, 프로토콜은 유효하지 않은 항목을 사용하도록 설계될 수 없다. 인코더는 자신이 사용되는 프로토콜에 필요한 만큼 많거나 적은 타입의 값을 인코딩할 수 있으며, 디코더는 자신이 사용되는 프로토콜에 필요한 만큼 많거나 적은 타입의 값을 이해할 수 있다. 이러한 제한의 부재는 CBOR가 극도로 제약된 환경에서 사용될 수 있게 한다.

이 섹션의 나머지는 CBOR 기반 프로토콜을 만들 때의 몇 가지 고려 사항을 논의한다. 몇 가지 예외를 제외하면, 이는 권고적일 뿐이며 BCP 14 [RFC2119] [RFC8174]의 의미에서 "MAY"로 해석될 수 있는 단어 이외의 BCP 14 언어를 명시적으로 제외한다. 예외들은 다양한 일반 및 애플리케이션별 인코더와 디코더를 모두 사용하면서 CBOR 기반 프로토콜의 상호 운용성을 촉진하는 것을 목표로 한다.

5.1. 스트리밍 애플리케이션에서의 CBOR

스트리밍 애플리케이션에서 데이터 스트림은 CBOR 데이터 항목들의 시퀀스를 연속으로 이어 붙인 것으로 구성될 수 있다. 이러한 환경에서는 이전 데이터 항목의 끝 이후에 데이터가 발견되면 디코더가 즉시 새 데이터 항목의 디코딩을 시작한다.

데이터 항목을 구성하는 모든 바이트가 디코더에 즉시 제공되지는 않을 수 있다. 일부 디코더는 완전한 데이터 항목을 애플리케이션에 제시할 수 있을 때까지 추가 데이터를 버퍼링한다. 다른 디코더는 최상위 데이터 항목에 대한 부분 정보를 애플리케이션에 제시할 수 있다. 예를 들어 이미 디코딩할 수 있는 중첩 데이터 항목이나, 아직 완전히 도착하지 않은 바이트 문자열의 일부도 제시할 수 있다. 그러한 애플리케이션은 또한 애플리케이션에 제시되는 점진적 데이터에 대해 원하는 보호를 제공할 수 있는, 일치하는 스트리밍 보안 메커니즘을 가져야 MUST 한다.

일부 애플리케이션과 프로토콜은 부정 길이 인코딩을 사용하고 싶어 하지 않을 수 있음에 유의한다. 부정 길이 인코딩을 사용하면 인코더가 개수를 세기 위해 모든 데이터를 마샬링할 필요가 없지만, 디코더는 항목의 끝을 기다리는 동안 증가하는 양의 메모리를 할당해야 한다. 이는 일부 애플리케이션에는 괜찮을 수 있지만 다른 애플리케이션에는 그렇지 않을 수 있다.

5.2. 일반 인코더 및 디코더

일반 CBOR 디코더는 모든 올바른 형식의 인코딩된 CBOR 데이터 항목을 디코딩하고 그 데이터 항목을 애플리케이션에 제시할 수 있다. 부록 C를 참조한다. (진단 표기법(섹션 8)은 올바른 형식의 CBOR 값을 사람에게 제시하는 데 사용될 수 있다.)

일반 CBOR 인코더는 인코더가 알지 못하는 단순 값과 태그를 포함하여, 애플리케이션이 올바른 형식의 어떤 값이든 CBOR 데이터 항목으로 인코딩하도록 지정할 수 있는 애플리케이션 인터페이스를 제공한다.

CBOR가 이러한 경우를 최소화하려고 시도하더라도, 모든 올바른 형식의 CBOR 데이터가 유효한 것은 아니다. 예를 들어, 인코딩된 텍스트 문자열 0x62c0ae는 유효한 UTF-8을 포함하지 않는다 ([RFC3629]가 항상 가장 짧은 형식을 사용하도록 요구하기 때문). 따라서 이는 유효한 CBOR 항목이 아니다. 또한 특정 태그는 의미적 제약을 만들 수 있으며, 예를 들어 큰 수 태그가 다른 태그를 둘러싸거나, 태그 번호 0의 인스턴스가 바이트 문자열을 포함하거나 [RFC3339]date-time 생성 규칙과 일치하지 않는 내용을 가진 텍스트 문자열을 포함하는 경우 이러한 제약이 위반될 수 있다. 일반 인코더와 디코더가 유효하지 않은 데이터 처리를 가능하게 하기 위해 애플리케이션 인터페이스에 부자연스러운 선택을 해야 한다는 요구 사항은 없다. 일반 인코더와 디코더는 인코더/디코더가 작성된 시점에 특정 코드포인트가 등록되어 있지 않더라도 단순 값과 태그를 전달할 것으로 기대된다 (섹션 5.4).

5.3. 항목의 유효성

올바른 형식이지만 유효하지 않은 CBOR 데이터 항목(섹션 1.2)은 그 안에 인코딩된 데이터를 CBOR 데이터 모델에서 해석하는 데 문제를 제기한다. CBOR 기반 프로토콜은 여러 계층으로 지정될 수 있으며, 이때 하위 계층은 자신들이 전달하는 일부 CBOR 데이터의 의미를 처리하지 않는다. 이러한 계층은 처리하지 않는 데이터의 유효성 오류를 알아차릴 수 없으며, 그 데이터를 있는 그대로 전달해야 MUST 한다. 유효하지 않은 CBOR 항목의 의미를 처리하는 첫 번째 계층은 두 가지 선택지 중 하나를 선택해야 MUST 한다.

  1. 문제가 있는 항목을 오류 표시자로 바꾸고 다음 항목으로 계속한다. 또는
  2. 오류를 내고 처리를 완전히 중지한다.

CBOR 기반 프로토콜은 자신들의 디코더가 마주칠 수 있는 각 종류의 유효하지 않은 항목에 대해 이러한 옵션 중 어느 것을 취하는지 지정해야 MUST 한다.

이러한 문제는 CBOR의 기본 유효성 수준이나 태그(태그 유효성)의 맥락에서 발생할 수 있다.

5.3.1. 기본 유효성

기본 일반 데이터 모델에서는 두 종류의 유효성 오류가 발생할 수 있다.

맵의 중복 키:
일반 디코더(섹션 5.2)는 네이티브 CBOR 데이터 모델을 사용하여 데이터를 애플리케이션에 제공한다. 그 데이터 모델은 맵(고유한 키를 가진 키-값 매핑)을 포함하지만, 멀티맵(여러 항목이 같은 키를 가질 수 있는 키-값 매핑)은 포함하지 않는다. 따라서 중복 키가 있는 CBOR 맵 항목을 받은 일반 디코더는 그 키의 인스턴스 하나만 있는 맵으로 디코딩하거나, 처리를 완전히 중지할 수 있다. 반면에 "스트리밍 디코더"는 이를 알아차리지 못할 수도 있다. 맵의 키에 대한 추가 논의는 섹션 5.6을 참조한다.
유효하지 않은 UTF-8 문자열:
디코더는 UTF-8 문자열(주요 타입 3)의 바이트 시퀀스가 실제로 유효한 UTF-8인지 검증하고 적절히 반응하기를 원할 수도 있고 원하지 않을 수도 있다.

5.3.2. 태그 유효성

기본 일반 데이터 모델에 태그를 추가함으로써 두 가지 추가적인 유효성 오류가 도입된다.

태그 내용에 허용되지 않는 타입:
태그 번호(섹션 3.4)는 어떤 타입의 데이터 항목이 그 태그 내용으로 사용되어야 하는지를 지정한다. 예를 들어, 부호 없는 또는 음의 큰 수에 대한 태그 번호는 바이트 문자열에 붙도록 되어 있다. 태그가 지정된 데이터 항목을 네이티브 표현(이 예에서는 네이티브 큰 정수)으로 디코딩하는 디코더는 태그가 지정되는 데이터 항목의 타입을 확인할 것으로 기대된다. 그러한 네이티브 표현을 사용할 수 없는 환경의 디코더도 자신이 알고 있는 태그에 대해서는 검사를 수행하고 적절히 반응할 수 있다.
태그 내용에 허용되지 않는 값:
데이터 항목의 타입은 태그의 내용에 허용될 수 있지만, 특정 값은 허용되지 않을 수 있다. 예를 들어 "yesterday"라는 값은 올바르게 텍스트 문자열이더라도 태그 0의 내용으로는 허용되지 않는다. 일반적으로 그러한 태그를 동등한 플랫폼 타입으로 받아들이는 디코더는 이 태그를 알 수 없는 태그 번호의 태그를 제시하는 방식과 유사하게 애플리케이션에 제시할 수 있다 (섹션 5.4).

5.4. 유효성 및 발전

유효성 검사를 수행하는 디코더는 유효성 오류가 있는 데이터 항목을 신뢰성 있게 감지하기 위해 노력을 들인다. 예를 들어, 그러한 디코더는 이전 하위 섹션에 나열된 유효성 오류 중 어느 것이든 포함하는 CBOR 데이터 항목에 대해 오류를 보고하고 데이터를 반환하지 않는 API를 가져야 한다.

"Concise Binary Object Representation (CBOR) Tags" 레지스트리(섹션 9.2)에 정의된 태그 집합과 "Concise Binary Object Representation (CBOR) Simple Values" 레지스트리(섹션 9.1)에 정의된 단순 값 집합은 일반 디코더가 이해하는 집합을 넘어 언제든지 증가할 수 있다. 유효성 검사 디코더는 자신이 인식하지 못하는 그러한 경우를 만나면 다음 두 가지 중 하나를 수행할 수 있다.

  • 오류를 보고하고 데이터를 반환하지 않을 수 있다. 이 경우를 오류로 처리하면 고착화를 유발할 수 있으므로 권장되지 않는다는 점에 유의한다. 이 오류는 그 자체로는 유효성 오류가 아니다. 이러한 종류의 오류는 이것이 알려진 경우였다면 유효성 검사를 수행했을 디코더가 제기할 가능성이 더 높다.
  • 알 수 없는 항목(타입, 값, 그리고 태그의 경우 디코딩된 태그가 지정된 데이터 항목)을 디코더를 호출한 애플리케이션에 내보내고, 그 후 디코더가 해당 태그 번호 또는 단순 값을 인식하지 못했다는 표시를 애플리케이션에 제공할 수 있다.

후자의 접근 방식은 유효성 검사를 지원하지 않는 디코더에도 적합하며, 새로 등록된 태그와 단순 값에 대해 호출 애플리케이션과 동시에 인코더를 업데이트해야 할 필요 없이 전방 호환성을 제공한다. (이를 위해 디코더의 API는 호출 애플리케이션이 프로그램에 적합한 방식으로 처리할 수 있도록 알 수 없는 항목을 표시하는 능력이 필요하다.)

유효성 검사에 필요한 처리 중 일부는 상당한 비용을 가질 수 있으므로(특히 맵의 중복 감지), 유효성 검사 지원은 모든 CBOR 디코더에 부과되는 요구 사항이 아니다.

일부 인코더는 애플리케이션이 유효한 CBOR가 인코더에서 나오도록 입력 데이터를 제공한다고 가정한다. 일반 인코더는 또한 애플리케이션이 실제로 API에 부합하는 데이터를 제공하는지 여부와 무관하게 자신의 출력을 유효한 CBOR로 신뢰성 있게 제한하는 유효성 검사 모드를 제공하고자 할 수 있다.

5.5. 숫자

CBOR 기반 프로토콜은 서로 다른 언어 환경이 표현 가능한 숫자의 범위와 정밀도에 서로 다른 제한을 부과한다는 점을 고려해야 한다. 예를 들어, 기본 JavaScript 숫자 시스템은 모든 숫자를 부동소수점 값으로 취급하므로, 53개를 초과하는 유효 비트를 가진 정수를 디코딩할 때 정밀도가 조용히 손실될 수 있다. 또 다른 예는 CBOR가 정수 표현의 부호 비트를 주요 타입에 보관하므로, 특정 길이의 부호 있는 숫자에 대해 동일한 길이의 일반적인 플랫폼 부호 있는 정수 표현보다 한 비트가 더 많다는 것이다 (예: 1+8바이트 정수의 경우 -264..264-1, 8바이트 int64_t의 경우 -263..263-1). 숫자를 사용하는 프로토콜은 디코더와 수신 애플리케이션에서 비사소한 숫자를 어떻게 처리할지에 대한 기대를 정의해야 한다.

부동소수점 수를 포함하는 CBOR 기반 프로토콜은 세 가지 형식(반정밀도, 단정밀도, 배정밀도) 중 어느 것이 지원되어야 하는지를 제한할 수 있다. 정수 전용 애플리케이션의 경우, 프로토콜은 부동소수점 값의 사용을 완전히 배제하고자 할 수 있다.

간결성을 위해 설계된 CBOR 기반 프로토콜은 애플리케이션에 필요한 것보다 긴 특정 정수 인코딩을 배제하여, 예를 들어 64비트 정수를 구현할 필요를 줄이고자 할 수 있다. 인코더가 주어진 값을 표현할 수 있는 가장 간결한 정수 표현을 사용할 것이라는 기대가 있다. 그러나 결정적 인코딩을 요구하지 않는 간결한 애플리케이션은 주어진 크기의 정수를 디코딩할 수 있는 한, 필요한 것보다 긴 인코딩(예: "0"을 0b000_11001 뒤에 두 바이트 0x00이 오는 방식으로 인코딩)을 사용하는 값을 받아들여야 한다. 유사한 고려 사항은 부동소수점 값에도 적용된다. 선호 직렬화와 필요한 것보다 긴 직렬화를 모두 디코딩하는 것이 권장된다.

특정 숫자를 정수로 표현할지, 또는 십진 분수나 큰 부동소수점 수로 표현할지 선택지를 제공하는 제약 애플리케이션용 CBOR 기반 프로토콜(예: 지수가 작고 음이 아닌 경우)은 정수 표현이 직접 사용된다는 구현 품질 기대를 표현하고자 할 수 있다.

5.6. 맵의 키 지정

인코딩 및 디코딩 애플리케이션은 맵에서 어떤 타입의 키가 사용될 것인지에 대해 합의해야 한다. JSON 기반 애플리케이션과 상호 운용해야 하는 애플리케이션에서는 키를 텍스트 문자열로만 제한함으로써 변환이 단순해진다. 그렇지 않으면 다른 CBOR 타입에서 텍스트 문자열로의 지정된 매핑이 있어야 하며, 이는 종종 구현 오류로 이어진다. 키가 본질적으로 숫자인 애플리케이션에서, 그리고 키의 숫자 순서가 애플리케이션에 중요하다면, 키에 숫자를 직접 사용하는 것이 유용하다.

여러 타입의 키가 사용될 경우, 사용될 특정 프로그래밍 환경에서 이러한 타입들이 어떻게 표현될지를 고려해야 한다. 예를 들어, JavaScript Maps [ECMA262]에서는 정수 1인 키를 부동소수점 1.0인 키와 구별할 수 없다. 이는 정수 키가 사용된다면 프로토콜이 같은 맵에서 값이 우연히 정수인 부동소수점 키의 사용을 피해야 함을 의미한다.

CBOR 데이터 항목 안에 중첩된 데이터 항목을 디코딩하는 즉시 전달하는 디코더("스트리밍 디코더")는 종종 맵에서 키의 고유성을 확인하는 데 필요한 상태를 유지하지 않는다. 마찬가지로, 포함하는 데이터 항목이 완전히 사용 가능해지기 전에 데이터 항목의 인코딩을 시작할 수 있는 인코더("스트리밍 인코더")는 데이터 소스가 고유성을 유지한다고 믿음으로써 자신의 오버헤드를 크게 줄이고자 할 수 있다.

CBOR 기반 프로토콜은 수신 애플리케이션이 맵에서 여러 동일한 키를 보았을 때 무엇을 해야 하는지 정의해야 MUST 한다. 프로토콜의 결과 규칙은 CBOR 데이터 모델을 존중해야 MUST 한다. 즉, 동일한 키를 가진 항목에 대한 특정 처리를 규정할 수 없으며, 다만 맵에 동일한 키가 있으면 잘못된 형식의 맵을 나타내고 디코더가 오류로 중지해야 한다는 규칙을 둘 수는 있다. 중복 키를 가진 항목을 보이는 맵을 처리할 때, 일반 디코더는 다음 중 하나를 수행할 수 있다.

  • 중복 키가 있는 맵을 받아들이지 않는다 (즉, 맵에 대한 유효성을 강제한다. 섹션 5.4도 참조). 이러한 일반 디코더는 보편적으로 유용하다. 애플리케이션은 여전히 애플리케이션 규칙에 따라 자체 중복 검사를 수행해야 할 수 있다(예를 들어, 특정 맵의 맵 키 위치에서 애플리케이션이 정수와 부동소수점 값을 동등하게 취급하는 경우).
  • 중복 키가 있는 항목을 포함하여 모든 맵 항목을 애플리케이션에 전달한다. 이는 애플리케이션 규칙이 일반 데이터 모델 규칙과 동일하더라도, 애플리케이션이 중복 키를 처리(검사)해야 함을 요구한다.
  • 중복 키가 있는 항목 중 일부를 잃는다. 예를 들어 같은 키를 가진 항목들 중 마지막(또는 첫 번째) 항목만 전달한다. 그러한 일반 디코더를 사용하면 애플리케이션은 특정 키에 대해 실행마다, 그리고 일반 디코더마다 서로 다른 결과를 얻을 수 있으며, 어떤 값이 반환되는지는 일반 디코더 구현과 맵 안의 실제 키 순서에 기반한다. 특히, 애플리케이션은 반드시 모든 항목을 보는 것은 아니므로 자체적으로 키 고유성을 검증할 수 없으며, 키 고유성을 검증해야 한다면 그러한 일반 디코더를 사용할 수 없을 수 있다. 이러한 일반 디코더는 데이터 소스와 전송이 항상 유효한 맵을 제공하는 상황에서만 사용할 수 있다. 데이터 소스와 전송이 공격받을 수 있다면 이는 불가능하다.

일반 디코더는 이 세 접근 방식 중 어느 것을 구현하는지 문서화해야 한다.

맵에 대한 CBOR 데이터 모델은 맵 표현에서 키/값 쌍의 순서에 의미를 부여하는 것을 허용하지 않는다. 따라서 CBOR 기반 프로토콜은 맵에서 키/값 쌍의 순서를 바꾸는 것이 의미를 바꾼다고 지정해서는 MUST NOT 안 된다. 다만 예를 들어 결정적 인코딩(섹션 4.2)의 요구 사항을 충족하지 않는 순서를 허용하지 않는다고 지정하는 것은 예외이다. (맵 순서가 타이밍, 캐시 사용 및 기타 잠재적 부채널에 미치는 2차 효과는 의미의 일부로 간주되지 않지만, 프로토콜이 결정적 인코딩 형식을 요구할 충분한 이유가 될 수는 있다.)

제약 장치용 애플리케이션은 자주 사용되는 키가 적은 수로 있는 맵을 가진 경우, 작은 정수를 키로 사용하는 것을 고려해야 한다. 예를 들어 24개 이하의 키 집합은 부호 없는 정수로 한 바이트에 인코딩될 수 있으며, 음의 정수도 사용한다면 최대 48개까지 가능하다. 덜 자주 발생하는 키는 더 긴 인코딩을 가진 정수를 사용할 수 있다.

5.6.1. 키의 동등성

CBOR 데이터 항목에 적용되는 특정 데이터 모델은 맵에 나타나는 키가 중복인지 서로 다른지를 결정하는 데 사용된다.

일반 데이터 모델 수준에서, 수치적으로 동등한 정수와 부동소수점 값은 서로 구별되며, 다양한 큰 숫자(태그 2부터 5까지)와도 구별된다. 마찬가지로, 텍스트 문자열은 같은 바이트로 구성되어 있더라도 바이트 문자열과 구별된다. 태그가 지정된 값은 태그가 없는 값이나 다른 태그 번호로 태그가 지정된 값과 구별된다.

이러한 각 그룹 안에서, 숫자 값은 수치적으로 같지 않으면 서로 구별된다(특히 -0.0은 0.0과 같다). 맵 키 동등성의 목적상, NaN 값은 두 가수를 오른쪽에서 64비트까지 0으로 확장한 뒤 같은 가수를 가지면 동등하다.

바이트 문자열과 텍스트 문자열은 모두 바이트 단위로 비교되고, 배열은 요소 단위로 비교되며, 같은 수의 바이트/요소와 같은 위치의 같은 값을 가지면 같다. 두 맵은 순서와 관계없이 같은 쌍 집합을 가지면 같다. 쌍은 키와 값이 모두 같으면 같다.

태그가 지정된 값은 태그 번호와 태그 내용이 모두 같으면 같다. (특정 태그에 대한 처리를 제공하는 일반 디코더는 예를 들어 태그 2 또는 태그 3의 내용에 선행 0이 있는 경우처럼 일부 의미적으로 동등한 값을 구별하지 못할 수도 있음에 유의한다 (섹션 3.4.3).) 단순 값은 단순히 같은 값을 가지면 같다. 일반 데이터 모델에서는 그 밖의 것은 아무것도 같지 않다. 단순 값 2는 정수 2와 동등하지 않으며, 배열은 결코 맵과 동등하지 않다.

섹션 2.2에서 논의한 것처럼, 특정 데이터 모델은 일반 데이터 모델에서는 서로 다른 값들을 맵 키 비교 목적상 동등하게 만들 수 있다. 이는 일반 디코더가 애플리케이션에 디코딩된 맵을 전달할 수 있으며, 그 애플리케이션이 중복 맵 키를 검사해야 함을 의미한다는 점에 유의한다 (또는 디코더가 애플리케이션을 위해 이 서비스를 수행하는 프로그래밍 인터페이스를 제공할 수 있다). 특정 데이터 모델은 일반 데이터 모델 수준에서 이 목적상 같은 맵 키 값을 구별할 수 없다.

5.7. 정의되지 않은 값

일부 CBOR 기반 프로토콜에서는 undefined의 단순 값(섹션 3.3)이 인코더에 의해 인코딩 문제가 있는 데이터 항목의 대체물로 사용될 수 있다. 이는 포함하는 나머지 데이터 항목들이 해를 끼치지 않고 인코딩될 수 있도록 하기 위한 것이다.

6. CBOR와 JSON 간 데이터 변환

이 섹션은 CBOR와 JSON 간 변환에 대한 비규범적 조언을 제공한다. 변환기 구현은 여기의 조언 중 원하는 것을 MAY 사용할 수 있다.

JSON 텍스트는 인코딩된 바이트 시퀀스가 아니라 문자 시퀀스인 반면, CBOR 데이터 항목은 문자가 아니라 바이트로 구성된다는 점에 주목할 가치가 있다.

6.1. CBOR에서 JSON으로 변환

CBOR의 대부분 타입은 JSON에 직접적인 대응물이 있다. 그러나 일부는 그렇지 않으며, CBOR-to-JSON 변환기를 구현하는 사람은 그런 경우 무엇을 할지 고려해야 한다. 다음 비규범적 조언은 이들을 JSON null과 같은 단일 대체 값으로 변환하는 방식으로 다룬다.

  • 정수(주요 타입 0 또는 1)는 JSON 숫자가 된다.
  • 제안된 인코딩을 지정하는 태그에 포함되어 있지 않은 바이트 문자열(주요 타입 2)은 패딩 없는 base64url로 인코딩되어 JSON 문자열이 된다.
  • UTF-8 문자열(주요 타입 3)은 JSON 문자열이 된다. JSON은 특정 문자([RFC8259], 섹션 7)를 이스케이프해야 한다는 점에 유의한다: 따옴표(U+0022), 역 솔리더스(U+005C), 그리고 "C0 제어 문자"(U+0000부터 U+001F까지). 다른 모든 문자는 JSON UTF-8 문자열에 변경 없이 복사된다.
  • 배열(주요 타입 4)은 JSON 배열이 된다.
  • 맵(주요 타입 5)은 JSON 객체가 된다. 이는 모든 키가 UTF-8 문자열인 경우에만 직접 가능하다. 변환기는 다른 키도 UTF-8 문자열로 변환할 수 있다(예: 정수를 그 십진수 표현을 포함하는 문자열로 변환). 그러나 그렇게 하면 키 충돌의 위험이 생긴다. 또한 아래에서 제안한 것처럼 UTF-8 문자열의 태그를 무시하면, 태그가 다르더라도 문자열이 같을 때 키 충돌이 발생한다는 점에 유의한다.
  • False(주요 타입 7, 추가 정보 20)는 JSON false가 된다.
  • True(주요 타입 7, 추가 정보 21)는 JSON true가 된다.
  • Null(주요 타입 7, 추가 정보 22)은 JSON null이 된다.
  • 부동소수점 값(주요 타입 7, 추가 정보 25부터 27까지)은 유한한 경우 JSON 숫자가 된다 (즉, JSON 숫자로 표현될 수 있다). 값이 비유한값(NaN, 또는 양의 Infinity나 음의 Infinity)이면 대체 값으로 표현된다.
  • 다른 모든 단순 값(주요 타입 7, 아직 논의되지 않은 임의의 추가 정보 값)은 대체 값으로 표현된다.
  • 큰 수(주요 타입 6, 태그 번호 2 또는 3)는 그 바이트 문자열을 패딩 없는 base64url로 인코딩하여 JSON 문자열이 되는 방식으로 표현된다. 태그 번호 3(음의 큰 수)의 경우, base 인코딩된 값 앞에 "~"(ASCII 물결표)가 삽입된다. (숫자 대신 이진 블롭으로 변환하는 것은 JSON 디코더에서 발생할 가능성이 높은 숫자 오버플로를 방지하기 위한 것이다.)
  • 인코딩 힌트가 있는 바이트 문자열(주요 타입 6, 태그 번호 21부터 23까지)은 힌트가 설명하는 대로 인코딩되어 JSON 문자열이 된다.
  • 다른 모든 태그(주요 타입 6, 임의의 다른 태그 번호)의 경우, 태그 내용은 JSON 값으로 표현되며 태그 번호는 무시된다.
  • 부정 길이 항목은 변환 전에 정길이로 만들어진다.

CBOR-to-JSON 변환기는 상호 운용성을 극대화하고 JSON 출력이 예측 가능한 결과로 처리될 수 있다는 신뢰를 높이기 위해 JSON 프로필 I-JSON [RFC7493]을 따르고자 할 수 있다. 예를 들어, 이는 안정적으로 표현될 수 있는 정수 범위뿐 아니라, 오래된 JSON 구현이 지원할 수 있는 최상위 항목에도 영향을 미친다.

6.2. JSON에서 CBOR로 변환

모든 JSON 값은 일단 디코딩되면 하나 이상의 CBOR 값으로 직접 매핑된다. 어떤 종류의 CBOR 생성에서와 마찬가지로, 숫자 표현과 관련하여 결정을 내려야 한다. 제안되는 변환에서는 다음과 같다.

  • 소수 부분이 없는 JSON 숫자(정수 숫자)는 가장 짧은 형식을 선택하여 정수(주요 타입 0 및 1, 가능한 경우 주요 타입 6, 태그 번호 2 및 3)로 표현된다. 구현이 정의한 임계값보다 긴 정수는 대신 부동소수점 값으로 표현될 수 있다. 정수로 표현되는 기본 범위는 -253+1..253-1이다(JSON을 디코딩하는 데 자주 사용되는 binary64 표현에서 정확한 정수 범위를 완전히 활용함 [RFC7493]). CBOR 기반 프로토콜 또는 일반 변환기 구현은 -232..232-1 또는 -264..264-1(각각 uint32_t 또는 uint64_t로 CBOR에서 사용할 수 있는 정수 범위를 완전히 사용함), 또는 심지어 -231..231-1 또는 -263..263-1(2의 보수 부호 있는 정수에서 널리 쓰이는 범위를 사용함)을 선택할 수 있다. (JSON이 JavaScript 구현에서 생성되었다면, 그 정밀도는 이미 최대 53비트로 제한된다.)
  • 소수 부분이 있는 숫자는 부동소수점 값으로 표현되며, IEEE 754 binary64가 제공하는 정밀도를 기반으로 십진수-이진수 변환을 수행한다. JSON 숫자의 수학적 값은 [IEEE754]의 섹션 4.3.1에 있는 roundTiesToEven 절차를 사용하여 binary64로 변환된다. 그런 다음 CBOR로 인코딩할 때, 선호 직렬화는 이 변환 결과를 정확히 표현하는 가장 짧은 부동소수점 표현을 사용한다. 예를 들어, 1.5는 16비트 부동소수점 값으로 표현된다(다만 모든 구현이 최소 형식을 효율적으로 찾을 수 있는 것은 아니다). 기본 binary64 정밀도를 사용하는 대신, 표현되는 값의 정밀도에 영향을 주는 구현 정의 변환 정밀도 제한이 있을 수 있다. 십진 표현은 프로토콜에서 지정한 경우에만 CBOR 쪽에서 사용해야 한다.

CBOR는 일반적으로 JSON보다 더 간결한 인코딩을 제공하도록 설계되었다. 떠올릴 수 있는 한 가지 구현 전략은 단일 버퍼 안에서 JSON-to-CBOR 인코딩을 제자리에서 수행하는 것이다. 이 전략은 병적인 여러 경우를 신중하게 고려해야 한다. 예를 들어, 이스케이프가 없거나 매우 적고 255바이트보다 길거나 훨씬 긴 일부 문자열은 CBOR에서 UTF-8 문자열로 인코딩될 때 확장될 수 있다. 마찬가지로, 일부 이진 부동소수점 표현은 JSON의 짧은 십진 표현(1.1, 1e9)에서 확장을 일으킬 수 있다. 이를 올바르게 처리하기는 어려울 수 있으며, 그 결과 발생하는 취약점은 공격자에 의해 악용될 수 있다.

7. CBOR의 향후 발전

성공적인 프로토콜은 시간이 지나면서 발전한다. 새로운 아이디어가 나타나고, 구현 플랫폼이 개선되며, 관련 프로토콜이 개발되고 발전하고, 애플리케이션과 프로토콜의 새로운 요구 사항이 추가된다. 따라서 프로토콜 발전을 촉진하는 것은 모든 프로토콜 개발에서 중요한 설계 고려 사항이다.

CBOR를 사용할 프로토콜을 위해, CBOR는 그 발전을 촉진하는 유용한 메커니즘을 제공한다. 이를 위한 모범 사례는 잘 알려져 있으며, 특히 JSON 기반 프로토콜의 JSON 형식 개발에서 알려져 있다. 따라서 그러한 모범 사례는 이 명세의 범위 밖이다.

그러나 CBOR 자체의 발전을 촉진하는 것은 그 범위 안에 매우 잘 들어맞는다. CBOR는 CBOR 기반 프로토콜 개발을 위한 안정적인 기반을 제공하면서도 발전할 수 있도록 설계되었다. 성공적인 프로토콜은 수십 년 동안 살아남을 수 있으므로, CBOR는 수십 년 동안 사용되고 발전하도록 설계되어야 한다. 이 섹션은 CBOR의 발전에 대한 몇 가지 지침을 제공한다. 이는 이 문서의 다른 부분보다 필연적으로 더 주관적이다. 또한 프로토콜 개발에 관한 교과서가 되지 않도록 필연적으로 불완전하다.

7.1. 확장 지점

프로토콜 설계에서 발전의 기회는 종종 확장 지점의 형태로 포함된다. 예를 들어, 처음부터 완전히 할당되지 않은 코드포인트 공간이 있을 수 있으며, 프로토콜은 처음 할당된 것보다 더 많은 코드포인트를 사용하기 시작하는 구현을 용인하고 수용하도록 설계된다.

필요한 범위를 예측하기 어려울 수 있으므로 코드포인트 공간의 크기를 정하는 것은 어려울 수 있다. 프로토콜 설계는 의도된 프로토콜 수명 동안 천천히 채워질 수 있을 만큼 코드포인트 공간을 충분히 크게 만들도록 시도해야 한다.

CBOR에는 세 가지 주요 확장 지점이 있다.

"simple" 공간(주요 타입 7의 값):
24개의 효율적인 값(그리고 224개의 약간 덜 효율적인 값) 중 소수만 할당되어 있다. 알 수 없는 단순 데이터 항목을 수신하는 구현은 그 값의 구조가 실제로 단순하다면 이를 그대로 쉽게 처리할 수 있을 수 있다. 섹션 9.1의 IANA 레지스트리가 이 코드포인트 공간의 확장성을 다루는 적절한 방법이다.
"tag" 공간(주요 타입 6의 값):
전체 코드포인트 공간은 풍부하며, 아주 작은 부분만 할당되어 있다. 그러나 이 코드포인트들이 모두 똑같이 효율적인 것은 아니다. 처음 24개는 단일("1+0") 바이트만 소비하며, 그 절반은 이미 할당되어 있다. 다음 232개 값은 두("1+1") 바이트만 소비하며, 거의 4분의 1이 이미 할당되어 있다. 이러한 하위 공간은 몇십 년 더 지속되도록 어느 정도 관리가 필요하다. 알 수 없는 태그 번호를 수신하는 구현은 포함된 태그 내용만 처리하거나, 바람직하게는 태그 내용을 감싸는 알 수 없는 태그 번호로 태그를 처리하도록 선택할 수 있다. 섹션 9.2의 IANA 레지스트리가 이 코드포인트 공간의 확장성을 다루는 적절한 방법이다.
"additional information" 공간:
알 수 없는 추가 정보 값을 수신한 구현은 디코딩을 계속할 방법이 없으므로, 이 공간에 코드포인트를 할당하는 것은 단순히 확장 지점을 사용하는 것보다 훨씬 큰 단계이다. 또한 남아 있는 코드포인트도 매우 적다. 섹션 7.2도 참조한다.

7.2. 추가 정보 공간 관리

인간의 마음은 때때로 어떤 것을 깔끔하게 만들기 위해 작게 인식되는 빈틈을 채우는 데 끌린다. 추가 정보 값의 코드포인트 공간에 남아 있는 빈틈은, 단지 거기에 있다는 이유만으로 새로운 아이디어를 끌어들이는 요인이 될 것으로 예상한다.

현재 명세는 추가 정보 코드포인트 공간을 IANA 레지스트리로 관리하지 않는다. 대신, 이 공간에서의 할당은 이 명세를 갱신하는 방법으로만 수행될 수 있다.

n >= 24인 추가 정보 값의 경우, 추가 데이터의 크기는 일반적으로 2n-24바이트이다. 따라서 추가 정보 값 28과 29는 프로토콜에 추가해야 할 필요가 생길 경우 128비트 및 256비트 수량의 후보로 보아야 한다. 그러면 추가 정보 값 30은 일반 할당에 사용할 수 있는 유일한 추가 정보 값이 되며, 현재 명세의 갱신을 통해 이를 할당하기 전에 매우 좋은 이유가 있어야 한다.

8. 진단 표기법

CBOR는 이진 교환 형식이다. 문서화와 디버깅을 촉진하고, 특히 디버깅에서 협력하는 엔터티 간의 소통을 촉진하기 위해, 이 섹션은 단순한 사람이 읽을 수 있는 진단 표기법을 정의한다. 실제 교환은 항상 이진 형식에서 일어난다.

이는 실제로 진단 형식이며, 구문 분석되도록 의도되지 않았다는 점에 유의한다. 따라서 이 문서에는 (ABNF와 같은) 공식 정의가 제공되지 않는다. (구성 파일에서 CBOR 데이터 항목을 표현하기 위한 텍스트 기반 형식을 찾는 구현자는 YAML [YAML]도 고려하고자 할 수 있다.)

진단 표기법은 RFC 8259에 정의된 JSON을 느슨하게 기반으로 하며, 필요한 곳에서 확장한다.

이 표기법은 숫자(정수 및 부동소수점), True(>true<), False(>false<), Null(>null<), UTF-8 문자열, 배열 및 맵에 대한 JSON 구문을 차용한다(맵은 JSON에서 객체라고 불린다. 진단 표기법은 여기서 키 위치에 어떤 데이터 항목도 허용하여 JSON을 확장한다). Undefined는 JavaScript에서처럼 >undefined<로 쓴다. 비유한 부동소수점 수 Infinity, -Infinity 및 NaN은 이 문장에 있는 그대로 정확히 쓴다(이는 JSON이 허용하지 않지만 JavaScript에서 쓸 수 있는 방식이기도 하다). 태그는 태그 번호에 대한 정수 숫자와, 그 뒤의 괄호 안 태그 내용으로 쓴다. 예를 들어, RFC 3339(ISO 8601)가 지정한 형식의 날짜는 다음과 같이 표기될 수 있다.

0("2013-03-21T20:04:00Z")

또는 동등한 상대 시간은 다음과 같다.

1(1363896240)

바이트 문자열은 base 인코딩 중 하나로 표기되며, 패딩 없이 작은따옴표로 둘러싸고, base16의 경우 >h<, base32의 경우 >b32<, base32hex의 경우 >h32<, base64 또는 base64url의 경우 >b64<를 앞에 붙인다 (실제 인코딩은 서로 겹치지 않으므로 문자열은 모호하지 않다). 예를 들어, 바이트 문자열 0x12345678은 h'12345678', b32'CI2FM6A' 또는 b64'EjRWeA'로 쓸 수 있다.

할당되지 않은 단순 값은 괄호 안에 적절한 정수를 넣어 "simple()"로 제공된다. 예를 들어, "simple(42)"는 주요 타입 7, 값 42를 나타낸다.

여기에 정의된 진단 표기법에 대한 여러 유용한 확장은 [RFC8610]의 부록 G, "Extended Diagnostic Notation" (EDN)에 제공되어 있다. 마찬가지로, 이 표기법은 이 문서에서 다루지 않는 NaN 페이로드에 대한 문서화를 제공하기 위해 별도 문서에서 확장될 수 있다.

8.1. 인코딩 표시자

때때로 진단 표기법에서 여러 대체 표현 중 실제로 어떤 것이 사용되었는지를 나타내는 것이 유용하다. 예를 들어, 진단 디코더가 >1.5<로 쓴 데이터 항목은 반정밀도, 단정밀도 또는 배정밀도 부동소수점으로 인코딩되었을 수 있다.

인코딩 표시자의 관례는 밑줄로 시작하고 뒤따르는 모든 영숫자 또는 밑줄 문자가 인코딩 표시자라는 것이며, 이 정보에 관심이 없는 사람은 이를 무시할 수 있다. 예: _ 또는 _3. 인코딩 표시자는 항상 선택 사항이다.

맵의 여는 중괄호나 배열의 여는 대괄호 뒤에 단일 밑줄을 써서 데이터 항목이 부정 길이 형식으로 표현되었음을 나타낼 수 있다. 예를 들어, [_ 1, 2]는 데이터 항목 [1, 2]를 표현하는 데 부정 길이 표현이 사용되었다는 표시자를 포함한다.

밑줄 뒤에 십진 숫자 n이 오면 앞선 항목(또는 배열과 맵의 경우 앞선 대괄호나 중괄호로 시작하는 항목)이 24+n의 추가 정보 값으로 인코딩되었음을 나타낸다. 예를 들어, 1.5_1은 반정밀도 부동소수점 수이고, 1.5_3은 배정밀도로 인코딩된다. 이 인코딩 표시자는 부록 A에는 표시되지 않는다. (따라서 인코딩 표시자 "_"는 사용되지 않는 전체 형식 "_7"의 축약이라는 점에 유의한다.)

부정 길이의 바이트 및 텍스트 문자열의 자세한 청크 구조는 (_ h'0123', h'4567') 및 (_ "foo", "bar") 형식으로 표기할 수 있다. 그러나 내부에 청크가 없는 부정 길이 문자열의 경우, (_ )는 바이트 문자열(0x5fff)을 의미하는지 텍스트 문자열 (0x7fff)을 의미하는지 모호하므로 사용되지 않는다. 대신 기본 형식 ''_ 및 ""_를 사용할 수 있으며, 청크가 없는 경우에만 예약된다. 이는 청크 구조를 보존하기 위해 (_ ''), (_ "") 등으로 표기해야 하는, 빈 청크만 있는(허용되지만 실제로는 유용하지 않은) 인코딩의 짧은 형식이 아니다.

9. IANA 고려 사항

IANA는 새로운 CBOR 값을 위해 두 개의 레지스트리를 만들었다. 이 레지스트리들은 별도이며, 즉 포괄 레지스트리 아래에 있지 않고, [RFC8126]의 규칙을 따른다. IANA는 또한 새 미디어 타입, 관련 CoAP Content-Format 항목 및 구조화 구문 접미사를 할당했다.

9.1. CBOR 단순 값 레지스트리

IANA는 [IANA.cbor-simple-values]에 "Concise Binary Object Representation (CBOR) Simple Values" 레지스트리를 만들었다. 초기 값은 표 4에 나와 있다.

0부터 19까지 범위의 새 항목은 Standards Action [RFC8126]으로 할당된다. 하위 번호를 연속 블록(있는 경우)을 위해 예약하기 위해, IANA가 숫자 16부터 값을 할당하는 것이 제안된다.

32부터 255까지 범위의 새 항목은 Specification Required로 할당된다.

9.2. CBOR 태그 레지스트리

IANA는 [IANA.cbor-tags]에 "Concise Binary Object Representation (CBOR) Tags" 레지스트리를 만들었다. [RFC7049]에 정의되어 있던 태그들은 섹션 3.4에서 자세히 설명되며, 그 이후 다른 태그들도 이미 정의되었다.

0부터 23까지("1+0") 범위의 새 항목은 Standards Action으로 할당된다. 24부터 255까지("1+1") 및 256부터 32767까지("1+2"의 하위 절반) 범위의 새 항목은 Specification Required로 할당된다. 32768부터 18446744073709551615까지 ("1+2"의 상위 절반, "1+4" 및 "1+8") 범위의 새 항목은 First Come First Served로 할당된다. 등록 요청 템플릿은 다음과 같다.

  • 데이터 항목
  • 의미(짧은 형식)

또한 First Come First Served 요청에는 다음이 포함되어야 한다.

  • 연락 담당자
  • 의미 설명(URL) -- 이 설명은 선택 사항이다. URL은 Internet-Draft나 웹 페이지 같은 것을 가리킬 수 있다.

First Come First Served 범위를 사용하고 32비트로 표현할 수 없는 태그 번호 (즉, 4294967295보다 큰 번호)를 제안하는 신청자는, 이것이 64비트 숫자를 지원하지 않는 구현과의 상호 운용성을 줄일 수 있음을 인식해야 한다.

9.3. 미디어 타입 레지스트리

단일 인코딩된 CBOR 데이터 항목에 대한 인터넷 미디어 타입 [RFC6838] ("MIME 타입")은 "Media Types" 레지스트리 [IANA.media-types]에 정의된 "application/cbor"이다:

타입 이름:
application
하위 타입 이름:
cbor
필수 매개변수:
n/a
선택 매개변수:
n/a
인코딩 고려 사항:
이진
보안 고려 사항:
RFC 8949의 섹션 10 참조.
상호 운용성 고려 사항:
n/a
공개된 명세:
RFC 8949
이 미디어 타입을 사용하는 애플리케이션:
다수
추가 정보:


매직 넘버:
n/a
파일 확장자:
.cbor
Macintosh 파일 타입 코드:
n/a
추가 정보를 위한 연락 담당자 및 이메일 주소:
IETF CBOR Working Group (cbor@ietf.org) 또는 IETF Applications and Real-Time Area (art@ietf.org)
의도된 사용:
COMMON
사용 제한:
없음
저자:
IETF CBOR Working Group (cbor@ietf.org)
변경 관리 주체:
The IESG (iesg@ietf.org)

9.4. CoAP Content-Format 레지스트리

CBOR용 CoAP Content-Format은 "Constrained RESTful Environments (CoRE) Parameters" 레지스트리 [IANA.core-parameters] 내의 "CoAP Content-Formats" 하위 레지스트리에 등록되었다:

미디어 타입:
application/cbor
인코딩:
-
ID:
60
참조:
RFC 8949

9.5. 구조화 구문 접미사 레지스트리

단일 인코딩된 CBOR 데이터 항목을 기반으로 하는 미디어 타입에 대한 구조화 구문 접미사 [RFC6838]는 +cbor이며, IANA는 이를 "Structured Syntax Suffixes" 레지스트리 [IANA.structured-suffix]에 등록했다:

이름:
간결한 이진 객체 표현 (CBOR)
+접미사:
+cbor
참조:
RFC 8949
인코딩 고려 사항:
CBOR는 이진 형식이다.
상호 운용성 고려 사항:
n/a
프래그먼트 식별자 고려 사항:

+cbor에 대해 지정된 프래그먼트 식별자의 구문과 의미는 "application/cbor"에 대해 지정된 것과 같아야 SHOULD 한다. (RFC 8949 출판 시점에는 "application/cbor"에 대해 정의된 프래그먼트 식별 구문이 없다.)

특정 "xxx/yyy+cbor"에 대한 프래그먼트 식별자의 구문과 의미는 다음과 같이 처리되어야 SHOULD 한다:

  • +cbor에 정의된 경우로, 프래그먼트 식별자가 +cbor 규칙에 따라 해소되면, +cbor에 지정된 대로 처리한다.
  • +cbor에 정의된 경우로, 프래그먼트 식별자가 +cbor 규칙에 따라 해소되지 않으면, "xxx/yyy+cbor"에 지정된 대로 처리한다.
  • +cbor에 정의되지 않은 경우에는 "xxx/yyy+cbor"에 지정된 대로 처리한다.
보안 고려 사항:
RFC 8949의 섹션 10 참조.
연락처:
IETF CBOR Working Group (cbor@ietf.org) 또는 IETF Applications and Real-Time Area (art@ietf.org)
저자/변경 관리 주체:
IETF

10. 보안 고려 사항

네트워크에 노출된 애플리케이션은 들어오는 데이터에 대한 처리 로직에서 취약점을 보일 수 있다. 복잡한 파서는 노드를 원격으로 크래시시키거나, 심지어 그 노드에서 임의 코드를 원격으로 실행할 수 있는 능력과 같은 취약점의 유력한 원천으로 잘 알려져 있다. CBOR는 가능한 경우 인코딩 가능한 값 전체 범위에 의미를 부여하여 파서 복잡성을 줄임으로써, 그러한 취약점을 도입할 기회를 좁히려고 시도한다.

CBOR 디코더는 검증되지 않은 입력을 처리하는 첫 단계로 자주 사용되므로, CBOR 데이터 항목을 디코딩하는 시스템을 손상시키거나, 넘치게 하거나, 제어를 획득하도록 설계될 수 있는 모든 유형의 적대적 입력에 완전히 대비해야 한다. CBOR 디코더는 모든 입력이 방화벽에서 검사되었거나, TLS와 같은 보안 채널을 통해 왔거나, 암호화 또는 서명되었거나, 신뢰된다고 추정되는 다른 출처에서 왔더라도 적대적일 수 있다고 가정해야 한다.

섹션 4.1은 비선호 직렬화를 사용하는 CBOR 인코더의 입력과 함께 제약 CBOR 디코더를 사용할 때 상호 운용성의 한계에 대한 예를 제공한다. 단일 데이터 항목이 그러한 제약 디코더와 완전한 디코더 모두에서 소비되는 경우, 콘텐츠를 주입하거나 조작할 수 있는 공격자가 악용할 수 있는 보안 문제로 이어질 수 있다.

이 문서 전반에서 논의한 것처럼, 어떤 상황에서는 "동등"하고 다른 상황에서는 "동등하지 않음"으로 간주될 수 있는 값이 많다. 단 하나의 예로, 숫자 "one"에 대한 수치 값은 정수 또는 큰 수로 표현될 수 있다. CBOR 입력을 해석하는 시스템은 숫자 "one"에 대해 두 형식 중 어느 것이든 받아들일 수도 있고, 한 형식(또는 두 형식 모두)을 거부할 수도 있다. 그러한 수용 또는 거부는 해석된 입력을 사용하는 프로그램에서 보안상의 영향을 가질 수 있다.

적대적 입력은 버퍼를 넘치게 하거나, 정수 산술에서 오버플로 또는 언더플로를 일으키거나, 다른 디코딩 교란을 유발하도록 구성될 수 있다. CBOR 데이터 항목은 의도적으로 극도로 크거나 너무 짧은 길이나 크기를 가질 수 있다. 리소스 고갈 공격은 디코더가 매우 큰 데이터 항목 (문자열, 배열, 맵, 또는 임의 정밀도 숫자까지)을 할당하도록 유인하거나, 깊게 중첩된 항목을 설정하여 스택 깊이를 고갈시키려고 시도할 수 있다. 디코더는 이러한 공격을 완화하기 위해 적절한 리소스 관리를 가져야 한다. (매우 큰 크기가 주어진 항목은 정수 오버플로 취약점을 악용하려고 시도할 수도 있다.)

CBOR 디코더는 정의상 올바른 형식의 CBOR만 받아들이며, 이것이 견고성의 첫 단계이다. 올바른 형식의 CBOR가 아닌 입력은 올바른 형식이 아님이 감지된 지점부터 더 이상의 처리를 유발하지 않는다. 가능하다면, 이 지점까지 디코딩된 어떤 데이터도 CBOR 디코더를 사용하는 애플리케이션에 영향을 주지 않아야 한다.

올바른 형식임을 확인하는 것에 더하여, CBOR 디코더는 CBOR 데이터에 대한 유효성 검사도 수행할 수 있다. 또는 그러한 검사를 디코더를 사용하는 애플리케이션에 맡길 수 있다. 이 선택은 디코더에 명확히 문서화되어야 한다. CBOR 수준의 유효성을 넘어, 애플리케이션은 입력이 CBOR로 직렬화된 애플리케이션 프로토콜과 일치하는지도 확인해야 한다.

입력 검사 자체가 리소스를 소비할 수 있다. 이는 보통 입력 크기에 선형적이므로, 공격자는 입력 검증에 방어자가 소비하는 리소스와 상응하는 리소스를 소비해야 함을 의미한다. 그러나 공격자는 자신이 생성하는 것보다 대상 디코더가 처리하는 데 더 오래 걸리는 입력을 만들 수 있을 수도 있다. 임의 정밀도 숫자 처리는 선형 노력을 초과할 수 있다. 또한 디코더가 맵의 메모리 내 표현을 구축하는 데 사용하는 일부 해시 테이블 구현은, 비밀 키 ([SIPHASH_LNCS]의 섹션 7 참조, 또한 [SIPHASH_OPEN])나 다른 완화책이 사용되지 않으면 이차적 노력을 소비하도록 공격받을 수 있다. 이러한 초선형 노력은 공격자가 입력 검증기에서 또는 그 이전에 리소스를 고갈시키는 데 악용될 수 있으므로, CBOR 디코더 구현에서 피해야 한다. 태그 번호 정의와 그 구현은 이러한 종류의 보안 고려 사항을 추가할 수 있다는 점에 유의한다. 그러한 경우 이는 태그 번호 정의의 보안 고려 사항에서 논의되어야 한다.

CBOR 인코더는 네트워크에서 직접 입력을 받지 않으므로 CBOR 디코더와 같은 방식으로 직접 공격받지는 않는다. 그러나 CBOR 인코더는 구현의 다른 수준에서 입력을 받는 API를 가지고 있는 경우가 많으며, 그 API를 통해 공격받을 수 있다. 그 API의 설계와 구현은 호출자의 동작이 적대적 입력이나 코딩 실수에 기반할 수 있다고 가정해야 한다. 이는 버퍼 오버런, 정수 산술의 오버플로와 언더플로, 그리고 인코더를 교란하려는 기타 오류에 대해 입력을 검사해야 한다.

프로토콜은 잠재적인 여러 해석이 신뢰성 있게 단일 해석으로 줄어들도록 정의되어야 한다. 예를 들어, 공격자는 맵의 중복 키와 같은 유효하지 않은 입력을 사용하거나, 숫자 처리의 정밀도 차이를 악용하여 한 애플리케이션이 두 번째 애플리케이션에서 사용될 해석과 다른 해석을 기반으로 결정을 내리게 할 수 있다. 일관된 해석을 촉진하기 위해, 인코더와 디코더 구현은 유효성 검사 동작 모드 (섹션 5.4)를 제공해야 한다. 그러나 일반 디코더는 애플리케이션이 입력 데이터에 부과하는 모든 요구 사항을 알 수 없으므로, 애플리케이션이 자체 입력 검사를 수행할 책임을 덜어 주지는 않는다는 점에 유의한다. 또한 정의된 태그 번호 집합은 발전하므로, 애플리케이션은 자신이 사용하는 일반 디코더가 아직 유효성 검사를 지원하지 않는 태그 번호를 사용할 수 있다. 따라서 일반 디코더는 어떤 태그 번호를 지원하는지와, 그 태그 번호들 및 기본 CBOR(UTF-8 검사, 중복 맵 키 검사)에 대해 어떤 유효성 검사를 제공하는지를 문서화해야 한다.

섹션 3.4.3은 숫자를 인코딩할 때 기본 정수 대신 큰 수 표현을 사용하는 비선호 선택이 애플리케이션 의미를 갖도록 의도되지 않았다고 언급한다. 그러나 CBOR 데이터를 수신하는 애플리케이션이 기본 일반 데이터 모델의 디코더를 사용하는 경우 그러한 의미를 가질 수 있다. 두 의미 집합이 다르면 이 불일치는 보안 문제를 일으킨다. 따라서 CBOR를 사용하는 애플리케이션은 CBOR 데이터의 각 사용에 대해 자신들이 사용하는 데이터 모델을 지정해야 한다.

CBOR 데이터를 다른 형식으로 변환하는 것은 흔하다. 많은 경우, CBOR는 다른 형식보다 더 표현력 있는 타입을 가진다. 이는 특히 JSON으로의 일반적인 변환에서 참이다. 타입 정보의 손실은 표현력이 더 낮은 데이터를 처리하는 시스템에 보안 문제를 일으킬 수 있다.

섹션 6.2는 공격자가 애플리케이션이 변환을 수행하고 있음을 알고 있다면 공격을 허용할 수 있는, CBOR와 JSON 간 변환의 가능한 일반적 사용 시나리오를 설명한다.

[RFC4648]의 base16 및 base64 사용에 대한 보안 고려 사항과, [RFC3629]의 UTF-8 사용에 대한 보안 고려 사항은 CBOR에도 관련된다.

11. 참고 문헌

11.1. 규범 참고 문헌

[C]
국제 표준화 기구, "정보 기술 - 프로그래밍 언어 - C", 제4판, ISO/IEC 9899:2018, , <https://www.iso.org/standard/74528.html>.
[Cplusplus20]
국제 표준화 기구, "프로그래밍 언어 - C++", 제6판, ISO/IEC DIS 14882, ISO/IEC ISO/IEC JTC1 SC22 WG21 N 4860, , <https://isocpp.org/files/papers/N4860.pdf>.
[IEEE754]
IEEE, "부동소수점 산술을 위한 IEEE 표준", IEEE Std 754-2019, DOI 10.1109/IEEESTD.2019.8766229, <https://ieeexplore.ieee.org/document/8766229>.
[RFC2045]
Freed, N. 및 N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: 인터넷 메시지 본문의 형식", RFC 2045, DOI 10.17487/RFC2045, , <https://www.rfc-editor.org/info/rfc2045>.
[RFC2119]
Bradner, S., "요구 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC3339]
Klyne, G. 및 C. Newman, "인터넷의 날짜와 시간: 타임스탬프", RFC 3339, DOI 10.17487/RFC3339, , <https://www.rfc-editor.org/info/rfc3339>.
[RFC3629]
Yergeau, F., "ISO 10646의 변환 형식, UTF-8", STD 63, RFC 3629, DOI 10.17487/RFC3629, , <https://www.rfc-editor.org/info/rfc3629>.
[RFC3986]
Berners-Lee, T., Fielding, R., 및 L. Masinter, "Uniform Resource Identifier (URI): 일반 구문", STD 66, RFC 3986, DOI 10.17487/RFC3986, , <https://www.rfc-editor.org/info/rfc3986>.
[RFC4287]
Nottingham, M., Ed. 및 R. Sayre, Ed., "Atom 배급 형식", RFC 4287, DOI 10.17487/RFC4287, , <https://www.rfc-editor.org/info/rfc4287>.
[RFC4648]
Josefsson, S., "Base16, Base32 및 Base64 데이터 인코딩", RFC 4648, DOI 10.17487/RFC4648, , <https://www.rfc-editor.org/info/rfc4648>.
[RFC8126]
Cotton, M., Leiba, B., 및 T. Narten, "RFC에서 IANA 고려 사항 섹션을 작성하기 위한 지침", BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/info/rfc8126>.
[RFC8174]
Leiba, B., "RFC 2119 핵심 단어에서 대문자와 소문자의 모호성", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[TIME_T]
The Open Group, "The Open Group 기본 명세", 섹션 4.16, '에포크 이후의 초', Issue 7, 2018년판, IEEE Std 1003.1, , <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16>.

11.2. 정보 참고 문헌

[ASN.1]
국제 전기 통신 연합, "정보 기술 - ASN.1 인코딩 규칙: 기본 인코딩 규칙(BER), 표준 인코딩 규칙(CER) 및 식별 인코딩 규칙(DER)의 명세", ITU-T Recommendation X.690, , <https://www.itu.int/rec/T-REC-X.690-201508-I/en>.
[BSON]
Various, "BSON - Binary JSON", <http://bsonspec.org/>.
[CBOR-TAGS]
Bormann, C., "주목할 만한 CBOR 태그", 진행 중 작업, Internet-Draft, draft-bormann-cbor-notable-tags-02, , <https://tools.ietf.org/html/draft-bormann-cbor-notable-tags-02>.
[ECMA262]
Ecma International, "ECMAScript 2020 Language Specification", Standard ECMA-262, 제11판, , <https://www.ecma-international.org/publications/standards/Ecma-262.htm>.
[Err3764]
RFC 정오표, 정오표 ID 3764, RFC 7049, <https://www.rfc-editor.org/errata/eid3764>.
[Err3770]
RFC 정오표, 정오표 ID 3770, RFC 7049, <https://www.rfc-editor.org/errata/eid3770>.
[Err4294]
RFC 정오표, 정오표 ID 4294, RFC 7049, <https://www.rfc-editor.org/errata/eid4294>.
[Err4409]
RFC 정오표, 정오표 ID 4409, RFC 7049, <https://www.rfc-editor.org/errata/eid4409>.
[Err4963]
RFC 정오표, 정오표 ID 4963, RFC 7049, <https://www.rfc-editor.org/errata/eid4963>.
[Err4964]
RFC 정오표, 정오표 ID 4964, RFC 7049, <https://www.rfc-editor.org/errata/eid4964>.
[Err5434]
RFC 정오표, 정오표 ID 5434, RFC 7049, <https://www.rfc-editor.org/errata/eid5434>.
[Err5763]
RFC 정오표, 정오표 ID 5763, RFC 7049, <https://www.rfc-editor.org/errata/eid5763>.
[Err5917]
RFC 정오표, 정오표 ID 5917, RFC 7049, <https://www.rfc-editor.org/errata/eid5917>.
[IANA.cbor-simple-values]
IANA, "간결한 이진 객체 표현 (CBOR) 단순 값", <https://www.iana.org/assignments/cbor-simple-values>.
[IANA.cbor-tags]
IANA, "간결한 이진 객체 표현 (CBOR) 태그", <https://www.iana.org/assignments/cbor-tags>.
[IANA.core-parameters]
IANA, "Constrained RESTful Environments (CoRE) Parameters", <https://www.iana.org/assignments/core-parameters>.
[IANA.media-types]
IANA, "미디어 타입", <https://www.iana.org/assignments/media-types>.
[IANA.structured-suffix]
IANA, "구조화 구문 접미사", <https://www.iana.org/assignments/media-type-structured-suffix>.
[MessagePack]
Furuhashi, S., "MessagePack", <https://msgpack.org/>.
[PCRE]
Hazel, P., "PCRE - Perl Compatible Regular Expressions", <https://www.pcre.org/>.
[RFC0713]
Haverty, J., "MSDTP-Message Services Data Transmission Protocol", RFC 713, DOI 10.17487/RFC0713, , <https://www.rfc-editor.org/info/rfc713>.
[RFC6838]
Freed, N., Klensin, J., 및 T. Hansen, "미디어 타입 명세 및 등록 절차", BCP 13, RFC 6838, DOI 10.17487/RFC6838, , <https://www.rfc-editor.org/info/rfc6838>.
[RFC7049]
Bormann, C. 및 P. Hoffman, "간결한 이진 객체 표현(CBOR)", RFC 7049, DOI 10.17487/RFC7049, , <https://www.rfc-editor.org/info/rfc7049>.
[RFC7228]
Bormann, C., Ersue, M., 및 A. Keranen, "제약 노드 네트워크를 위한 용어", RFC 7228, DOI 10.17487/RFC7228, , <https://www.rfc-editor.org/info/rfc7228>.
[RFC7493]
Bray, T., Ed., "I-JSON 메시지 형식", RFC 7493, DOI 10.17487/RFC7493, , <https://www.rfc-editor.org/info/rfc7493>.
[RFC7991]
Hoffman, P., "The "xml2rfc" Version 3 Vocabulary", RFC 7991, DOI 10.17487/RFC7991, , <https://www.rfc-editor.org/info/rfc7991>.
[RFC8259]
Bray, T., Ed., "JavaScript Object Notation (JSON) 데이터 교환 형식", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/info/rfc8259>.
[RFC8610]
Birkholz, H., Vigano, C., 및 C. Bormann, "Concise Data Definition Language (CDDL): 간결한 이진 객체 표현(CBOR) 및 JSON 데이터 구조를 표현하기 위한 표기 관례", RFC 8610, DOI 10.17487/RFC8610, , <https://www.rfc-editor.org/info/rfc8610>.
[RFC8618]
Dickinson, J., Hague, J., Dickinson, S., Manderson, T., 및 J. Bond, "Compacted-DNS (C-DNS): DNS 패킷 캡처를 위한 형식", RFC 8618, DOI 10.17487/RFC8618, , <https://www.rfc-editor.org/info/rfc8618>.
[RFC8742]
Bormann, C., "간결한 이진 객체 표현(CBOR) 시퀀스", RFC 8742, DOI 10.17487/RFC8742, , <https://www.rfc-editor.org/info/rfc8742>.
[RFC8746]
Bormann, C., Ed., "타입 배열을 위한 간결한 이진 객체 표현(CBOR) 태그", RFC 8746, DOI 10.17487/RFC8746, , <https://www.rfc-editor.org/info/rfc8746>.
[SIPHASH_LNCS]
Aumasson, J. 및 D. Bernstein, "SipHash: 빠른 짧은 입력 PRF", Progress in Cryptology - INDOCRYPT 2012, pp. 489-508, DOI 10.1007/978-3-642-34931-7_28, , <https://doi.org/10.1007/978-3-642-34931-7_28>.
[SIPHASH_OPEN]
Aumasson, J. 및 D.J. Bernstein, "SipHash: 빠른 짧은 입력 PRF", <https://www.aumasson.jp/siphash/siphash.pdf>.
[YAML]
Ben-Kiki, O., Evans, C., 및 I.d. Net, "YAML Ain't Markup Language (YAML[TM]) Version 1.2", 제3판, , <https://www.yaml.org/spec/1.2/spec.html>.

부록 A. 인코딩된 CBOR 데이터 항목의 예

다음 표는 일부 CBOR 인코딩 값을 16진수 (오른쪽 열)로 제공하며, 이 값들에 대한 진단 표기법(왼쪽 열)도 함께 제공한다. 문자열 "\u00fc"는 단일 Unicode 문자 U+00FC (LATIN SMALL LETTER U WITH DIAERESIS, "ü")를 포함하는 UTF-8 문자열에 대한 진단 표기법의 한 형태임에 유의한다. 마찬가지로, "\u6c34"는 단일 문자 U+6C34 (CJK UNIFIED IDEOGRAPH-6C34, "水")를 가진 진단 표기법의 UTF-8 문자열로, 종종 "물"을 나타내며, "\ud800\udd51"은 단일 문자 U+10151 (GREEK ACROPHONIC ATTIC FIFTY STATERS, "𐅑")를 가진 진단 표기법의 UTF-8 문자열이다. (이러한 모든 단일 문자 문자열은 진단 표기법에서 네이티브 UTF-8로도 표현될 수 있지만, ASCII 전용 명세가 요구되는 경우에는 그렇지 않다는 점에 유의한다.) 큰 수에 대해 제공된 진단 표기법에서는, 의도된 수치 값이 태그가 지정된 바이트 문자열 (예: 2(h'010000000000000000')) 대신 십진수 숫자 (예: 18446744073709551616)로 표시된다.

표 6: 인코딩된 CBOR 데이터 항목의 예
진단 인코딩
0 0x00
1 0x01
10 0x0a
23 0x17
24 0x1818
25 0x1819
100 0x1864
1000 0x1903e8
1000000 0x1a000f4240
1000000000000 0x1b000000e8d4a51000
18446744073709551615 0x1bffffffffffffffff
18446744073709551616 0xc249010000000000000000
-18446744073709551616 0x3bffffffffffffffff
-18446744073709551617 0xc349010000000000000000
-1 0x20
-10 0x29
-100 0x3863
-1000 0x3903e7
0.0 0xf90000
-0.0 0xf98000
1.0 0xf93c00
1.1 0xfb3ff199999999999a
1.5 0xf93e00
65504.0 0xf97bff
100000.0 0xfa47c35000
3.4028234663852886e+38 0xfa7f7fffff
1.0e+300 0xfb7e37e43c8800759c
5.960464477539063e-8 0xf90001
0.00006103515625 0xf90400
-4.0 0xf9c400
-4.1 0xfbc010666666666666
Infinity 0xf97c00
NaN 0xf97e00
-Infinity 0xf9fc00
Infinity 0xfa7f800000
NaN 0xfa7fc00000
-Infinity 0xfaff800000
Infinity 0xfb7ff0000000000000
NaN 0xfb7ff8000000000000
-Infinity 0xfbfff0000000000000
false 0xf4
true 0xf5
null 0xf6
undefined 0xf7
simple(16) 0xf0
simple(255) 0xf8ff
0("2013-03-21T20:04:00Z") 0xc074323031332d30332d32315432303a 30343a30305a
1(1363896240) 0xc11a514b67b0
1(1363896240.5) 0xc1fb41d452d9ec200000
23(h'01020304') 0xd74401020304
24(h'6449455446') 0xd818456449455446
32("http://www.example.com") 0xd82076687474703a2f2f7777772e6578 616d706c652e636f6d
h'' 0x40
h'01020304' 0x4401020304
"" 0x60
"a" 0x6161
"IETF" 0x6449455446
"\"\\" 0x62225c
"\u00fc" 0x62c3bc
"\u6c34" 0x63e6b0b4
"\ud800\udd51" 0x64f0908591
[] 0x80
[1, 2, 3] 0x83010203
[1, [2, 3], [4, 5]] 0x8301820203820405
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] 0x98190102030405060708090a0b0c0d0e 0f101112131415161718181819
{} 0xa0
{1: 2, 3: 4} 0xa201020304
{"a": 1, "b": [2, 3]} 0xa26161016162820203
["a", {"b": "c"}] 0x826161a161626163
{"a": "A", "b": "B", "c": "C", "d": "D", "e": "E"} 0xa5616161416162614261636143616461 4461656145
(_ h'0102', h'030405') 0x5f42010243030405ff
(_ "strea", "ming") 0x7f657374726561646d696e67ff
[_ ] 0x9fff
[_ 1, [2, 3], [_ 4, 5]] 0x9f018202039f0405ffff
[_ 1, [2, 3], [4, 5]] 0x9f01820203820405ff
[1, [2, 3], [_ 4, 5]] 0x83018202039f0405ff
[1, [_ 2, 3], [4, 5]] 0x83019f0203ff820405
[_ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] 0x9f0102030405060708090a0b0c0d0e0f 101112131415161718181819ff
{_ "a": 1, "b": [_ 2, 3]} 0xbf61610161629f0203ffff
["a", {_ "b": "c"}] 0x826161bf61626163ff
{_ "Fun": true, "Amt": -2} 0xbf6346756ef563416d7421ff

부록 B. 초기 바이트에 대한 점프 테이블

간결성을 위해, 이 점프 테이블은 향후 확장을 위해 예약된 초기 바이트를 표시하지 않는다. 또한 선택 기능에 사용할 수 있는 초기 바이트 중 일부만 보여 준다. (모든 부호 없는 정수는 네트워크 바이트 순서이다.)

표 7: 초기 바이트에 대한 점프 테이블
바이트 구조/의미
0x00..0x17 부호 없는 정수 0x00..0x17 (0..23)
0x18 부호 없는 정수(1바이트 uint8_t가 뒤따름)
0x19 부호 없는 정수(2바이트 uint16_t가 뒤따름)
0x1a 부호 없는 정수(4바이트 uint32_t가 뒤따름)
0x1b 부호 없는 정수(8바이트 uint64_t가 뒤따름)
0x20..0x37 음의 정수 -1-0x00..-1-0x17 (-1..-24)
0x38 음의 정수 -1-n(n에 대한 1바이트 uint8_t가 뒤따름)
0x39 음의 정수 -1-n(n에 대한 2바이트 uint16_t가 뒤따름)
0x3a 음의 정수 -1-n(n에 대한 4바이트 uint32_t가 뒤따름)
0x3b 음의 정수 -1-n(n에 대한 8바이트 uint64_t가 뒤따름)
0x40..0x57 바이트 문자열(0x00..0x17바이트가 뒤따름)
0x58 바이트 문자열(n에 대한 1바이트 uint8_t와 그 뒤에 n바이트가 뒤따름)
0x59 바이트 문자열(n에 대한 2바이트 uint16_t와 그 뒤에 n바이트가 뒤따름)
0x5a 바이트 문자열(n에 대한 4바이트 uint32_t와 그 뒤에 n바이트가 뒤따름)
0x5b 바이트 문자열(n에 대한 8바이트 uint64_t와 그 뒤에 n바이트가 뒤따름)
0x5f 바이트 문자열, 바이트 문자열들이 뒤따르며 "break"로 종료됨
0x60..0x77 UTF-8 문자열(0x00..0x17바이트가 뒤따름)
0x78 UTF-8 문자열(n에 대한 1바이트 uint8_t와 그 뒤에 n바이트가 뒤따름)
0x79 UTF-8 문자열(n에 대한 2바이트 uint16_t와 그 뒤에 n바이트가 뒤따름)
0x7a UTF-8 문자열(n에 대한 4바이트 uint32_t와 그 뒤에 n바이트가 뒤따름)
0x7b UTF-8 문자열(n에 대한 8바이트 uint64_t와 그 뒤에 n바이트가 뒤따름)
0x7f UTF-8 문자열, UTF-8 문자열들이 뒤따르며 "break"로 종료됨
0x80..0x97 배열(0x00..0x17개의 데이터 항목이 뒤따름)
0x98 배열(n에 대한 1바이트 uint8_t와 그 뒤에 n개의 데이터 항목이 뒤따름)
0x99 배열(n에 대한 2바이트 uint16_t와 그 뒤에 n개의 데이터 항목이 뒤따름)
0x9a 배열(n에 대한 4바이트 uint32_t와 그 뒤에 n개의 데이터 항목이 뒤따름)
0x9b 배열(n에 대한 8바이트 uint64_t와 그 뒤에 n개의 데이터 항목이 뒤따름)
0x9f 배열, 데이터 항목들이 뒤따르며 "break"로 종료됨
0xa0..0xb7 맵(0x00..0x17쌍의 데이터 항목이 뒤따름)
0xb8 맵(n에 대한 1바이트 uint8_t와 그 뒤에 n쌍의 데이터 항목이 뒤따름)
0xb9 맵(n에 대한 2바이트 uint16_t와 그 뒤에 n쌍의 데이터 항목이 뒤따름)
0xba 맵(n에 대한 4바이트 uint32_t와 그 뒤에 n쌍의 데이터 항목이 뒤따름)
0xbb 맵(n에 대한 8바이트 uint64_t와 그 뒤에 n쌍의 데이터 항목이 뒤따름)
0xbf 맵, 데이터 항목의 쌍들이 뒤따르며 "break"로 종료됨
0xc0 텍스트 기반 날짜/시간(데이터 항목이 뒤따름; 섹션 3.4.1 참조)
0xc1 에포크 기반 날짜/시간(데이터 항목이 뒤따름; 섹션 3.4.2 참조)
0xc2 부호 없는 큰 수(데이터 항목 "바이트 문자열"이 뒤따름)
0xc3 음의 큰 수(데이터 항목 "바이트 문자열"이 뒤따름)
0xc4 십진 분수(데이터 항목 "배열"이 뒤따름; 섹션 3.4.4 참조)
0xc5 큰 부동소수점 수(데이터 항목 "배열"이 뒤따름; 섹션 3.4.4 참조)
0xc6..0xd4 (태그)
0xd5..0xd7 예상 변환(데이터 항목이 뒤따름; 섹션 3.4.5.2 참조)
0xd8..0xdb (추가 태그; 태그 번호의 1/2/4/8바이트와 그 뒤에 데이터 항목이 뒤따름)
0xe0..0xf3 (단순 값)
0xf4 false
0xf5 true
0xf6 null
0xf7 undefined
0xf8 (단순 값, 1바이트가 뒤따름)
0xf9 반정밀도 부동소수점(2바이트 IEEE 754)
0xfa 단정밀도 부동소수점(4바이트 IEEE 754)
0xfb 배정밀도 부동소수점(8바이트 IEEE 754)
0xff "break" 정지 코드

부록 C. 의사 코드

CBOR 항목의 올바른 형식 여부는 그림 1의 의사 코드로 검사할 수 있다. 데이터는 다음 경우에 그리고 그 경우에만 올바른 형식이다.

의사 코드는 다음 전제 조건을 가진다.

well_formed는 올바른 형식의 정길이 항목에 대해 주요 타입을 반환하지만, 부정 길이 항목에 대해서는 99를 반환한다 (또는 breakable이 설정된 경우에만 "break" 정지 코드에 대해 -1). 이는 well_formed_indefinite에서 부정 길이 문자열이 청크로 정길이 문자열만 포함하는지 확인하는 데 사용된다.

well_formed(breakable = false) {
  // process initial bytes
  ib = uint(take(1));
  mt = ib >> 5;
  val = ai = ib & 0x1f;
  switch (ai) {
    case 24: val = uint(take(1)); break;
    case 25: val = uint(take(2)); break;
    case 26: val = uint(take(4)); break;
    case 27: val = uint(take(8)); break;
    case 28: case 29: case 30: fail();
    case 31:
      return well_formed_indefinite(mt, breakable);
  }
  // process content
  switch (mt) {
    // case 0, 1, 7 do not have content; just use val
    case 2: case 3: take(val); break; // bytes/UTF-8
    case 4: for (i = 0; i < val; i++) well_formed(); break;
    case 5: for (i = 0; i < val*2; i++) well_formed(); break;
    case 6: well_formed(); break;     // 1 embedded data item
    case 7: if (ai == 24 && val < 32) fail(); // bad simple
  }
  return mt;                    // definite-length data item
}

well_formed_indefinite(mt, breakable) {
  switch (mt) {
    case 2: case 3:
      while ((it = well_formed(true)) != -1)
        if (it != mt)           // need definite-length chunk
          fail();               //    of same type
      break;
    case 4: while (well_formed(true) != -1); break;
    case 5: while (well_formed(true) != -1) well_formed(); break;
    case 7:
      if (breakable)
        return -1;              // signal break out
      else fail();              // no enclosing indefinite
    default: fail();            // wrong mt
  }
  return 99;                    // indefinite-length data item
}
그림 1: 올바른 형식 여부 검사를 위한 의사 코드

완전한 CBOR 디코더에 남는 복잡성은 디코딩된 데이터를 적절한 형태로 애플리케이션에 제시하는 것에 관한 것임에 유의한다.

주요 타입 0과 1은 양수/음수에 대한 if-then-else를 실제로 수행하지 않고도 부호 있는 정수에서 C로 인코딩될 수 있도록 설계되어 있다(그림 2). 이는 주요 타입 1에 대한 변환인 (-1-n)이 C 부호 없는 산술에서 ~n(비트 단위 보수)과 같다는 사실을 사용한다. 그런 다음 음수의 경우 ~n은 (-1)^n으로 표현할 수 있고, 0^n은 음이 아닌 경우 n을 변경하지 않고 둔다. 숫자의 부호는 숫자의 비트 길이보다 하나 적게 산술 시프트하여 음수에 대해 -1, 음이 아닌 값(0 또는 양수)에 대해 0으로 변환할 수 있다(예: 64비트 숫자의 경우 63만큼).

void encode_sint(int64_t n) {
  uint64t ui = n >> 63;    // extend sign to whole length
  unsigned mt = ui & 0x20; // extract (shifted) major type
  ui ^= n;                 // complement negatives
  if (ui < 24)
    *p++ = mt + ui;
  else if (ui < 256) {
    *p++ = mt + 24;
    *p++ = ui;
  } else
       ...
그림 2: 부호 있는 정수 인코딩을 위한 의사 코드

이 코드 조각들에서 사용되는 C 언어 프로파일에 관한 몇 가지 특정 가정은 섹션 1.2를 참조한다.

부록 D. 반정밀도

반정밀도 부동소수점 수는 2008년에야 IEEE 754에 추가되었으므로 [IEEE754], 오늘날의 프로그래밍 플랫폼은 여전히 이에 대한 지원이 제한적인 경우가 많다. 그러한 지원이 없어도 적어도 디코딩 지원을 포함하는 것은 매우 쉽다. C 언어로 된 반정밀도 부동소수점 수용 작은 디코더의 예는 그림 3에 나와 있다. Python용 유사한 프로그램은 그림 4에 있으며, 이 코드는 2바이트 값이 이미 네트워크 바이트 순서의 (부호 없는 short) 정수로 디코딩되었다고 가정한다(부록 C의 의사 코드에서 수행되는 것처럼).

#include <math.h>

double decode_half(unsigned char *halfp) {
  unsigned half = (halfp[0] << 8) + halfp[1];
  unsigned exp = (half >> 10) & 0x1f;
  unsigned mant = half & 0x3ff;
  double val;
  if (exp == 0) val = ldexp(mant, -24);
  else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
  else val = mant == 0 ? INFINITY : NAN;
  return half & 0x8000 ? -val : val;
}
그림 3: 반정밀도 디코더를 위한 C 코드
import struct
from math import ldexp

def decode_single(single):
    return struct.unpack("!f", struct.pack("!I", single))[0]

def decode_half(half):
    valu = (half & 0x7fff) << 13 | (half & 0x8000) << 16
    if ((half & 0x7c00) != 0x7c00):
        return ldexp(decode_single(valu), 112)
    return decode_single(valu | 0x7f800000)
그림 4: 반정밀도 디코더를 위한 Python 코드

부록 E. 다른 이진 형식과 CBOR의 설계 목표 비교

CBOR 제안은 컴퓨터 자체의 역사만큼이나 긴 이진 형식의 역사를 따른다. 서로 다른 형식은 서로 다른 목표를 가져 왔다. 대부분의 경우, 형식의 목표는 명시된 적이 없지만, 그 형식이 처음 사용된 맥락에서 때때로 암시될 수 있다. 일부 형식은 보편적으로 사용할 수 있도록 의도되었지만, 역사는 어떤 이진 형식도 모든 프로토콜과 애플리케이션의 요구를 충족하지 못한다는 것을 증명했다.

CBOR는 일련의 목표에서 출발하여 바로 그 목표들만 충족하려고 시도한다는 점에서 이러한 여러 형식과 다르다. 이 섹션은 독자가 특정 프로토콜이나 애플리케이션에 CBOR를 사용할지 다른 형식을 사용할지 결정하는 데 도움을 주기 위해, 수십 가지 형식 중 일부를 CBOR의 목표와 비교한다.

여기서의 논의는 어떤 형식에 대한 비판을 의도한 것이 아님에 유의한다. 우리가 아는 한, CBOR 이전의 어떤 형식도 우리가 부여한 우선순위로 CBOR의 목표를 포괄하도록 의도되지 않았다. 섹션 1.1의 목표를 간단히 요약하면 다음과 같다.

  1. 인터넷 표준의 대부분 공통 데이터 형식에 대한 모호하지 않은 인코딩
  2. 인코더 또는 디코더를 위한 코드 간결성
  3. 스키마 설명이 필요 없음
  4. 합리적으로 간결한 직렬화
  5. 제약 및 비제약 애플리케이션 모두에 대한 적용 가능성
  6. 좋은 JSON 변환
  7. 확장성

다른 설계 목표 집합과 관련한 CBOR 및 다른 형식에 대한 논의는 [RFC8618]섹션 5 및 부록 C에 제공되어 있다.

E.1. ASN.1 DER, BER 및 PER

[ASN.1]은 많은 직렬화를 가진다. IETF에서는 DER 및 BER이 가장 일반적이다. 직렬화된 출력은 많은 항목에 대해 특별히 간결하지 않으며, 숫자 항목을 디코딩하는 데 필요한 코드는 제약 장치에서 복잡할 수 있다.

IETF 프로토콜 중 Packed Encoding Rules(PER)의 여러 변형 중 하나를 채택한 것은 거의 없다(있더라도). 여기에는 여러 이유가 있을 수 있지만, 흔히 언급되는 이유 중 하나는 PER이 데이터 항목의 표면 구조를 구문 분석하는 데에도 스키마를 사용하여 상당한 도구 지원을 요구한다는 것이다. 사용 중인 ASN.1 스키마 언어에는 서로 다른 버전도 있어, 이는 채택을 저해하기도 했다.

E.2. MessagePack

[MessagePack]은 CBOR와 여러 속성에서 유사한, 간결하고 널리 구현된 카운트 기반 이진 직렬화 형식이지만, 다소 덜 규칙적이다. 데이터 모델은 JSON 데이터를 표현하는 데 사용할 수 있지만, MessagePack은 많은 원격 프로시저 호출(RPC) 애플리케이션과 데이터의 장기 저장에도 사용되어 왔다.

MessagePack은 2011년경 처음 공개된 이후 본질적으로 안정적이었으며, 아직 전환을 겪지 않았다. MessagePack의 발전은 기존 저장 데이터와의 완전한 하위 호환성을 유지해야 한다는 명령에 의해 저해되며, 확장에 사용할 수 있는 바이트코드는 거의 남아 있지 않다. 인코딩에서 이진 문자열과 텍스트 문자열을 분리하라는 MessagePack 사용자 커뮤니티의 수년간 반복된 요청은 최근 MessagePack의 "raw" 데이터를 이진 데이터와 텍스트 데이터에 대한 용도 사이에서 모호하게 남겨 두는 확장 제안으로 이어졌다. MessagePack의 확장 메커니즘은 여전히 불명확하다.

E.3. BSON

[BSON]은 MongoDB 데이터베이스에서 JSON 유사 맵(JSON 객체)을 저장하기 위해 개발된 데이터 형식이다. 주요한 구별 특징은 제자리 업데이트 기능이며, 이는 간결한 표현을 방해한다. BSON은 맵 키를 제외하고는 카운트 기반 표현을 사용하며, 맵 키는 널 바이트로 종료된다. BSON은 전송선상에서 JSON 유사 객체를 표현하는 데 사용할 수 있지만, 그 명세는 데이터베이스 애플리케이션의 요구 사항이 지배하며 다소 바로크식이 되었다. BSON 확장이 어떻게 구현될지의 상태는 여전히 불명확하다.

E.4. MSDTP: RFC 713

Message Services Data Transmission(MSDTP)은 간결한 메시지 형식의 매우 이른 예이며, 1976년에 작성된 [RFC0713]에 설명되어 있다. 이는 역사적 가치 때문에 여기에 포함되었으며, 널리 사용된 적이 있어서가 아니다.

E.5. 전송선상의 간결성

인코더와 디코더의 코드 간결성이라는 CBOR의 설계 목표가 전송선상의 간결성이라는 목표보다 더 높은 우선순위이지만, 많은 사람은 전송 크기에 주목한다. 표 8은 단순한 중첩 배열 [1, [2, 3]]에 대한 몇 가지 인코딩 예를 보여 준다. 인코딩에서 어떤 형태의 부정 길이 인코딩을 지원하는 경우, [_ 1, [2, 3]](외부 배열의 부정 길이)도 표시되어 있다.

표 8: 서로 다른 간결성 수준의 예
형식 [1, [2, 3]] [_ 1, [2, 3]]
RFC 713 c2 05 81 c2 02 82 83
ASN.1 BER 30 0b 02 01 01 30 06 02 01 02 02 01 03 30 80 02 01 01 30 06 02 01 02 02 01 03 00 00
MessagePack 92 01 92 02 03
BSON 22 00 00 00 10 30 00 01 00 00 00 04 31 00 13 00 00 00 10 30 00 02 00 00 00 10 31 00 03 00 00 00 00 00
CBOR 82 01 82 02 03 9f 01 82 02 03 ff

부록 F. 올바른 형식 오류 및 예

CBOR 데이터 항목을 디코딩할 때 발생할 수 있는 올바른 형식 오류의 기본 종류는 세 가지이다.

데이터가 너무 많음:
소비되지 않은 입력 바이트가 남아 있다. 이는 애플리케이션이 입력 바이트가 정확히 하나의 데이터 항목에 걸쳐 있다고 가정한 경우에만 오류이다. 애플리케이션이 예를 들어 CBOR 시퀀스 [RFC8742]에서처럼 데이터 항목 뒤에 추가 데이터를 허용하기 위해 CBOR 인코딩의 자기 구분 특성을 사용하는 경우, CBOR 디코더는 입력의 어느 부분이 소비되지 않았는지만 표시할 수 있다.
데이터가 너무 적음:
사용 가능한 입력 데이터는 완전한 CBOR 데이터 항목을 위해 끝에 추가 바이트가 필요하다. 이는 입력이 잘렸음을 나타낼 수 있으며, 임의 데이터를 CBOR로 디코딩하려고 할 때 흔한 오류이기도 하다. 그러나 일부 애플리케이션에서는, 애플리케이션이 아직 모든 데이터를 가지고 있는지 확신하지 못하고 추가 입력 바이트를 얻거나 기다릴 수 있으므로 실제로 오류가 아닐 수 있다. 이러한 애플리케이션 중 일부는 얼마나 많은 추가 데이터가 나타날 수 있는지에 대한 상한을 가질 수 있다. 이 경우 디코더는 인코딩된 CBOR 데이터 항목이 이 한계 안에서 완료될 수 없음을 표시할 수 있다.
구문 오류:
입력 데이터가 CBOR 인코딩의 요구 사항과 일치하지 않으며, 끝에 데이터를 추가(또는 제거)하여 이를 고칠 수 없다.

부록 C에서 첫 번째 종류의 오류는 첫 번째 단락과 글머리표 목록("남은 바이트가 없음"을 요구함)에서 다루어지고, 두 번째 종류의 오류는 두 번째 단락/글머리표 목록 ("n바이트를 더 이상 사용할 수 없으면" 실패함)에서 다루어진다. 세 번째 종류의 오류는 의사 코드에서 다음 순서의 특정 fail() 호출 인스턴스로 식별된다.

F.1. 올바른 형식이 아닌 CBOR 데이터 항목의 예

이 하위 섹션은 올바른 형식이 아닌 CBOR 데이터 항목에 대한 몇 가지 예를 보여 준다. 각 예는 바이트 시퀀스이며, 각 바이트는 16진수로 표시된다. 목록의 여러 예는 쉼표로 구분된다.

올바른 형식 오류 종류 1(데이터가 너무 많음)의 예는 올바른 형식으로 인코딩된 CBOR 데이터 항목에 데이터를 추가하여 쉽게 만들 수 있다.

마찬가지로, 올바른 형식 오류 종류 2(데이터가 너무 적음)의 예는 올바른 형식으로 인코딩된 CBOR 데이터 항목을 잘라서 만들 수 있다. 테스트 모음에서는 완료되기 위해 많은 양의 추가가 필요한 불완전한 데이터 항목으로 구체적으로 테스트하는 것이 유익할 수 있다 (예를 들어 매우 큰 크기의 문자열 인코딩을 시작하는 방식).

입력의 조기 종료는 헤드에서 또는 포함된 데이터 안에서 발생할 수 있다. 그 데이터는 단순 문자열이거나, 카운트되거나 "break" 정지 코드로 끝났어야 하는 포함 데이터 항목일 수 있다.

헤드에서 입력 종료:
18, 19, 1a, 1b, 19 01, 1a 01 02, 1b 01 02 03 04 05 06 07, 38, 58, 78, 98, 9a 01 ff 00, b8, d8, f8, f9 00, fa 00 00, fb 00 00 00
데이터가 짧은 정길이 문자열:
41, 61, 5a ff ff ff ff 00, 5b ff ff ff ff ff ff ff ff 01 02 03, 7a ff ff ff ff 00, 7b 7f ff ff ff ff ff ff ff 01 02 03
충분한 항목으로 닫히지 않은 정길이 맵 및 배열:
81, 81 81 81 81 81 81 81 81 81, 82 00, a1, a2 01 02, a1 00, a2 00 00 00
태그 번호 뒤에 태그 내용이 오지 않음:
c0
"break" 정지 코드로 닫히지 않은 부정 길이 문자열:
5f 41 00, 7f 61 00
"break" 정지 코드로 닫히지 않은 부정 길이 맵 및 배열:
9f, 9f 01 02, bf, bf 01 02 01 02, 81 9f, 9f 80 00, 9f 9f 9f 9f 9f ff ff ff ff, 9f 81 9f 81 9f 9f ff ff ff

올바른 형식 오류 종류 3(구문 오류)의 다섯 하위 종류에 대한 몇 가지 예는 아래에 표시되어 있다.

하위 종류 1:

예약된 추가 정보 값:
1c, 1d, 1e, 3c, 3d, 3e, 5c, 5d, 5e, 7c, 7d, 7e, 9c, 9d, 9e, bc, bd, be, dc, dd, de, fc, fd, fe,
하위 종류 2:

단순 값의 예약된 2바이트 인코딩:
f8 00, f8 01, f8 18, f8 1f
하위 종류 3:

올바른 타입이 아닌 부정 길이 문자열 청크:
5f 00 ff, 5f 21 ff, 5f 61 00 ff, 5f 80 ff, 5f a0 ff, 5f c0 00 ff, 5f e0 ff, 7f 41 00 ff
정길이가 아닌 부정 길이 문자열 청크:
5f 5f 41 00 ff ff, 7f 7f 61 00 ff ff
하위 종류 4:

부정 길이 항목 밖에서 단독으로 발생하는 Break:
ff
정길이 배열, 맵 또는 태그 안에서 발생하는 Break:
81 ff, 82 00 ff, a1 ff, a1 ff 00, a1 00 ff, a2 00 00 ff, 9f 81 ff, 9f 82 9f 81 9f 9f ff ff ff ff
항목 수가 홀수가 되게 하는 부정 길이 맵 안의 Break (값 위치의 break):
bf 00 ff, bf 00 00 00 ff
하위 종류 5:

추가 정보 31을 가진 주요 타입 0, 1, 6:
1f, 3f, df

부록 G. RFC 7049에서의 변경 사항

소개에서 논의한 것처럼, 이 문서는 RFC 7049의 교환 형식과 완전한 호환성을 유지하면서 RFC 7049를 공식적으로 폐기한다. 이 문서는 편집상 개선, 추가 세부 사항 및 정오표 수정을 제공한다. 이 문서는 형식의 새 버전을 만들지 않는다.

G.1. 정오표 처리 및 사무적 변경 사항

RFC 7049의 검증된 두 정오표, [Err3764][Err3770]는 본문에 있는 두 인코딩 예와 관련되어 있었고, 이는 수정되었다 (섹션 3.4.3: "29" -> "49", 섹션 5.5: "0b000_11101" -> "0b000_11001"). 또한 RFC 7049에는 단순 값에 대해 수치 값 24를 사용하는 예 [Err5917]가 포함되어 있었는데, 이는 올바른 형식이 아니므로 이 예는 제거되었다. 정오표 보고서 5763 [Err5763]은 태그 정의 문구의 오류를 지적했으며, 이는 섹션 3.4를 다시 작성하는 과정에서 해결되었다. 정오표 보고서 5434 [Err5434]부록 E의 Universal Binary JSON (UBJSON) 예가 정오표 보고서 제출 당시의 최신 UBJSON 버전을 더 이상 준수하지 않는다고 지적했다. 2013년 이후 UBJSON 명세가 완전히 변경된 것으로 밝혀졌으므로 이 예는 제거되었다. 다른 정오표 보고서 [Err4409] [Err4963] [Err4964]는 정규 인코딩의 맵 키 정렬 규칙이 부담스럽다고 불평했으며, 이는 정규 인코딩 제안을 재검토하고 결정적 인코딩 제안 (아래 설명)으로 대체하는 결과를 낳았다. 정오표 보고서 4294의 편집상 제안 [Err4294]도 구현되었다(섹션 3.2.2의 마지막 예에 있는 주석에 "Second value"를 추가하여 대칭성을 개선).

그 밖의 사무적 변경 사항에는 다음이 포함된다.

  • 새 xml2rfc 기능 [RFC7991]의 사용;
  • 사용된 표기법에 대한 더 많은 설명;
  • 참고 문헌의 갱신, 예를 들어 RFC 4627에서 [RFC8259]로, CNN-TERMS에서 [RFC7228]로, 그리고 [ECMA262]의 5.1판에서 제11판으로의 갱신; [IEEE754]에 대한 참조 추가 및 필요한 정의의 가져오기; [C][Cplusplus20]에 대한 참조 추가; 그리고 부록 E의 논의를 더 자세히 보여 주는 [RFC8618]에 대한 참조 추가;
  • 진단 표기법에 대한 논의(섹션 8)에서, [RFC8610]에 정의된 "Extended Diagnostic Notation"(EDN)이 이제 언급되고, NaN 페이로드 표현의 공백이 이제 강조되며, 청크가 없는 부정 길이 문자열을 표현하는 설명이 추가되었다 (섹션 8.1);
  • 이 부록의 추가.

G.2. IANA 고려 사항의 변경 사항

IANA 고려 사항은 일반적으로 갱신되었다(예: 이제 명세의 저자로 CBOR Working Group을 가리키는 등의 사무적 변경). 각각의 IANA 레지스트리에 대한 참조가 정보 참고 문헌에 추가되었다.

"Concise Binary Object Representation (CBOR) Tags" 레지스트리 [IANA.cbor-tags]에서, 256부터 32767까지의 공간("1+2"의 하위 절반)에 있는 태그는 더 이상 First Come First Served로 할당되지 않는다. 이 범위는 이제 Specification Required이다.

G.3. 제안 및 기타 정보 구성 요소의 변경 사항

문서를 개정하면서, 정오표 보고서 처리 외에도, 작업 그룹은 다양한 애플리케이션 집합에서 CBOR를 사용한 거의 7년간의 경험을 활용했다. 이는 설명을 위한 표 추가를 포함한 여러 편집상 변경으로 이어졌지만, 또한 일부 측면을 강조하고 다른 측면을 덜 강조하는 결과도 낳았다.

중요한 추가 사항은 CBOR 데이터 모델과 CBOR 처리에 관여하는 그 작은 변형들을 논의하는 섹션 2이다. 이러한 변형(기본 일반, 확장 일반, 특정)에 대한 용어 도입은 문서의 다른 곳에서 더 간결한 언어를 가능하게 하고, 구현에 대한 기대와 형식의 확장성 기능을 명확히 하는 데도 도움이 된다.

JSON 생태계에서 파생된 형식으로서, RFC 7049는 당시 JavaScript에서 물려받은 JSON 숫자 시스템의 영향을 받았다. JSON은 정수와 부동소수점 값을 구별하여 제공하지 않는다 (그리고 후자는 형식에서 십진수이다). CBOR는 숫자의 이진 표현을 제공하며, 이는 정수와 부동소수점 값 사이에서 서로 다르다. 구현 및 사용 경험은 이 두 숫자 영역 사이의 분리를 문서에서 더 명확히 해야 함을 시사했다. 정수가 부동소수점 값을 매끄럽게 대신할 수 있음을 암시하는 문구는 제거되었다. 또한 JSON을 CBOR로 변환할 때 이러한 타입을 처리하기 위한 제안 (I-JSON [RFC7493] 기반)이 추가되었고, 특정 반올림 메커니즘의 사용이 권장되었다.

데이터 모델의 단일 값에 대해, CBOR는 종종 여러 인코딩 선택지를 제공한다. 새 섹션(섹션 4)은 "선호 직렬화"(섹션 4.1)라는 용어를 도입하고 다양한 종류의 데이터 항목에 대해 이를 정의한다. 이 용어를 바탕으로, 그 섹션은 CBOR 기반 프로토콜이 RFC 7049의 "canonical" 및 "canonicalization"이라는 용어를 피하면서 "결정적 인코딩"(섹션 4.2)을 정의할 수 있는 방법을 논의한다. "Core Deterministic Encoding Requirements"(섹션 4.2.1)의 제안은 그러한 프로토콜 정의 인코딩 요구 사항에 대한 일반 지원을 가능하게 한다. 이 문서는 RFC 7049에서 제안한 맵 정렬을 인코딩된 키의 단순한 사전식 정렬로 단순화하여 결정적 인코딩 구현을 더욱 쉽게 한다. 이전 제안의 설명은 이제 "길이 우선 맵 키 정렬"(섹션 4.2.3)이라고 불리는 대안으로 유지된다.

올바른 형식 및 유효한 데이터에 대한 용어가 다듬어지고 더 엄격하게 사용되었으며, 예 밖에서는 "syntax error", "decoding error", "strict mode"와 같은 덜 잘 정의된 대체 용어를 피했다. 또한 CBOR 수준의 유효성을 넘어 애플리케이션이 입력 데이터에 대해 갖는 세 번째 요구 수준이 이제 명시적으로 언급된다. 올바른 형식(전혀 처리 가능), 유효함 (유효성 검사 일반 디코더가 검사), 예상 입력 (애플리케이션이 검사)은 수용 가능성 계층의 위계로 다루어진다.

올바른 형식이 아닌 단순 값의 처리는 본문과 의사 코드에서 명확해졌다. 부록 F가 추가되어 올바른 형식 오류를 논의하고 그 예를 제공한다. 의사 코드는 더 이식 가능하도록 갱신되었으며, 몇 가지 이식성 고려 사항도 추가되었다.

유효성에 대한 논의는 두 영역에서 더 명확해졌다. 맵 유효성(중복 키 처리)이 명확해졌고, 특정 구현 선택의 적용 범위가 설명되었다. 또한 태그, 태그 번호 및 태그 내용에 대한 용어를 간소화하면서, 태그 유효성에 대한 논의가 추가되었고, 태그 내용에 대한 제한이 일반적으로 그리고 태그 1에 대해 구체적으로 명확해졌다.

직렬화 순서에 의존하는 의미를 가진 태그를 정의하는 것에 대한 구현 참고(및 향후 태그 정의를 위한 참고)가 섹션 3.4에 추가되었다.

태그 35는 이 문서에서 정의되지 않는다. RFC 7049의 정의에 기반한 등록은 그대로 유지된다.

"인수"와 "헤드"에 대한 용어가 섹션 3에 도입되어, 이후 논의를 단순화했다.

보안 고려 사항(섹션 10)은 대부분 다시 작성되고 크게 확장되었다. 문서의 여러 다른 곳에서도 디코더가 올바른 형식 오류를 단순히 용인할 수 없음을 이제 더 명시적으로 밝힌다.

감사의 말

CBOR는 MessagePack에서 영감을 받았다. MessagePack은 Sadayuki Furuhashi("frsyuki")가 개발하고 홍보했다. MessagePack에 대한 이 참조는 오직 출처 표시를 위한 것이다. CBOR는 서로 다른 설계 목표와 요구 사항을 가지므로 MessagePack의 버전이나 대체물을 의도하지 않는다.

원래 MessagePack 명세를 넘어서는 기능의 필요성은 2012년경 거의 같은 시기에 많은 사람들에게 분명해졌다. BinaryPack은 MessagePack의 작은 파생물로, binaryjs 프로젝트를 위해 Eric Zhang이 개발했다. 유사하지만 다른 확장은 Tim Caswell이 자신의 msgpack-js 및 msgpack-js-browser 프로젝트를 위해 만들었다. 많은 사람이 MessagePack을 확장하여 텍스트 문자열 표현을 바이트 문자열 표현과 분리하는 논의에 기여했다.

CBOR에서 추가 정보의 인코딩은 CoAP를 위해 Klaus Hartke가 설계한 길이 정보 인코딩에서 영감을 받았다.

이 문서는 또한 많은 사람들이 제안한 내용을 포함하고 있으며, 특히 Dan Frost, James Manger, Jeffrey Yasskin, Joe Hildebrand, Keith Moore, Laurence Lundblade, Matthew Lepinski, Michael Richardson, Nico Williams, Peter Occil, Phillip Hallam-Baker, Ray Polk, Stuart Cheshire, Tim Bray, Tony Finch, Tony Hansen, 및 Yaron Sheffer의 제안을 포함한다. Benjamin Kaduk은 IESG 처리 중 광범위한 검토를 제공했다. Éric Vyncke, Erik Kline, Robert Wilton, 및 Roman Danyliw는 추가 IESG 의견을 제공했으며, 여기에는 Eve Schooler의 IoT directorate 검토도 포함되었다.

저자 주소

Carsten Bormann
Universität Bremen TZI
Postfach 330440
D-28359 Bremen
독일
Paul Hoffman
ICANN