Além do fato de que sua função de hashing não é muito boa * , o maior problema com seu código não é que ele retorna um número diferente dependendo da versão do .NET, mas que em ambos os casos ele retorna um número totalmente sem sentido: a resposta correta para o problema é
49 103 mod 143 = é 114. ( link para Wolfram Alpha )
Você pode usar este código para calcular esta resposta:
private static int PowMod(int a, int b, int mod) {
if (b == 0) {
return 1;
}
var tmp = PowMod(a, b/2, mod);
tmp *= tmp;
if (b%2 != 0) {
tmp *= a;
}
return tmp%mod;
}
A razão pela qual seu cálculo produz um resultado diferente é que, para produzir uma resposta, você usa um valor intermediário que elimina a maioria dos dígitos significativos do número 49 103 : apenas os primeiros 16 de seus 175 dígitos estão corretos!
1230824813134842807283798520430636310264067713738977819859474030746648511411697029659004340261471771152928833391663821316264359104254030819694748088798262075483562075061997649
Os 159 dígitos restantes estão todos errados. A operação mod, no entanto, busca um resultado que exija que cada dígito esteja correto, incluindo os últimos. Portanto, mesmo a menor melhoria na precisão do Math.Pow
que pode ter sido implementado no .NET 4, resultaria em uma diferença drástica do seu cálculo, o que essencialmente produz um resultado arbitrário.
* Uma vez que esta questão fala sobre elevar inteiros a altas potências no contexto de hashing de senha, pode ser uma boa ideia ler este link de resposta antes de decidir se sua abordagem atual deve ser alterada por uma potencialmente melhor.