Search code examples
scalaipv6bigintegerinetaddress

How to convert IPv6 Addresses to and from BigInteger in Scala


Looking to convert IPv6 Strings (such as 2001:0:4137:9e76:34b7:2e31:3f57:fd9a) to BigInteger and from BigInteger to IPv6 Strings.


Solution

  • import java.math.BigInteger
    import java.net.InetAddress
    import java.net.Inet6Address
    def ipv6ToBigInteger(ipv6 : String) : BigInteger = {
        val ia = InetAddress.getByName(ipv6)
        val byteArr : Array[Byte] = ia.getAddress()
        var ipNumber = new BigInteger("0")
        if (ia.isInstanceOf[Inet6Address]) {
            ipNumber = new BigInteger(1, byteArr)
        }
        return ipNumber
    }
    
    def bigIntegerToIPv6(ipv6Num : BigInteger) : String = {
        val ipv6Str = InetAddress.getByAddress(ipv6Num.toByteArray).toString()
        return ipv6Str.replaceFirst("/", "")
    }
    
    val ipv6 = "2001:0:4137:9e76:34b7:2e31:3f57:fd9a"
    val ipv6Num = ipv6ToBigInteger(ipv6) // ipv6Num: java.math.BigInteger = 42540488182159607633435240198452018586
    val ipv6Str = bigIntegerToIPv6(ipv6Num) // ipv6Str: String = 2001:0:4137:9e76:34b7:2e31:3f57:fd9a
    ipv6 == ipv6Str // res0: Boolean = true
    

    UPDATE EDIT:

    Per a suggested edit from an anonymous user:

    "Comment: InetAddress.getByAddress requires a 16-byte array in order to parse an IPv6 address (4-byte array for IPv4). As it was, the code failed for any value that did not result in a 16-byte array when .toByteArray was called on it"

    def bigIntToFixedSizeByteArray(n: BigInteger, size: Int = 16): Array[Byte] = {
        val a = n.toByteArray
        val leadingLength = math.max(size - a.length, 0)
        Array.ofDim[Byte](leadingLength) ++ a
    }
    
    def bigIntegerToIPv6(ipv6Num : BigInteger) : String = {
        val address = InetAddress.getByAddress(bigIntToFixedSizeByteArray(ipv6Num))  
        address.toString.replaceFirst("/", "")
    }