Protocol: freeze device proof and browser CSRF contracts
This commit is contained in:
@@ -187,6 +187,7 @@ def generate_go(defs: dict[str, dict[str, Any]], schema_hash: str, version: str,
|
||||
"",
|
||||
"import (",
|
||||
"\"bytes\"",
|
||||
"\"encoding/binary\"",
|
||||
"\"encoding/base64\"",
|
||||
"\"encoding/json\"",
|
||||
"\"errors\"",
|
||||
@@ -272,6 +273,22 @@ def generate_go(defs: dict[str, dict[str, Any]], schema_hash: str, version: str,
|
||||
out.append("}")
|
||||
out.append("")
|
||||
out.extend([
|
||||
"func DeviceRegistrationProofTranscript(serverID, principalID, deviceID, challenge []byte, expiryUnixMilliseconds int64) ([]byte, error) {",
|
||||
"\tfor _, value := range []struct { field string; bytes []byte; length int }{{\"server_id\", serverID, 16}, {\"principal_id\", principalID, 16}, {\"device_id\", deviceID, 16}, {\"challenge\", challenge, 32}} {",
|
||||
"\t\tif len(value.bytes) != value.length { return nil, ValidationError{Violations: []FieldViolation{{Field: value.field, Code: \"invalid_length\"}}} }",
|
||||
"\t}",
|
||||
"\tif expiryUnixMilliseconds < 0 { return nil, ValidationError{Violations: []FieldViolation{{Field: \"expiry_unix_milliseconds\", Code: \"minimum\"}}} }",
|
||||
"\ttranscript := make([]byte, 0, 112)",
|
||||
"\ttranscript = append(transcript, \"versevdi-device-proof-v1\"...)",
|
||||
"\ttranscript = append(transcript, serverID...)",
|
||||
"\ttranscript = append(transcript, principalID...)",
|
||||
"\ttranscript = append(transcript, deviceID...)",
|
||||
"\ttranscript = append(transcript, challenge...)",
|
||||
"\tvar expiry [8]byte",
|
||||
"\tbinary.BigEndian.PutUint64(expiry[:], uint64(expiryUnixMilliseconds))",
|
||||
"\treturn append(transcript, expiry[:]...), nil",
|
||||
"}",
|
||||
"",
|
||||
"var ErrNoCapabilityOverlap = errors.New(\"no capability overlap\")",
|
||||
"",
|
||||
"func IntersectCapabilityProfiles(profiles ...CapabilityProfile) (CapabilityProfile, error) {",
|
||||
@@ -508,6 +525,21 @@ def generate_rust(defs: dict[str, dict[str, Any]], schema_hash: str, compatibili
|
||||
])
|
||||
out.extend(["}", ""])
|
||||
out.extend([
|
||||
"pub fn device_registration_proof_transcript(server_id: &[u8], principal_id: &[u8], device_id: &[u8], challenge: &[u8], expiry_unix_milliseconds: i64) -> Result<Vec<u8>, ValidationError> {",
|
||||
" for (field, value, length) in [(\"server_id\", server_id, 16), (\"principal_id\", principal_id, 16), (\"device_id\", device_id, 16), (\"challenge\", challenge, 32)] {",
|
||||
" if value.len() != length { return Err(ValidationError::new(field, \"invalid_length\")); }",
|
||||
" }",
|
||||
" if expiry_unix_milliseconds < 0 { return Err(ValidationError::new(\"expiry_unix_milliseconds\", \"minimum\")); }",
|
||||
" let mut transcript = Vec::with_capacity(112);",
|
||||
" transcript.extend_from_slice(b\"versevdi-device-proof-v1\");",
|
||||
" transcript.extend_from_slice(server_id);",
|
||||
" transcript.extend_from_slice(principal_id);",
|
||||
" transcript.extend_from_slice(device_id);",
|
||||
" transcript.extend_from_slice(challenge);",
|
||||
" transcript.extend_from_slice(&(expiry_unix_milliseconds as u64).to_be_bytes());",
|
||||
" Ok(transcript)",
|
||||
"}",
|
||||
"",
|
||||
"pub fn intersect_capability_profiles(profiles: &[CapabilityProfile]) -> Result<CapabilityProfile, ValidationError> {",
|
||||
" let mut selected = profiles.first().ok_or_else(|| ValidationError::new(\"capabilities\", \"no_overlap\"))?.clone();",
|
||||
" selected.validate().map_err(|_| ValidationError::new(\"capabilities\", \"no_overlap\"))?;",
|
||||
@@ -674,6 +706,21 @@ def generate_swift(defs: dict[str, dict[str, Any]], schema_hash: str, compatibil
|
||||
out.extend(swift_validation(definition))
|
||||
out.extend([" }", "", " public static func decodeJSON(_ data: Data) throws -> Self { try JSONDecoder().decode(Self.self, from: data) }", " public func encodeJSON() throws -> Data { try validate(); return try JSONEncoder().encode(self) }", "}", ""])
|
||||
out.extend([
|
||||
"public func deviceRegistrationProofTranscript(serverID: Data, principalID: Data, deviceID: Data, challenge: Data, expiryUnixMilliseconds: Int64) throws -> Data {",
|
||||
" for (field, value, length) in [(\"server_id\", serverID, 16), (\"principal_id\", principalID, 16), (\"device_id\", deviceID, 16), (\"challenge\", challenge, 32)] {",
|
||||
" if value.count != length { throw ContractValidationError(field: field, code: \"invalid_length\") }",
|
||||
" }",
|
||||
" if expiryUnixMilliseconds < 0 { throw ContractValidationError(field: \"expiry_unix_milliseconds\", code: \"minimum\") }",
|
||||
" var transcript = Data(\"versevdi-device-proof-v1\".utf8)",
|
||||
" transcript.append(serverID)",
|
||||
" transcript.append(principalID)",
|
||||
" transcript.append(deviceID)",
|
||||
" transcript.append(challenge)",
|
||||
" var expiry = UInt64(expiryUnixMilliseconds).bigEndian",
|
||||
" Swift.withUnsafeBytes(of: &expiry) { transcript.append(contentsOf: $0) }",
|
||||
" return transcript",
|
||||
"}",
|
||||
"",
|
||||
"public extension TunnelAdmissionRequest {",
|
||||
" func deviceAdmissionTranscript() -> Data {",
|
||||
" var fields = [sessionId, gatewayId, audience, grant, String(reconnectSequence), clientNonce, capabilities.transport, capabilities.framing, capabilities.media, capabilities.audio, capabilities.sourceRateControl, String(capabilities.clientDecode.count)]",
|
||||
|
||||
Reference in New Issue
Block a user