// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: MIT // The n-fold of RFC 3961 appendix A, ported from the reference // implementation of MIT krb5: the input is cycled through the least // common multiple of the input and output byte lengths, and the // repetitions summed with end-around carry. package krb5 // NFold stretches in to outBytes octets with every input bit weighted // equally into every output bit. func NFold(in []byte, outBytes int) []byte { inBytes := len(in) a, b := outBytes, inBytes for b != 0 { a, b = b, a%b } lcm := outBytes * inBytes / a out := make([]byte, outBytes) carry := 0 for i := lcm - 1; i >= 0; i-- { msbit := ((inBytes << 3) - 1 + ((inBytes<<3)+13)*(i/inBytes) + ((inBytes - i%inBytes) << 3)) % (inBytes << 3) hi := (inBytes - 1 - (msbit >> 3)) % inBytes lo := (inBytes - (msbit >> 3)) % inBytes carry += int(((uint16(in[hi])<<8 | uint16(in[lo])) >> uint((msbit&7)+1)) & 0xff) carry += int(out[i%outBytes]) out[i%outBytes] = byte(carry) carry >>= 8 } if carry != 0 { for i := outBytes - 1; i >= 0; i-- { carry += int(out[i]) out[i] = byte(carry) carry >>= 8 } } return out }