matrix-org / vodozemac

An implementation of Olm and Megolm in pure Rust.
Apache License 2.0
155 stars 29 forks source link

Encoding issue with GroupSession #69

Closed ctron closed 2 years ago

ctron commented 2 years ago

Describe the bug

I believe that there is an encoding issue with the GroupSession messages.

To Reproduce Steps to reproduce the behavior:

fn test(payload: &str) -> anyhow::Result<()> {
    let outbound = vodozemac::megolm::GroupSession::new();

    let json = serde_json::to_string(&outbound.pickle())?;
    let mut outbound: vodozemac::megolm::GroupSession =
        serde_json::from_str::<vodozemac::megolm::GroupSessionPickle>(&json)?.into();

    let session_key = outbound.session_key().to_base64();
    let inbound = olm_rs::inbound_group_session::OlmInboundGroupSession::new(&session_key)?;

    let mut i = 10;
    let msg = loop {
        let msg = outbound.encrypt(payload).to_bytes();

        i -= 1;
        if i == 0 {
            break base64::encode(&msg);
        }
    };

    let _msg = inbound.decrypt(msg)?;

    //assert_eq!(payload, msg.0);
    //println!("Message: {msg:?}");

    Ok(())
}

fn main() {
    for i in 0..256 {
        let payload = "0".repeat(i);
        println!("{i}: {}", if test(&payload).is_ok() { "Ok" } else { "Err" });
    }
}

Expected behavior All messages decode properly.

Screenshots

Log output ``` 0: Ok 1: Ok 2: Ok 3: Ok 4: Ok 5: Ok 6: Ok 7: Ok 8: Ok 9: Ok 10: Ok 11: Ok 12: Ok 13: Ok 14: Ok 15: Ok 16: Err 17: Err 18: Err 19: Err 20: Err 21: Err 22: Err 23: Err 24: Err 25: Err 26: Err 27: Err 28: Err 29: Err 30: Err 31: Err 32: Err 33: Err 34: Err 35: Err 36: Err 37: Err 38: Err 39: Err 40: Err 41: Err 42: Err 43: Err 44: Err 45: Err 46: Err 47: Err 48: Ok 49: Ok 50: Ok 51: Ok 52: Ok 53: Ok 54: Ok 55: Ok 56: Ok 57: Ok 58: Ok 59: Ok 60: Ok 61: Ok 62: Ok 63: Ok 64: Err 65: Err 66: Err 67: Err 68: Err 69: Err 70: Err 71: Err 72: Err 73: Err 74: Err 75: Err 76: Err 77: Err 78: Err 79: Err 80: Err 81: Err 82: Err 83: Err 84: Err 85: Err 86: Err 87: Err 88: Err 89: Err 90: Err 91: Err 92: Err 93: Err 94: Err 95: Err 96: Ok 97: Ok 98: Ok 99: Ok 100: Ok 101: Ok 102: Ok 103: Ok 104: Ok 105: Ok 106: Ok 107: Ok 108: Ok 109: Ok 110: Ok 111: Ok 112: Err 113: Err 114: Err 115: Err 116: Err 117: Err 118: Err 119: Err 120: Err 121: Err 122: Err 123: Err 124: Err 125: Err 126: Err 127: Err 128: Ok 129: Ok 130: Ok 131: Ok 132: Ok 133: Ok 134: Ok 135: Ok 136: Ok 137: Ok 138: Ok 139: Ok 140: Ok 141: Ok 142: Ok 143: Ok 144: Err 145: Err 146: Err 147: Err 148: Err 149: Err 150: Err 151: Err 152: Err 153: Err 154: Err 155: Err 156: Err 157: Err 158: Err 159: Err 160: Err 161: Err 162: Err 163: Err 164: Err 165: Err 166: Err 167: Err 168: Err 169: Err 170: Err 171: Err 172: Err 173: Err 174: Err 175: Err 176: Ok 177: Ok 178: Ok 179: Ok 180: Ok 181: Ok 182: Ok 183: Ok 184: Ok 185: Ok 186: Ok 187: Ok 188: Ok 189: Ok 190: Ok 191: Ok 192: Err 193: Err 194: Err 195: Err 196: Err 197: Err 198: Err 199: Err 200: Err 201: Err 202: Err 203: Err 204: Err 205: Err 206: Err 207: Err 208: Err 209: Err 210: Err 211: Err 212: Err 213: Err 214: Err 215: Err 216: Err 217: Err 218: Err 219: Err 220: Err 221: Err 222: Err 223: Err 224: Ok 225: Ok 226: Ok 227: Ok 228: Ok 229: Ok 230: Ok 231: Ok 232: Ok 233: Ok 234: Ok 235: Ok 236: Ok 237: Ok 238: Ok 239: Ok 240: Err 241: Err 242: Err 243: Err 244: Err 245: Err 246: Err 247: Err 248: Err 249: Err 250: Err 251: Err 252: Err 253: Err 254: Err 255: Err ```

Additional context

The reverse test (encoding with libolm and decoding with vodozemac) works all the time.

poljar commented 2 years ago

You seem to be using your own base64 encoding method, does this happen with the to_base64() method that MegolmMessage has as well?

You'll need to configure your base64 encoder to use unpadded base64 for libolm to be able to decode it.

ctron commented 2 years ago

@poljar yea, I dug a bit deeper into that after lunch :) … and came to the same result. Thanks for taking a look!

I also did try this out with a matrix of encoding/decoder x volozemac/olm. Volozemac actually decodes base64 just fine, in any case. While libolm fails in weird ways when the format is not right.

I shouldn't have expected that a pure Rust implementation fails like this :grin:

So if there is a bug, then I guess it is with libolm, and not with vodozemac :) Sorry for the noise.