x509-cert/const-oid: a 100-character OID (RFC 5280 Appendix B) needs 40 octets, so a certificate carrying one as a non-critical extension id does not decode
维护者通常 1 天内回复
还没有人认领这个 Issue。
- #2497 来自 @choksi2212 —— 已关闭,未合并
评估
调研方向
Start with const-oid’s DEFAULT_MAX_SIZE and parsing in src/lib.rs and src/encoder.rs, then trace DER OID decoding in der/src/asn1/oid.rs and Extension::extn_id in x509-cert’s src/ext.rs. Reproduce the 40-octet case and compare it with the 39-octet control. Done when certificates with the Appendix B sized non-critical extension OID decode successfully and the existing controls still pass.
由索引模型根据 Issue 内容生成。
描述
Hi,
RFC 5280 Appendix B requires support for OIDs whose dotted-decimal form is up to 100 characters, with up to 20 arcs, each below 2^28. ObjectIdentifier's default capacity is 39 octets. A 100-character OID that stays within those limits can need 40, and then it doesn't fit. When that OID is the id of a non-critical extension, Certificate::from_der refuses the whole certificate, although RFC 5280 §4.2 says a non-critical extension a relying party doesn't recognise MAY be ignored.
The OID used is 1.3 followed by nine arcs of 268435455 (2^28 − 1, the largest Appendix B mandates) and then 123456: 12 arcs, 100 characters, 40 contents octets (1 + 9 × 4 + 3). The control swaps the last arc for 16383 (99 characters, 39 octets) and decodes fine. The three test certificates differ only in that extension id, and both controls re-encode to the exact octets they were decoded from, so the DER is canonical and the 40th octet is what fails.
What the reproduction shows
| const-oid 0.10.2 + x509-cert 0.3.0 | const-oid 0.9.6 + x509-cert 0.2.5 | |
|---|---|---|
| OID, 100 chars / 40 octets | new and from_bytes: Err(Length) |
from_bytes: Err(NotEnoughArcs) |
| OID, 99 chars / 39 octets (control) | Ok |
Ok |
certificate, extension id 1.3.6.1.4.1.99999.1 (control) |
Ok, re-encodes identically |
Ok, re-encodes identically |
| certificate, extension id = the 99-char OID (control) | Ok, re-encodes identically |
Ok, re-encodes identically |
| certificate, extension id = the 100-char OID | Err: incorrect length for OBJECT IDENTIFIER at DER byte 214 |
Err: incorrect length for OBJECT IDENTIFIER at DER byte 212 |
Where it comes from
- const-oid 0.10.2:
DEFAULT_MAX_SIZEis 39 (src/lib.rs:48,src/lib.rs:66). The string parser refuses an arc that would end past it (src/encoder.rs:96-102), andfrom_bytesdoes the same after checking the arcs (src/lib.rs:121-132intosrc/lib.rs:234-254,Error::Lengthat:240-241). - der 0.8.2 decodes an
OBJECT IDENTIFIERinto a buffer of that capacity and fails when the contents are longer (src/asn1/oid.rs:12-28). - x509-cert 0.3.0 and 0.2.5 type
Extension::extn_idas the defaultObjectIdentifier(src/ext.rs:29-36), and the extensions are a field of the TBS certificate (src/certificate.rs:163-164in 0.3.0), so one extension id that doesn't fit fails the decode, critical or not. - On 0.9.6,
from_bytesreports an input that is too long asError::NotEnoughArcs(src/lib.rs:143-147), which names the wrong problem.
flowchart TD
cert["Certificate DER, extension id = 1.3 + 9 x 268435455 + 123456<br/>100 characters, 40 octets (RFC 5280 App. B: must be supported)"]
cert --> a["x509-cert 0.3.0 Certificate::from_der"]
cert --> b["x509-cert 0.2.5 Certificate::from_der"]
a --> ext3["Extension.extn_id: ObjectIdentifier<br/>ext.rs:29-36"]
b --> ext2["Extension.extn_id: ObjectIdentifier<br/>ext.rs:29-36"]
ext3 --> d8["der 0.8.2 decode_value: buf [u8; 39]<br/>oid.rs:12-28 -> length error"]
ext2 --> d7["der 0.7.10 decode_value: buf [u8; 39]<br/>oid.rs:12-23 -> length error"]
d8 --> cap10["const-oid 0.10.2 DEFAULT_MAX_SIZE = 39<br/>lib.rs:48, 66"]
d7 --> cap9["const-oid 0.9.6 MAX_SIZE = 39<br/>lib.rs:92"]
cap10 --> fail["Err: the whole certificate is unreadable<br/>(RFC 5280 4.2: a non-critical extension MAY be ignored)"]
cap9 --> fail
ctl["control: the same certificate with 39 octets<br/>Ok, re-encodes identically"]
classDef bad fill:#fde,stroke:#b35
classDef good fill:#def,stroke:#37b
class fail bad
class ctl good
This is related to #1984 but isn't the same thing: that asked for arcs beyond 2^32, which Appendix B doesn't require. This OID is inside Appendix B's limits and is one octet over the default capacity.
What would help, if you agree it's worth fixing: a default capacity that holds every OID Appendix B mandates, or an x509-cert decode path that accepts a larger MAX_SIZE, which const-oid's const parameter already makes possible. I'm happy to send a PR for whichever you prefer.
Reproduction script (self-contained; needs bash, rustup and network access for cargo to fetch the pinned crates)
Save it as repro.sh and run bash repro.sh. It writes a small Cargo project (locked by its own Cargo.lock) into a new temporary directory, builds it with Rust 1.98.0, and compares each observation with the table above. It exits 0 when everything matches. The script is yours to use under Apache-2.0 OR MIT.
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
# Self-contained reproduction (UP-CONSTOID-001). It writes the files below into a new
# temporary directory and runs repro.sh there; nothing outside that
# directory is written. Run it with: bash this-file.sh
set -euo pipefail
dir=$(mktemp -d "${TMPDIR:-/tmp}/repro.XXXXXX")
echo "files written to $dir"
cat >"$dir/rust-toolchain.toml" <<'__REPRO_FILE_1__'
[toolchain]
channel = "1.98.0"
__REPRO_FILE_1__
mkdir -p "$dir/harness"
cat >"$dir/harness/Cargo.lock" <<'__REPRO_FILE_2__'
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "base64ct"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "const-oid"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
[[package]]
name = "der"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
"const-oid 0.9.6",
"der_derive 0.7.3",
"flagset",
"zeroize",
]
[[package]]
name = "der"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a878c850e9e421b20262e9b41f9c860e4785fa07541c266b62ff9d1ef998a80a"
dependencies = [
"const-oid 0.10.2",
"der_derive 0.8.0",
"flagset",
"zeroize",
]
[[package]]
name = "der_derive"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "der_derive"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59600e2c2d636fde9b65e99cc6445ac770c63d3628195ff39932b8d6d7409903"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "flagset"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"
[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der 0.7.10",
]
[[package]]
name = "spki"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef958a98b9d5da290cfc78946e9f3e61e1e62a18db0d92cac0b83cc161491a9"
dependencies = [
"base64ct",
"der 0.8.2",
]
[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
[[package]]
name = "up-constoid-001"
version = "0.0.0"
dependencies = [
"const-oid 0.10.2",
"const-oid 0.9.6",
"x509-cert 0.2.5",
"x509-cert 0.3.0",
]
[[package]]
name = "x509-cert"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1301e935010a701ae5f8655edc0ad17c44bad3ac5ce8c39185f75453b720ae94"
dependencies = [
"const-oid 0.9.6",
"der 0.7.10",
"spki 0.7.3",
]
[[package]]
name = "x509-cert"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "105ef4642d9cb137ef83d623d0e4bf08b8adf69e9918ca904a174adb6d3d038b"
dependencies = [
"const-oid 0.10.2",
"der 0.8.2",
"spki 0.8.1",
]
[[package]]
name = "zeroize"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879"
__REPRO_FILE_2__
mkdir -p "$dir/harness"
cat >"$dir/harness/Cargo.toml" <<'__REPRO_FILE_3__'
# SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
# UP-CONSTOID-001's harness: const-oid 0.10.2 under x509-cert 0.3.0 (the
# newest of each), and const-oid 0.9.6 under x509-cert 0.2.5 (the 0.2
# line).
[package]
name = "up-constoid-001"
version = "0.0.0"
edition = "2021"
publish = false
[dependencies]
const-oid = "=0.10.2"
x509-cert = { version = "=0.3.0", default-features = false }
const-oid-09 = { package = "const-oid", version = "=0.9.6" }
x509-cert-02 = { package = "x509-cert", version = "=0.2.5", default-features = false }
[workspace]
__REPRO_FILE_3__
mkdir -p "$dir/harness/src"
cat >"$dir/harness/src/main.rs" <<'__REPRO_FILE_4__'
// SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
// SPDX-License-Identifier: Apache-2.0 OR MIT
//
//! UP-CONSTOID-001: an OID whose dotted-decimal form is 100 characters, as
//! the id of a non-critical extension, through const-oid 0.10.2 / x509-cert
//! 0.3.0 and const-oid 0.9.6 / x509-cert 0.2.5. RFC 5280 Appendix B:
//! "Implementations MUST also support OIDs where the length of the dotted
//! decimal ... string representation can be up to 100 bytes (inclusive)."
//! The certificate is assembled here octet by octet, so nothing of either
//! crate builds it; the control decodes and re-encodes to the same octets.
//! Prints `OBS key=value`.
use x509_cert::der::{Decode as _, Encode as _};
use x509_cert_02::der::{Decode as _, Encode as _};
/// The dotted form: `1.3`, nine `.268435455` (2^28 - 1, the largest arc RFC
/// 5280 Appendix B mandates) and a last arc.
fn dotted(last: u32) -> String {
let mut s = String::from("1.3");
for _ in 0..9 {
s.push_str(".268435455");
}
s.push_str(&format!(".{last}"));
s
}
/// X.690 §8.19 contents octets, written here rather than by either crate.
fn oid_contents(dotted: &str) -> Vec<u8> {
let arcs: Vec<u64> = dotted.split('.').map(|a| a.parse().expect("digits")).collect();
let mut out = vec![(arcs[0] * 40 + arcs[1]) as u8];
for &arc in &arcs[2..] {
let mut groups = vec![(arc & 0x7f) as u8];
let mut rest = arc >> 7;
while rest > 0 {
groups.push(0x80 | (rest & 0x7f) as u8);
rest >>= 7;
}
groups.reverse();
out.extend(groups);
}
out
}
fn tlv(tag: u8, value: &[u8]) -> Vec<u8> {
let mut out = vec![tag];
let n = value.len();
if n < 0x80 {
out.push(n as u8);
} else if n <= 0xff {
out.extend([0x81, n as u8]);
} else {
out.extend([0x82, (n >> 8) as u8, n as u8]);
}
out.extend_from_slice(value);
out
}
fn seq(parts: &[Vec<u8>]) -> Vec<u8> {
tlv(0x30, &parts.concat())
}
fn oid(dotted: &str) -> Vec<u8> {
tlv(0x06, &oid_contents(dotted))
}
/// A v3 certificate with one non-critical extension whose id is `ext_id`.
fn certificate(ext_id: &str) -> Vec<u8> {
let ecdsa_sha256 = seq(&[oid("1.2.840.10045.4.3.2")]);
let name = seq(&[tlv(0x31, &seq(&[oid("2.5.4.3"), tlv(0x0c, b"up-constoid-001")]))]);
let validity = seq(&[tlv(0x17, b"250101000000Z"), tlv(0x17, b"350101000000Z")]);
let mut point = vec![0x00, 0x04];
point.extend([0x11; 64]);
let spki = seq(&[
seq(&[oid("1.2.840.10045.2.1"), oid("1.2.840.10045.3.1.7")]),
tlv(0x03, &point),
]);
let extension = seq(&[oid(ext_id), tlv(0x04, &[0x05, 0x00])]);
let tbs = seq(&[
tlv(0xa0, &tlv(0x02, &[0x02])),
tlv(0x02, &[0x01]),
ecdsa_sha256.clone(),
name.clone(),
validity,
name,
spki,
tlv(0xa3, &seq(&[extension])),
]);
seq(&[tbs, ecdsa_sha256, tlv(0x03, &[0x00, 0x01, 0x02, 0x03])])
}
fn obs(key: &str, value: impl std::fmt::Display) {
println!("OBS {key}={value}");
}
fn verdict<T, E: std::fmt::Debug>(r: &Result<T, E>) -> String {
match r {
Ok(_) => "Ok".to_owned(),
Err(e) => format!("Err({e:?})"),
}
}
/// Decode with both x509-cert lines; on Ok, say whether re-encoding gives
/// back the same octets (it proves the assembled DER is the canonical form).
fn decode_both(label: &str, der: &[u8]) {
match x509_cert::Certificate::from_der(der) {
Ok(cert) => {
obs(&format!("{label}.x509-cert-0.3.0"), "Ok");
obs(
&format!("{label}.x509-cert-0.3.0.reencodes-identically"),
cert.to_der().map(|d| d == der).unwrap_or(false),
);
}
Err(e) => {
obs(&format!("{label}.x509-cert-0.3.0"), "Err");
obs(&format!("info.{label}.x509-cert-0.3.0.error"), e);
}
}
match x509_cert_02::Certificate::from_der(der) {
Ok(cert) => {
obs(&format!("{label}.x509-cert-0.2.5"), "Ok");
obs(
&format!("{label}.x509-cert-0.2.5.reencodes-identically"),
cert.to_der().map(|d| d == der).unwrap_or(false),
);
}
Err(e) => {
obs(&format!("{label}.x509-cert-0.2.5"), "Err");
obs(&format!("info.{label}.x509-cert-0.2.5.error"), e);
}
}
}
fn main() {
// 100 characters, 40 BER octets: the claim.
let long = dotted(123456);
// 99 characters, 39 BER octets: the largest the crates hold.
let fits = dotted(16383);
obs("oid100.chars", long.len());
obs("oid100.ber-octets", oid_contents(&long).len());
obs("oid99.chars", fits.len());
obs("oid99.ber-octets", oid_contents(&fits).len());
obs("const-oid-0.10.2.new(oid100)", verdict(&const_oid::ObjectIdentifier::new(&long)));
obs(
"const-oid-0.10.2.from_bytes(oid100)",
verdict(&const_oid::ObjectIdentifier::from_bytes(&oid_contents(&long))),
);
obs("const-oid-0.10.2.new(oid99)", verdict(&const_oid::ObjectIdentifier::new(&fits)));
obs(
"const-oid-0.9.6.from_bytes(oid100)",
verdict(&const_oid_09::ObjectIdentifier::from_bytes(&oid_contents(&long))),
);
obs(
"const-oid-0.9.6.from_bytes(oid99)",
verdict(&const_oid_09::ObjectIdentifier::from_bytes(&oid_contents(&fits))),
);
obs("info.const-oid-0.9.6.new(oid100)", verdict(&const_oid_09::ObjectIdentifier::new(&long)));
obs("info.const-oid-0.9.6.new(oid99)", verdict(&const_oid_09::ObjectIdentifier::new(&fits)));
decode_both("control", &certificate("1.3.6.1.4.1.99999.1"));
decode_both("cert-oid99", &certificate(&fits));
decode_both("cert-oid100", &certificate(&long));
}
__REPRO_FILE_4__
cat >"$dir/repro.sh" <<'__REPRO_FILE_5__'
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Protoworks Group (Pty) Ltd
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
set -euo pipefail
# repro.sh — UP-CONSTOID-001: an OID whose dotted-decimal form is 100
# characters (RFC 5280 Appendix B: "MUST also support OIDs where the length
# of the dotted decimal ... string representation can be up to 100 bytes")
# does not fit const-oid's ObjectIdentifier, in 0.10.2 (the newest, under
# x509-cert 0.3.0) or 0.9.6 (under x509-cert 0.2.5); as the id of a
# non-critical extension it makes the whole certificate undecodable. A
# defensive check over a certificate the harness assembles octet by octet.
#
# ./repro.sh
#
# What it does: builds harness/ (locked by harness/Cargo.lock) with the
# toolchain rust-toolchain.toml pins, runs it, and compares each
# `OBS key=value` with EXPECT, the claim table of the report. Lines named
# info.* are printed for the reader and not checked.
#
# Network: cargo's fetch of the crates harness/Cargo.lock pins. Nothing else.
#
# Exit status: 0 when every check holds (the defect is shown); otherwise the
# number of checks that disagreed; 2 if the harness could not be built or run.
#
# Dependencies: bash, awk, cargo and rustup (1.98.0).
here=$(cd "$(dirname "$0")" && pwd)
cd "$here"
fail=0
note() { echo "repro: $*"; }
check() { # check <label> <want> <got>
if [[ "$2" == "$3" ]]; then
printf ' ok %-60s %s\n' "$1" "$3"
else
printf ' FAIL %-60s got %s, want %s\n' "$1" "$3" "$2"
fail=$((fail + 1))
fi
}
if ! command -v cargo >/dev/null 2>&1; then
note "cargo is not installed; cannot run"
exit 2
fi
target=$(mktemp -d "${TMPDIR:-/tmp}/up-ev.XXXXXX")
trap 'rm -rf "$target"' EXIT
# The toolchain is the one the repository's rust-toolchain.toml pins.
rustc_version=$(cd "$here/harness" && rustc --version)
note "toolchain: $rustc_version"
check "rustc is the pinned 1.98.0" "rustc 1.98.0" "$(cut -d' ' -f1-2 <<<"$rustc_version")"
run_harness() { # run_harness -> the harness's stdout
(cd "$here/harness" && CARGO_TARGET_DIR="$target" cargo run --locked --quiet --release)
}
compare() { # compare <label> <harness output> ; reads key=value lines on stdin
local label="$1" out="$2" key want got
while IFS='=' read -r key want; do
[[ -z "$key" || "$key" == \#* ]] && continue
got=$(awk -v k="OBS ${key}=" 'index($0, k) == 1 { print substr($0, length(k) + 1); exit }' <<<"$out")
[[ -n "$got" ]] || got="(not printed)"
check "$label: $key" "$want" "$got"
done
}
finish() { # finish <id>
echo
if [[ "$fail" -eq 0 ]]; then
note "all checks held: $1 is shown as the report states it"
exit 0
fi
note "$fail checks disagreed with the claim"
exit "$fail"
}
note "building and running harness/ (const-oid 0.10.2 + x509-cert 0.3.0, const-oid 0.9.6 + x509-cert 0.2.5)"
out=$(run_harness) || { note "the harness did not build or run"; exit 2; }
printf '%s\n' "$out" | sed 's/^/ /'
compare oid "$out" <<'EXPECT'
oid100.chars=100
oid100.ber-octets=40
oid99.chars=99
oid99.ber-octets=39
EXPECT
compare const-oid "$out" <<'EXPECT'
const-oid-0.10.2.new(oid100)=Err(Length)
const-oid-0.10.2.from_bytes(oid100)=Err(Length)
const-oid-0.10.2.new(oid99)=Ok
const-oid-0.9.6.from_bytes(oid100)=Err(NotEnoughArcs)
const-oid-0.9.6.from_bytes(oid99)=Ok
EXPECT
# The controls: the assembled certificate is canonical DER, and the
# extension id is the only thing that changes between the three.
compare control "$out" <<'EXPECT'
control.x509-cert-0.3.0=Ok
control.x509-cert-0.3.0.reencodes-identically=true
control.x509-cert-0.2.5=Ok
control.x509-cert-0.2.5.reencodes-identically=true
cert-oid99.x509-cert-0.3.0=Ok
cert-oid99.x509-cert-0.3.0.reencodes-identically=true
cert-oid99.x509-cert-0.2.5=Ok
cert-oid99.x509-cert-0.2.5.reencodes-identically=true
EXPECT
compare claim "$out" <<'EXPECT'
cert-oid100.x509-cert-0.3.0=Err
cert-oid100.x509-cert-0.2.5=Err
EXPECT
finish UP-CONSTOID-001
__REPRO_FILE_5__
chmod +x "$dir/repro.sh"
cd "$dir" && ./repro.sh
Recorded run (macOS arm64, rustc 1.98.0)
repro: toolchain: rustc 1.98.0 (88d9e12ae 2026-08-18)
ok rustc is the pinned 1.98.0 rustc 1.98.0
repro: building and running harness/ (const-oid 0.10.2 + x509-cert 0.3.0, const-oid 0.9.6 + x509-cert 0.2.5)
ok oid: oid100.chars 100
ok oid: oid100.ber-octets 40
ok oid: oid99.chars 99
ok oid: oid99.ber-octets 39
ok const-oid: const-oid-0.10.2.new(oid100) Err(Length)
ok const-oid: const-oid-0.10.2.from_bytes(oid100) Err(Length)
ok const-oid: const-oid-0.10.2.new(oid99) Ok
ok const-oid: const-oid-0.9.6.from_bytes(oid100) Err(NotEnoughArcs)
ok const-oid: const-oid-0.9.6.from_bytes(oid99) Ok
ok control: control.x509-cert-0.3.0 Ok
ok control: control.x509-cert-0.3.0.reencodes-identically true
ok control: control.x509-cert-0.2.5 Ok
ok control: control.x509-cert-0.2.5.reencodes-identically true
ok control: cert-oid99.x509-cert-0.3.0 Ok
ok control: cert-oid99.x509-cert-0.3.0.reencodes-identically true
ok control: cert-oid99.x509-cert-0.2.5 Ok
ok control: cert-oid99.x509-cert-0.2.5.reencodes-identically true
ok claim: cert-oid100.x509-cert-0.3.0 Err
ok claim: cert-oid100.x509-cert-0.2.5 Err
repro: all checks held: UP-CONSTOID-001 is shown as the report states it
- 主要语言
- Rust
- 星标
- 344
- 派生
- 196
- 平均合并
- 1 天 17 小时
- 30 天内合并 PR
- 24
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
RustCrypto/formats 的其他 Issue
-
pem-rfc7468: a lone CR before -----BEGIN is refused as Error::Preamble, so a CR-terminated multi-certificate PEM fails load_pem_chain (RFC 7468 eol = CRLF / CR / LF)可能已有人在做 @choksi2212 于 5 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 77/100
RustCrypto/formats#2486 · 1 条评论 ·
维护者通常 1 天内回复
-
IssuingDistributionPoint has the wrong AssociatedOid (id-pe-subjectInfoAccess)可能已有人在做 @eyusd 于 84 天前认领。 未关闭
难度 1/5 1-3 小时 新手友好度 86/100
RustCrypto/formats#2389 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 68/100
RustCrypto/formats#2366 ·
维护者通常 1 天内回复
-
x509-cert 0.3.0 declares RFC 5914's TrustAnchorInfo v1 as 0, so it encodes v1 as INTEGER 0 and reads a written version 0 as v1可能已有人在做 @choksi2212 于 5 天前认领。 未关闭
难度 3/5 1-2 天 新手友好度 61/100
RustCrypto/formats#2487 · 2 条评论 ·
维护者通常 1 天内回复
-
mcf: `PasswordHash::push_base64` with empty input produces an invalid hash可能已有人在做 @choksi2212 于 3 天前认领。 未关闭
难度 4/5 3-5 天 新手友好度 45/100
RustCrypto/formats#2471 ·
维护者通常 1 天内回复
查看 RustCrypto/formats 的全部 Issue
相似的 Issue
-
area: library data-loss type: bug
难度 2/5 1-3 小时 新手友好度 72/100
alplabai/signex#1740 · 1 条评论 ·
维护者通常 1 天内回复
-
test(fslc): the unreadable mutate catalog test pins the Unix I/O error text and fails on Windows可能已有人在做 @rizumita 今天认领。 未关闭
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 69/100
维护者通常 1 天内回复
-
ServerProperties defaults white-list to true, so a fresh --dedicated server silently locks itself未关闭
难度 2/5 1-3 小时 新手友好度 78/100
horizon-rust/horizon#3888 ·
维护者通常 1 天内回复
-
refactor
难度 2/5 1-3 小时 新手友好度 66/100
维护者通常 1 天内回复