Skip to content

Commit 3ef8692

Browse files
author
Jeff McCune
committed
Merge pull request #27 from glarizza/feature/master/str2saltedsha512
New str2saltedsha512 function for OS X Passwords
2 parents a0e27cd + 02e85b9 commit 3ef8692

2 files changed

Lines changed: 83 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# str2saltedsha512.rb
3+
#
4+
5+
module Puppet::Parser::Functions
6+
newfunction(:str2saltedsha512, :type => :rvalue, :doc => <<-EOS
7+
This converts a string to a salted-SHA512 password hash (which is used for
8+
OS X versions >= 10.7). Given any simple string, you will get a hex version
9+
of a salted-SHA512 password hash that can be inserted into your Puppet
10+
manifests as a valid password attribute.
11+
EOS
12+
) do |arguments|
13+
require 'digest/sha2'
14+
15+
raise(Puppet::ParseError, "str2saltedsha512(): Wrong number of arguments " +
16+
"passed (#{arguments.size} but we require 1)") if arguments.size != 1
17+
18+
password = arguments[0]
19+
20+
unless password.is_a?(String)
21+
raise(Puppet::ParseError, 'str2saltedsha512(): Requires a ' +
22+
"String argument, you passed: #{password.class}")
23+
end
24+
25+
seedint = rand(2**31 - 1)
26+
seedstring = Array(seedint).pack("L")
27+
saltedpass = Digest::SHA512.digest(seedstring + password)
28+
(seedstring + saltedpass).unpack('H*')[0]
29+
end
30+
end
31+
32+
# vim: set ts=2 sw=2 et :
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env rspec
2+
require 'spec_helper'
3+
4+
describe "the str2saltedsha512 function" do
5+
before :all do
6+
Puppet::Parser::Functions.autoloader.loadall
7+
end
8+
9+
before :each do
10+
@scope = Puppet::Parser::Scope.new
11+
end
12+
13+
it "should exist" do
14+
Puppet::Parser::Functions.function("str2saltedsha512").should == "function_str2saltedsha512"
15+
end
16+
17+
it "should raise a ParseError if there is less than 1 argument" do
18+
expect { @scope.function_str2saltedsha512([]) }.should( raise_error(Puppet::ParseError) )
19+
end
20+
21+
it "should raise a ParseError if there is more than 1 argument" do
22+
expect { @scope.function_str2saltedsha512(['foo', 'bar', 'baz']) }.should( raise_error(Puppet::ParseError) )
23+
end
24+
25+
it "should return a salted-sha512 password hash 136 characters in length" do
26+
result = @scope.function_str2saltedsha512(["password"])
27+
result.length.should(eq(136))
28+
end
29+
30+
it "should raise an error if you pass a non-string password" do
31+
expect { @scope.function_str2saltedsha512([1234]) }.should( raise_error(Puppet::ParseError) )
32+
end
33+
34+
it "should generate a valid password" do
35+
# Allow the function to generate a password based on the string 'password'
36+
password_hash = @scope.function_str2saltedsha512(["password"])
37+
38+
# Separate the Salt and Password from the Password Hash
39+
salt = password_hash[0..7]
40+
password = password_hash[8..-1]
41+
42+
# Convert the Salt and Password from Hex to Binary Data
43+
str_salt = Array(salt.lines).pack('H*')
44+
str_password = Array(password.lines).pack('H*')
45+
46+
# Combine the Binary Salt with 'password' and compare the end result
47+
saltedpass = Digest::SHA512.digest(str_salt + 'password')
48+
result = (str_salt + saltedpass).unpack('H*')[0]
49+
result.should == password_hash
50+
end
51+
end

0 commit comments

Comments
 (0)