@NeonLost как и обещал, позанимался твоей задачкой. Имею сказать по ней следующее. Твоя уверенностиь в “невзамываемости” шифра базировалась на том, что ты используешь шифрование без дополнения, что исключает атаку
padding oracle
, которую я в самом начале и собирался применить когда вообще зашел разговор о локальном взломе. Обычно такие брутфорсеры собираются на коленке на базе BadPaddingException или GeneralSecurityException и время взлома пинкода занимается около 20минут в самом худшем случае.
Отсутствие дополнения, которое в общем-то не рекомендуется применять, в данном случае как раз усложняет процесс, потому что во-первых позволяет избежать исключений и просто выплевывать мусор в ответ на попытку расшифровки с неверным ключом, а во-вторых дает интересный эффект идентичного шифротекста при попытке зашифровать получившийся мусор для сравнения с эталоном.
Все в этой схеме складно, если бы не 2 больших НО. Во-первых, Refresh Token - это не какой-то рандомный мусор, который ты можешь нагенерить с помощью SecurityRandom(), это вполне себе нормальная строка которая соответствует [a-zA-Z0-9]. Во-вторых, отсутствие дополнения вынуждает тебя или использовать RT равный размеру блока (16 байт) или дополнять пришедший с сервера токен статической строкой, что сводит на нет все преимущества предложенной схемы шифрования.
В итоге, все сводится к стандартному брутфорсу, который вместо перехвата исключений будет сверять результат расшифровки с эталоном. Можно использовать например регулярное выражение, которое я написал выше или любое другое подходящее под задачу.
Чтобы быть совсем честным. Расшифровать приведенную тобой строку я конечно же не могу, по причинам описанным выше. Невозможно отличить правильный мусор от неправильного, даже будучи человеком. Поэтому способ вполне себе имеет право на жизнь для своего круга задач, но точно не для задачи безопасного хранения токенов.