To do a rough check on a Monero standard wallet address (not an integrated address), verify that it is 95 characters long, check it starts with a 4 (standard wallet address) or an 8 (subaddress) and that it only contains valid Base58 characters. The definition of Base58 allowed characters is "mixed-case alphanumeric, except the following similar-looking letters are omitted: 0 (zero), O (capital o), I (capital i) and l (lower case L)".
To do a rough check on a Monero integrated address, the procedure is the same as above except you'd verify that it is 106 characters long instead of 95 characters. It will still start with a 4.
To fully validate a Monero standard address or subaddress, you need to split it apart and verify the checksum. To split it apart, you need to perform a base58 decoding, taking care to note that Monero's base58 implementation is different to that of Bitcoin. Let's call that decoded result
W. The first byte of
W is the address type, which you should make sure is either
0x12 (standard) or
0x2A (subaddress). Then you need to check that the first 4 bytes of the keccak-256 hash of the first 65 bytes of
W match the last 4 bytes of
W. The technical details are here: What are the "public" viewkeys and spendkeys?
To fully validate a Monero integrated address, the procedure is the same as above except when you base58 decode it to get
W, check that the first byte is
0x13. Then you'll check that the first 4 bytes of the keccak-256 hash of the first 73 bytes of
W is equal to the last 4 bytes of
There is a 1 in 4.3 billion chance that the address will pass the checksum test if it is corrupted. If you want to be insanely thorough (perhaps because you'd written your own code to generate addresses and wanted to check you were generating them correctly), you could check that the compressed EC points in the address are valid. To do this, after reading the first byte of
W, you'd then read two groups of 32 bytes as EC points. Then you'd attempt to decode each point using a library that would alert you to badly formed points. Random bytes would be valid Ed25519 points 50% of the time. After that, you'd verify that the curve points are in the group of the Ed25519 base point G. To do this, you'd scalar multiply each EC point by
2^252 + 27742317777372353535851937790883648493 and verify that the resulting EC point hex is the identity point
0100000000000000000000000000000000000000000000000000000000000000. There would only be a 1 in 16 chance that random bytes would pass this test (i.e. 1 in 2 chance it would be an Ed25519 point at all, and then only a 1 in 8 chance it'd be in the base point group).