Naturally, Every public variable of contract is accessible by it's auto-generated getter function from outside. Every private variable is only accessible inside the contract and if you want to access the private variable from outside the contract you need to write a getter function.
Contract does not have any private key because contract is a programming code which execute the logic which we have coded and run's on EVM which is already secured.
Although if you are developer and can understand the memory lookup you can read the private variables also. There is a way to lookup the private variables by investigation into transaction which change the state.
E.g. to modify a private variable in the contract you need to pass the "private" value while calling the function which changes the value of private variable.
But all the function parameters (transaction data) is visible to every node so you can easily read the private variables if you know the transaction.
For every function call the transaction have 2 fields
- function selector
- function parameter
e.g. this is an transaction
0x6587f6ec0000000000000000000000000000000000000000000000000000000000000064
in this, first 4 bytes are function selector 0x6587f6ec
and other fields are showing parameter value in hex
0x0000000000000000000000000000000000000000000000000000000000000064
which is equal to 100. Value of private variable.
You can check more details in here.