Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support explicitly tagged types encoding #36

Closed
yaozongyou opened this issue Sep 9, 2021 · 3 comments
Closed

support explicitly tagged types encoding #36

yaozongyou opened this issue Sep 9, 2021 · 3 comments

Comments

@yaozongyou
Copy link

yaozongyou commented Sep 9, 2021

use rasn::{AsnType,Decode,Encode};
use std::error::Error;

#[derive(Debug, AsnType, Decode, Encode)]
struct Message {
    id: i32,
    #[rasn(choice, enumerated)]
    body: BODY,
}

#[derive(Debug, AsnType, Decode, Encode)]
#[rasn(choice)]
enum BODY {
    #[rasn(tag(context, 3000))]
    Request(Request),

    #[rasn(tag(context, 3001))]
    Response(Response),
}

#[derive(Debug, AsnType, Decode, Encode)]
struct Request {
    num: i32,
}

#[derive(Debug, AsnType, Decode, Encode)]
struct Response {
    ret: i32,
}

fn main() -> Result<(), Box<dyn Error>> {
    let p = Message {
        id: 1,
        body: BODY::Request(Request { num: 1 }),
    };
    let e = rasn::der::encode(&p).unwrap();
    println!("e: {:02x?}", e);
    Ok(())
}

the above piece of code prints: 30, 0a, 02, 01, 01, bf, 97, 38, 03, 02, 01, 01
i want it to print 30, 0c, 02, 01, 01, bf, 97, 38, 05, 30, 03, 02, 01, 01 because it need to talk to some program written using c++ and golang. This encoding requires each CHOICE of BODY explicitly tagged. See 5.2 Explicitly tagged types of http://luca.ntop.org/Teaching/Appunti/asn1.html
Is it possible to achieve this?

@XAMPPRocky
Copy link
Collaborator

XAMPPRocky commented Sep 9, 2021

Is it possible to achieve this?

Thank you for your issue! Yes, but not currently through the macro. (I'm adding it soon). For now, you have to use the Explicit new type wrapper, or write the codec implementation yourself and call Encoder::encode_explicit_prefix/Decoder::decode_explicit_prefix.

#[derive(rasn::Encode, rasn::Decode)]
struct Body;

struct C0;

impl AsnType for C0 {
    const TAG: rasn::Tag = rasn::Tag::new(rasn::types::Context, 0);
}

type WrappedBody = rasn::types::Explicit<C0, Body>;

let body = WrappedBody(Body);

assert_eq!(body, rasn::ber::decode(&rasn::ber::encode(&body).unwrap()).unwrap());

@yaozongyou
Copy link
Author

yaozongyou commented Sep 9, 2021

Thanks for your reply, I will have a try with the Explicit new type wrapper.

update: @XAMPPRocky I have tried with the Explicit new type wrapper following your guide. And it prints:
30, 0c, 02, 01, 01, 9f, 97, 38, 05, 30, 03, 02, 01, 01
rather than
30, 0c, 02, 01, 01, bf, 97, 38, 05, 30, 03, 02, 01, 01
maybe, rasn regards rasn::types::Explicit as primitive instead of constructed. Is it a bug?

the full code as follows:

use rasn::{AsnType,Decode,Encode};

#[derive(Debug, AsnType, Decode, Encode)]
struct Message {
    id: i32,
    #[rasn(choice)]
    body: BODY,
}

#[derive(Debug, AsnType, Decode, Encode)]
#[rasn(choice)]
enum BODY {
    #[rasn(tag(context, 3000))]
    Request(WrappedRequest),
}

#[derive(Debug, AsnType, Decode, Encode)]
struct Request {
    num: i32,
}

#[derive(Debug)]
struct C0;

impl AsnType for C0 {
    const TAG: rasn::Tag = rasn::Tag::new(rasn::types::Class::Context, 0);
}

type WrappedRequest = rasn::types::Explicit<C0, Request>;

fn main() {
    let p = Message {
        id: 1,
        body: BODY::Request(rasn::types::Explicit::new(Request { num: 1 })),
    };

    let e = rasn::der::encode(&p).unwrap();
    println!("e: {:02x?}", e);
}

@XAMPPRocky
Copy link
Collaborator

This is now available in the macro by using explicit around your tag definition. E.g. #[rasn(tag(explicit(context, 3000)))]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants