-
Notifications
You must be signed in to change notification settings - Fork 1
Parsing X509 IpAddressName #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
StjepanovicSrdjan
merged 7 commits into
development
from
feature/x509-ipaddressname-parsing
Sep 26, 2025
Merged
Changes from 4 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
a69b3e1
add methods for encodin/decoding ipaddressName octets
StjepanovicSrdjan 824229f
add tests
StjepanovicSrdjan 328bd5d
polishing
StjepanovicSrdjan 66b61dc
update cidre api
StjepanovicSrdjan 0d12dcb
extracted x509Octets parsing logic into IpAddressAndPrefix
StjepanovicSrdjan 26225ab
update changelog
StjepanovicSrdjan 1fcf3eb
polishing apidocs
StjepanovicSrdjan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ import at.asitplus.cidre.byteops.CidrNumber | |
| import at.asitplus.cidre.byteops.and | ||
| import at.asitplus.cidre.byteops.or | ||
| import at.asitplus.cidre.byteops.toNetmask | ||
| import at.asitplus.cidre.byteops.toPrefix | ||
|
|
||
|
|
||
| sealed class IpNetwork<N : Number, S : CidrNumber<S>> | ||
|
|
@@ -210,6 +211,11 @@ constructor(address: IpAddress<N, S>, override val prefix: Prefix, strict: Boole | |
| return address.octets contentEquals (network.address.octets and netmask) | ||
| } | ||
|
|
||
| /** | ||
| * Encodes this network into X.509 iPAddressName ByteArray (RFC 5280). | ||
| */ | ||
| fun toX509Octets(): ByteArray = address.octets + netmask | ||
|
|
||
| override fun equals(other: Any?): Boolean { | ||
| if (this === other) return true | ||
| if (other !is IpNetwork<*, *>) return false | ||
|
|
@@ -528,6 +534,29 @@ constructor(address: IpAddress<N, S>, override val prefix: Prefix, strict: Boole | |
| ) as IpNetwork<N, S> | ||
| } | ||
|
|
||
| /** | ||
| * Decodes an IpNetwork from X.509 iPAddressName ByteArray (RFC 5280). | ||
JesusMcCloud marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * 8 bytes (IPv4 base+mask) | ||
| * 32 bytes (IPv6 base+mask) | ||
| */ | ||
| @Throws(IllegalArgumentException::class) | ||
| fun fromX509Octets(bytes: ByteArray, strict: Boolean = false): IpNetwork<*, *> { | ||
| return when (bytes.size) { | ||
| 8 -> { | ||
|
||
| val address = bytes.copyOfRange(0, 4) | ||
| val mask = bytes.copyOfRange(4, 8) | ||
| val prefix = mask.toPrefix() | ||
| V4(IpAddress.V4(address), prefix, strict = strict) | ||
| } | ||
| 32 -> { | ||
| val address = bytes.copyOfRange(0, 16) | ||
| val mask = bytes.copyOfRange(16, 32) | ||
| val prefix = mask.toPrefix() | ||
| V6(IpAddress.V6(address), prefix, strict = strict) | ||
| } | ||
| else -> throw IllegalArgumentException("Invalid iPAddress length: ${bytes.size}") | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| import at.asitplus.cidre.IpNetwork | ||
| import kotlin.reflect.KClass | ||
| import kotlin.test.Test | ||
| import kotlin.test.assertContentEquals | ||
| import kotlin.test.assertEquals | ||
| import kotlin.test.assertTrue | ||
|
|
||
| class IpAddressNameParsingTest { | ||
|
|
||
| // IPv4 raw bytes | ||
| private val ipv4WithMask1 = byteArrayOf(0x0a, 0x09, 0x08, 0x00, 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0x00) | ||
| private val ipv4WithMask2 = byteArrayOf(0x0a, 0x09, 0x00, 0x00, 0xff.toByte(), 0xff.toByte(), 0x80.toByte(), 0x00) | ||
| private val ipv4WithMask3 = byteArrayOf(0x0a, 0x09, 0x00, 0x00, 0xff.toByte(), 0xff.toByte(), 0xc0.toByte(), 0x00) | ||
|
|
||
| private val ipv4WithMask1Str = "10.9.8.0/24" | ||
| private val ipv4WithMask2Str = "10.9.0.0/17" | ||
| private val ipv4WithMask3Str = "10.9.0.0/18" | ||
|
|
||
| // IPv6 raw bytes | ||
| private val ipv6a = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x8a.toByte(), 0x2e, 0x0a, 0x09, 0x08, 0x00, | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
| private val ipv6aMasked = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
|
|
||
| private val ipv6b = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x8a.toByte(), 0x2e, 0x0a, 0x09, 0x08, 0x00, | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte() | ||
| ) | ||
|
|
||
| private val ipv6c = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
|
|
||
| private val ipv6d = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xfe.toByte(), | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
| private val ipv6dMasked = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa2.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xfe.toByte(), | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
|
|
||
| private val ipv6e = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0x80.toByte(), 0x00, 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
| private val ipv6eMasked = byteArrayOf( | ||
| 0x20, 0x01, 0x0d, 0xb8.toByte(), 0x85.toByte(), 0xa3.toByte(), 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), 0xff.toByte(), | ||
| 0xff.toByte(), 0xff.toByte(), 0x80.toByte(), 0x00, 0x00, 0x00, | ||
| 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| ) | ||
|
|
||
| private val ipv6aStr = "2001:db8:85a3::/48" | ||
| private val ipv6bStr = "2001:db8:85a3::8a2e:a09:800/128" | ||
| private val ipv6cStr = "2001:db8:85a3::/48" | ||
| private val ipv6dStr = "2001:db8:85a2::/47" | ||
| private val ipv6eStr = "2001:db8:85a3::/49" | ||
|
|
||
| @Test fun parseIPv6a() = parseCheck(ipv6a, IpNetwork.V6::class, ipv6aStr, ipv6aMasked) | ||
| @Test fun parseIPv6b() = parseCheck(ipv6b, IpNetwork.V6::class, ipv6bStr) | ||
| @Test fun parseIPv6c() = parseCheck(ipv6c, IpNetwork.V6::class, ipv6cStr) | ||
| @Test fun parseIPv6d() = parseCheck(ipv6d, IpNetwork.V6::class, ipv6dStr, ipv6dMasked) | ||
| @Test fun parseIPv6e() = parseCheck(ipv6e, IpNetwork.V6::class, ipv6eStr, ipv6eMasked) | ||
|
|
||
| @Test fun parseIPv4mask24() = parseCheck(ipv4WithMask1, IpNetwork.V4::class, ipv4WithMask1Str) | ||
| @Test fun parseIPv4mask17() = parseCheck(ipv4WithMask2, IpNetwork.V4::class, ipv4WithMask2Str) | ||
| @Test fun parseIPv4mask18() = parseCheck(ipv4WithMask3, IpNetwork.V4::class, ipv4WithMask3Str) | ||
|
|
||
| private fun parseCheck(bytes: ByteArray, expectedType: KClass<out IpNetwork<*, *>>, expectedString: String, expectedBytes: ByteArray? = null) { | ||
| val network = IpNetwork.fromX509Octets(bytes, false) | ||
| assertTrue(expectedType.isInstance(network), "Expected type: $expectedType, but got ${network::class}") | ||
| assertContentEquals(expectedBytes ?: bytes, network.toX509Octets()) | ||
| assertEquals(expectedString, network.toString()) | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
illustrate the byte layout in the API Doc