rot13 also takes quite a lot of processing power, especially now that Unicode is a thing. Better just take the input as raw binary stream and xor it against a fixed value. You can write the whole thing in like a dozen or so assembly instructions.
In the same loop you can compare your password to the expected one as well, no need for a wasteful second loop.
It's been a few decades since i've done some assembly coding, but something like this should probably do it:
USERINPUT = $1000
PASSWORD = $2000
ldx $0; counter/offset
lda USERINPUT,x ; if null byte, check done and password ok
eor #$aa; XOR with constant
sbc PASSWORD,x ; substract byte of password
bne wrongpassword ; invalid byte
inx ; increment offset
jmp loop ; work on next byte
Edit: Ooops. By accidentally using the zero byte termination of the user input instead of the stored password, i seem to have recreated a rather classic exploit. In this, the user determines how many bytes are checked. If the user simply presses enter at the password prompt, the number of checked bytes is a staggering "none at all", which bypasses the check completely.
If i just swap USERINPUT and PASSWORD around, the check still works thanks to our totally secure XOR method. But there is STILL a problem, because now the thing only checks the number of bytes in PASSWORD, ignoring any additional bytes the user has typed in. So if the password is the letter "p", anything beginning with that letter (like "password1" or "perlmonks") will be accepted as valid. On the bright side, we not only saved a few assembly instructions, the algorithm is extremely fast.
On the other upside, if we use the code as posted, we can potentially byte-by-byte read out parts of the program memory by adding additional bytes to the user input and see if the the password still matches. It's because the thing will keep reading beyond the end of the stored password string and comparing it to the user input. Now, we can't submit a Zero-byte, because that would end the check, but if we excluded all other possible values for this byte we know it is a zero anyway. It would still end our memory exploration because we can't validate any more bytes, so it's a game of luck. Still, we need (at maximum) 255 tries per byte...
perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'