Parsing Google Authenticator export QR codes
23 May 2020We recently added support for scanning the new Google Authenticator export QR codes to Aegis Authenticator. The single token URI format is well-documented, but the format of the QR codes displayed in the new export feature of Google Authenticator is not. It’s not immediately obvious how the format works without doing some reverse engineering, so I figured I’d briefly explain it in a blog post.
The QR codes contain a URI with the following format:
otpauth-migration://offline?data=...
The scheme is otpauth-migration
,
the host is offline
and there is a data
query parameter. The data
parameter is a base64 encoded Protobuf message with the following format:
syntax = "proto3";
message MigrationPayload {
enum Algorithm {
ALGORITHM_UNSPECIFIED = 0;
ALGORITHM_SHA1 = 1;
ALGORITHM_SHA256 = 2;
ALGORITHM_SHA512 = 3;
ALGORITHM_MD5 = 4;
}
enum DigitCount {
DIGIT_COUNT_UNSPECIFIED = 0;
DIGIT_COUNT_SIX = 1;
DIGIT_COUNT_EIGHT = 2;
}
enum OtpType {
OTP_TYPE_UNSPECIFIED = 0;
OTP_TYPE_HOTP = 1;
OTP_TYPE_TOTP = 2;
}
message OtpParameters {
bytes secret = 1;
string name = 2;
string issuer = 3;
Algorithm algorithm = 4;
DigitCount digits = 5;
OtpType type = 6;
int64 counter = 7;
}
repeated OtpParameters otp_parameters = 1;
int32 version = 2;
int32 batch_size = 3;
int32 batch_index = 4;
int32 batch_id = 5;
}
The Protobuf message contains a list of OtpParameters. If you’ve worked with
HOTP/TOTP before, the fields in OtpParameters should look familiar, so I won’t
explain them here. If there are more than a few entries to export from Google
Authenticator, they will be split up into multiple QR codes. The batch_size
and batch_index
fields indicate the number of QR codes and the index of this
QR code, respectively. The batch_id
is a unique identifier for the export
attempt.
I’m not 100% sure if the types of the fields are exactly correct, as I don’t have access to the Protobuf message definition file of Google Authenticator, but they seem to match up well enough.