Today I had to copy a bank account number from a real (dead tree) letter to an Emacs buffer and then send it by email. And I made a mistake while copying it from the letter to the Emacs buffer (forgot one digit). Which resulted in one email from a coworker telling me: "couldn't make the payment, bogus IBAN".
How hard would it be to create a function/minor-mode that would:
detect "things" that do look like an IBAN (for example two uppercase letters followed by between 'x' and 'y' digits, ignoring spaces etc. There are ready-to-use regexps out there that verify if something looks like an IBAN or not)
run a mod 97 and highlight the IBAN in red if it looks invalid
Ideally I'd need a minor-mode that I could turn on for several types of buffers (silly text files, but also email, etc.).
What would be the "approach" to use to do that using Emacs?
You can easily use something like
(font-lock-add-keywords nil
'(("[A-Z][A-Z][0-9]\\{x,y\\}"
(0 (if (eq (mod blabla 97) foo) nil 'font-lock-warning-face))))))
Just fill in the blabla.
Related
I understood the process to shorten the URL with base 62 at How do I create a URL shortener?.
Steps given are
Think of an alphabet we want to use. In your case, that's [a-zA-Z0-9]. It contains 62 letters.
Take an auto-generated, unique numerical key (the auto-incremented id of a MySQL table for example).
For this example, I will use 12510 (125 with a base of 10).
Now you have to convert 12510 to X62 (base 62)
My question is why not just create unique numerical key and return it ? What is the advantage of concerting numerical key > Base 62 > then Finally some alphanumeric number ?
Is it because final alphanumeric number will be much smaller than unique numerical key ?
Yes. The idea is to make it short and usable in a URL. A number in base 62 will use fewer characters than the same number in base 10. Notice also that URL shorteners use short hosts, such as g.co.
I can see you understand that, yes, a number written in base 62 takes less characters than a number in base 10 just like a number in base 10 takes less characters than a number in base 2 (e.g. 0101 is 3 characters longer than just '5').
So, I'll answer specifically "Why".
Sometimes a link is shortened to be more visually pleasing. A company worried about their public perception likely doesn't want their links to look like an error code due to how long they are so they resort to shortening. That's why some url shortening services allow you to add your own "vanity url" which customizes the domain name, so that a link can be shortened and branded.
Other times a link is shortened to minimize character count when working with constraints, like Twitter. For example, at my company we shortened the links in our automated Twilio messages because SMS messages that contain more than 160 characters are technically 2 concatenated messages so it is more expensive to send.
And finally if the link is being shared through a medium that cannot be directly clicked on (e.g. verbally, on paper), making it shorter makes it much easier to type into an address bar manually. (Imagine trying to type the url to this SO question when someone is reading it to you.) I assume this is also at least partially why the base used for these links usually stop at around 62. If you start including other arbitrary characters to higher the base and consequentially make the link marginally shorter, it'll become harder to communicate, read and type. ("domain.name/5omeC0d3" vs "domian.name/🈲}♠"
So I have a big csv file, over 1gb. There's a column with IP addresses in ipv4 and ipv6. I want to convert the ipv6 addresses into numbers, but there are too many rows for libre calc. So I'm wondering if it's possible to use python in the terminal to convert all the ipv6 addresses.
Also, I could split the file up into smaller pieces, then use libre calc, but same problem--I wouldn't know how to script that either.
EDIT:
I don't mind, it might get more complicated though. Also not sure how this should be formatted, but I hope people get the idea...So I have one table with IPv6 addresses like these examples:
2001:db8::cafe:1111
2001:db8:0:a:1:2:3:4
2001:db8:aaaa::c
2001:db8:0:0:1::4
There are a bunch of different rules that govern the formatting--way too hard for me. I've heard that python has a function that will specifically return the conversion, but not sure about the rest (how to get the returned values back into the csv correctly, with formatting unbroken, etc.). Anyway, here's a row from the other table:
"58569107296622255421594597096899477504","58569107375850417935858934690443427839","NG","Nigeria","Abuja Federal Capital Territory","Abuja","9.057350","7.489760"
So the part I need to match is the first two numbers (first two columns), where there are several ranges from
"0","340282366920938463463374607431768211455"
So I wanted to take the IPv6 addresses, convert them to IP numbers, then sort them into their respective ranges.
Yes, this is something you can do in Python. I'll demonstrate with a few short snippets and links to documentation that will fall short of a full solution in favor of empowering you with the resources that you need to put the pieces together yourself.
First off, if you want to load one CSV file line-by-line and write to a second one this is how you would do it:
>>> import csv
>>> with open('eggs.csv', newline='') as in and open('omellette.csv', 'w') as out:
... r = csv.reader(in)
... w = csv.writer(out)
... for row in r:
... print(', '.join(row)) # print unmodified
... row[0] = ipToNum(row[0])
... row[1] = ipToNum(row[1])
... print(', '.join(row)) # print modified
... w.writerow(row)
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam
The original on which this example was based and additional information about python's built-in CSV capabilities can be found here:
https://docs.python.org/3/library/csv.html
You will probably need to make adjustments depending on the exact formatting of your particular CSV file. Now, to convert IP addresses to numbers you can do something like the following:
import socket, struct
def ipToNum(ip):
"convert ipv4/6 string to long integer"
return struct.unpack('>L',socket.inet_pton(ip))[0]
def numToDottedip(n):
"convert long int to ipv4/6"
return socket.inet_ntop(struct.pack('>L',n))
This example is adapted from what I found here:
https://www.oreilly.com/library/view/python-cookbook/0596001673/ch10s06.html
You will have to modify it
Also, if you want to learn more about the socket and struct modules here is the documentation:
https://docs.python.org/3/library/socket.html
https://docs.python.org/3/library/struct.html
You shouldn't need to split the file up since the CSV reader object will only return one line at a time rather than reading in the whole file at once. Of course, you also probably want to actually do something with those numbers once you've read them in but since you didn't specify I'll figuring that out to you.
Also note that I haven't tried any of this code. It's worth repeating here in the form of a metaphor: I'm trying to teach you to fish rather than just giving you fish. It's in your best interest to take this advice and wrestle with getting it to work yourself as that would be your first step toward actually being a programmer.
Recently have been looking at crypto currencies, mostly Bitcoin and Dogecoin. I'm using this source for my project. I've got Bitcoin to work perfectly, and since the Bitcoin gem did not have native support for Dogecoin I had to self-implement it.
Also noticed that another githubber had opened tried to implement dogecoin support, which as of now did not generating address correctly.
The problem seems to be in this particular line. (corresponding to the format of the crypto address)
:address_version => "30"
:address_version = PUBKEY_ADDRESS in base58.h
base58.h
PUBKEY_ADRESS contains value 30.
Specifying this particular number will give address beginning with letter 'L' (litecoin address), where Dogecoin requires 'D'.
Does this have anything to do with Doge using scrypt, I have no technical expertise in this field. How do I go about generating dogecoin pubkey/private key pair?
30 in decimal will give you a address begins with a letter D
30 in hexadecimal (48 in decimal) will give you a address begins with letter L
I think that bitcoin-ruby first changes PUBKEY_ADDRESS from hexa to decimal so :address_version should be 1E (30 in decimal)
I'm looking for one or more encryption algorithms that can encrypt passwords in a way that the encrypted text must be readable by humans.
For example if I give as password:
StackOverflow
The algorithm should gives me:
G0aThiR4i s0ieFer
So I want to get an encrypted password easily readable by humans (not strange strings with special chars or thousand of characters).
There are algorithms that fit this need?
RFC 1751, which defines a "Convention for Human-Readable 128-bit Keys" – basically just a mapping of blocks of bits to strings of English words.
For example, the 128-bit key of:
CCAC 2AED 5910 56BE 4F90 FD44 1C53 4766
would become
RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE
Algorithm is used for fixed-length 128-bit keys, that's a base for data size. Source data can be truncated or expanded to match the base.
Spec & implementation in C # https://www.rfc-editor.org/rfc/rfc1751
It ain't well known. I couldn't find implementation mention apart from one in spec & references to lost python library.
Your question puzzled me in many ways, leading to the hare-brained idea of creating a completely human-readable paragraph from a base 16 hash result. What's more readable than English sentences?
To maintain the security of a hashed password, the algorithm is as follows:
Hash a user's password using any of the basic techniques.
Run the hash through my special HashViewer
Enjoy the Anglicized goodness.
For example, if this Base16 hash is the input:
c0143d440bd61b33a65bfa31ac35fe525f7b625f10cd53b7cac8824d02b61dfc
the output from HashViewer would be this:
Smogs enjoy dogs. Logs unearth backlogs. Logs devour frogs. Grogs decapitate clogs and dogs conceptualize fogs. Fogs greet clogs. Cogs conceptualize warthogs. Bogs unearth dogs despite bogs squeeze fogs. Cogs patronize catalogs. Cogs juggle cogs. Warthogs debilitate grogs; unfortunately, clogs juggle cogs. Warthogs detest frogs; conversely, smogs decapitate cogs. Fogs conceptualize balrogs. Smogs greet smogs whenever polywogs accost eggnogs. Logs decapitate frogs. Eggnogs conceptualize clogs. Dogs decapitate warthogs. (smogs )
(The last words in parenthesis were words that were left over)
In this glorious paragraph form, we can look at two separate hashes and easily compare them to see if they are different.
As an extra feature, there is a function to convert the English text back in to the hash string.
Enjoy!
Step 1) Apply regular encryption algorithm.
Step 2) Base 26-encode it using letters a thru z
Step 3) ???
Step 4) Profit!
Even cooler would be to get a letter-bigraph distribution for the english language. Pick a simple pseudo-random-number algorithm and seed it with the non-human-readable password hash. Then use the algorithm to make up a word according to how likely a letter is to follow the letter before it in the english language. You'll get really english-sounding words, and consistently from the same seed. The chance for collisions might be unseasonably high, though.
EncryptedPassword = Base64(SHA1(UTF8(Password) + Salt))
Password is string
Salt is cryptographically strong random byte[]
UTF8: string -> byte[]
SHA1: byte[] -> byte[]
Base64: byte[] -> string
EncryptedPassword is string
Store (EncryptedPassword, Salt).
Throw in whatever encryption algorithm you want instead of SHA1.
For example, if password is StackOverflow you get the encrypted password LlijGz/xNSRXQXtbgNs+UIdOCwU.
I'm trying to generate UUIDs with the same style as bit.ly urls like:
http://bit [dot] ly/aUekJP
or cloudapp ones:
http://cl [dot] ly/1hVU
which are even smaller
how can I do it?
I'm now using UUID gem for ruby but I'm not sure if it's possible to limitate the length and get something like this.
I am currently using this:
UUID.generate.split("-")[0] => b9386070
But I would like to have even smaller and knowing that it will be unique.
Any help would be pretty much appreciated :)
edit note: replaced dot letters with [dot] for workaround of banned short link
You are confusing two different things here. A UUID is a universally unique identifier. It has a very high probability of being unique even if millions of them were being created all over the world at the same time. It is generally displayed as a 36 digit string. You can not chop off the first 8 characters and expect it to be unique.
Bitly, tinyurl et-al store links and generate a short code to represent that link. They do not reconstruct the URL from the code they look it up in a data-store and return the corresponding URL. These are not UUIDS.
Without knowing your application it is hard to advise on what method you should use, however you could store whatever you are pointing at in a data-store with a numeric key and then rebase the key to base32 using the 10 digits and 22 lowercase letters, perhaps avoiding the obvious typo problems like 'o' 'i' 'l' etc
EDIT
On further investigation there is a Ruby base32 gem available that implements Douglas Crockford's Base 32 implementation
A 5 character Base32 string can represent over 33 million integers and a 6 digit string over a billion.
If you are working with numbers, you can use the built in ruby methods
6175601989.to_s(30)
=> "8e45ttj"
to go back
"8e45ttj".to_i(30)
=>6175601989
So you don't have to store anything, you can always decode an incoming short_code.
This works ok for proof of concept, but you aren't able to avoid ambiguous characters like: 1lji0o. If you are just looking to use the code to obfuscate database record IDs, this will work fine. In general, short codes are supposed to be easy to remember and transfer from one medium to another, like reading it on someone's presentation slide, or hearing it over the phone. If you need to avoid characters that are hard to read or hard to 'hear', you might need to switch to a process where you generate an acceptable code, and store it.
I found this to be short and reliable:
def create_uuid(prefix=nil)
time = (Time.now.to_f * 10_000_000).to_i
jitter = rand(10_000_000)
key = "#{jitter}#{time}".to_i.to_s(36)
[prefix, key].compact.join('_')
end
This spits out unique keys that look like this: '3qaishe3gpp07w2m'
Reduce the 'jitter' size to reduce the key size.
Caveat:
This is not guaranteed unique (use SecureRandom.uuid for that), but it is highly reliable:
10_000_000.times.map {create_uuid}.uniq.length == 10_000_000
The only way to guarantee uniqueness is to keep a global count and increment it for each use: 0000, 0001, etc.